Skip to content

Commit

Permalink
Add property slotcache
Browse files Browse the repository at this point in the history
  • Loading branch information
svaarala committed Jan 15, 2017
1 parent c0f4a91 commit adbbeb1
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src-input/duk_forwdecl.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct duk_breakpoint;
struct duk_activation;
struct duk_catcher;
struct duk_strcache;
struct duk_slotcache_entry;
struct duk_ljstate;
struct duk_strtab_entry;

Expand Down Expand Up @@ -97,6 +98,7 @@ typedef struct duk_breakpoint duk_breakpoint;
typedef struct duk_activation duk_activation;
typedef struct duk_catcher duk_catcher;
typedef struct duk_strcache duk_strcache;
typedef struct duk_slotcache_entry duk_slotcache_entry;
typedef struct duk_ljstate duk_ljstate;
typedef struct duk_strtab_entry duk_strtab_entry;

Expand Down
22 changes: 22 additions & 0 deletions src-input/duk_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@
#define DUK_HEAP_STRCACHE_SIZE 4
#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */

/* Slotcache is used to speeding up object property lookups without
* caching a property value.
*/
#define DUK_HEAP_SLOTCACHE_SIZE 8192

/* helper to insert a (non-string) heap object into heap allocated list */
#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap),(hdr))

Expand Down Expand Up @@ -293,6 +298,15 @@ struct duk_strcache {
duk_uint32_t cidx;
};

/*
* Property slot cache. Best effort data structure to cache property
* table slots for recently accessed object/key combinations.
*/

struct duk_slotcache_entry {
duk_uint8_t slot;
};

/*
* Longjmp state, contains the information needed to perform a longjmp.
* Longjmp related values are written to value1, value2, and iserror.
Expand Down Expand Up @@ -461,6 +475,11 @@ struct duk_heap {
*/
duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];

/* property slot cache, global structure for speeding up commonly
* referenced property access.
*/
duk_slotcache_entry slotcache[DUK_HEAP_SLOTCACHE_SIZE];

/* built-in strings */
#if defined(DUK_USE_ROM_STRINGS)
/* No field needed when strings are in ROM. */
Expand Down Expand Up @@ -514,6 +533,9 @@ DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);

DUK_INTERNAL_DECL duk_uint32_t duk_heap_slotcache_lookup(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
DUK_INTERNAL_DECL void duk_heap_slotcache_insert(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint32_t slot);

#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
Expand Down
7 changes: 7 additions & 0 deletions src-input/duk_heap_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ DUK_LOCAL void duk__dump_type_sizes(void) {
DUK__DUMPSZ(duk_activation);
DUK__DUMPSZ(duk_catcher);
DUK__DUMPSZ(duk_strcache);
DUK__DUMPSZ(duk_slotcache_entry);
DUK__DUMPSZ(duk_ljstate);
DUK__DUMPSZ(duk_fixedbuffer);
DUK__DUMPSZ(duk_bitdecoder_ctx);
Expand Down Expand Up @@ -924,6 +925,12 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
}
#endif

/*
* Init slotcache
*/

/* Nothing to init now. */

/* XXX: error handling is incomplete. It would be cleanest if
* there was a setjmp catchpoint, so that all init code could
* freely throw errors. If that were the case, the return code
Expand Down
34 changes: 34 additions & 0 deletions src-input/duk_heap_slotcache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Object property table slot cache.
*/

#include "duk_internal.h"

DUK_INTERNAL duk_uint32_t duk_heap_slotcache_lookup(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
duk_uint32_t idx;
duk_slotcache_entry *ent;

DUK_ASSERT(heap != NULL);
DUK_ASSERT(obj != NULL);
DUK_ASSERT(key != NULL);

/* FIXME: assert: hashlimit <= 256 */

idx = ((duk_uint32_t) obj) ^ DUK_HSTRING_GET_HASH(key);
ent = heap->slotcache + (idx & (DUK_HEAP_SLOTCACHE_SIZE - 1));
return ent->slot;
}

DUK_INTERNAL void duk_heap_slotcache_insert(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint32_t slot) {
duk_uint32_t idx;
duk_slotcache_entry *ent;

/* FIXME: assert: hashlimit <= 256 */
/* FIXME: skip check if hash part present and hashlimit correct */
if (DUK_UNLIKELY(slot >= DUK_UINT16_MAX)) {
return;
}
idx = ((duk_uint32_t) obj) ^ DUK_HSTRING_GET_HASH(key);
ent = heap->slotcache + (idx & (DUK_HEAP_SLOTCACHE_SIZE - 1));
ent->slot = (duk_uint16_t) slot;
}
14 changes: 14 additions & 0 deletions src-input/duk_hobject_props.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,8 @@ DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
*/

DUK_INTERNAL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
duk_uint32_t slot;

DUK_ASSERT(obj != NULL);
DUK_ASSERT(key != NULL);
DUK_ASSERT(e_idx != NULL);
Expand All @@ -1177,10 +1179,22 @@ DUK_INTERNAL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *o
duk_hstring **h_keys_base;
DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));

slot = duk_heap_slotcache_lookup(heap, obj, key);
if (slot < DUK_HOBJECT_GET_ENEXT(obj)) {
if (DUK_HOBJECT_E_GET_KEY(heap, obj, slot) == key) {
DUK_D(DUK_DPRINT("slot cache hit: %p %p -> %ld", (void *) obj, (void *) key, (long) slot));
*e_idx = slot;
*h_idx = -1;
return;
}
}

h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
n = DUK_HOBJECT_GET_ENEXT(obj);
for (i = 0; i < n; i++) {
if (h_keys_base[i] == key) {
DUK_D(DUK_DPRINT("slot cache insert: %p %p -> %ld", (void *) obj, (void *) key, (long) i));
duk_heap_slotcache_insert(heap, obj, key, i);
*e_idx = i;
*h_idx = -1;
return;
Expand Down

0 comments on commit adbbeb1

Please sign in to comment.