Skip to content

Commit

Permalink
Prototype with propcache storage caching
Browse files Browse the repository at this point in the history
  • Loading branch information
svaarala committed Feb 12, 2017
1 parent 65ae169 commit 7c60b28
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src-input/duk_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ struct duk_propcache_entry {
/* All references are borrowed. */
duk_hobject *obj_lookup;
duk_hstring *key_lookup;
duk_tval value;
duk_tval *val_storage;
duk_uint32_t generation;
};

Expand Down
10 changes: 8 additions & 2 deletions src-input/duk_heap_propcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ DUK_LOCAL DUK_NOINLINE void duk__propcache_scrub(duk_heap *heap) {
* to zero, and the generation count is then bumped once more
* to one to invalidate the scrubbed entries.
*/
DUK_D(DUK_DPRINT("INVALIDATE propcache"));
DUK_MEMZERO((void *) heap->propcache, sizeof(heap->propcache));
heap->propcache_generation++;
}
Expand Down Expand Up @@ -33,10 +34,15 @@ DUK_INTERNAL duk_tval *duk_propcache_lookup(duk_hthread *thr, duk_hobject *obj,
prophash = duk__compute_prophash(obj, key);
ent = thr->heap->propcache + prophash;

DUK_D(DUK_DPRINT("lookup, prophash %lu, gen %lu, ent->gen %lu, ent->obj %p, ent->key %p, ent->val %p",
(unsigned long) prophash, (unsigned long) thr->heap->propcache_generation,
(unsigned long) ent->generation, (void *) ent->obj_lookup,
(void *) ent->key_lookup, (void *) ent->val_storage));

if (ent->generation == thr->heap->propcache_generation &&
ent->obj_lookup == obj &&
ent->key_lookup == key) {
return &ent->value;
return ent->val_storage; /* Storage location. */
}

return NULL;
Expand All @@ -51,5 +57,5 @@ DUK_INTERNAL void duk_propcache_insert(duk_hthread *thr, duk_hobject *obj, duk_h
ent->generation = thr->heap->propcache_generation;
ent->obj_lookup = obj;
ent->key_lookup = key;
DUK_TVAL_SET_TVAL(&ent->value, tv);
ent->val_storage = tv;
}
53 changes: 49 additions & 4 deletions src-input/duk_hobject_props.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,9 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

/* Invalidate property cache. FIXME: also at the end? */
duk_propcache_invalidate(thr);

/*
* Pre resize assertions.
*/
Expand Down Expand Up @@ -2668,10 +2671,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
*/
duk_tval *storage;
storage = duk_propcache_lookup(thr, curr, key);
DUK_D(DUK_DPRINT("propcache GETPROP lookup: %!O %!O -> %p", orig_base, key, (void *) storage));
if (storage) {
DUK_D(DUK_DPRINT("cached lookup %!O -> %!T", key, storage));
duk_pop(ctx);
DUK_D(DUK_DPRINT("cached GETPROP lookup %!O -> %!T", key, storage));
duk_push_tval(ctx, storage);
duk_remove(ctx, -2); /* FIXME: careful with order */
/* FIXME: assume no post process? */
return 1;
}
Expand Down Expand Up @@ -2802,9 +2806,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
}
#endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */

if (orig_base && arr_idx == DUK__NO_ARRAY_INDEX) { /* FIXME: condition */
if (orig_base && arr_idx == DUK__NO_ARRAY_INDEX && desc.e_idx >= 0) { /* FIXME: condition */
/* FIXME: other conditions, e.g. not a getter */
duk_propcache_insert(thr, orig_base, key, DUK_GET_TVAL_NEGIDX(ctx, -1));
/* FIXME: note that caching is based on orig_base, but storage location is in 'curr'! */
duk_tval *tv_storage;
tv_storage = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, curr, desc.e_idx);
DUK_D(DUK_DPRINT("insert propcache GETPROP %!O", key));
duk_propcache_insert(thr, orig_base, key, tv_storage);
}

duk_remove_m2(ctx); /* [key result] -> [result] */
Expand Down Expand Up @@ -3338,6 +3346,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
duk_tval tv_key_copy;
duk_tval tv_val_copy;
duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
duk_hobject *orig_base;
duk_hobject *curr;
duk_hstring *key = NULL;
duk_propdesc desc;
Expand All @@ -3362,7 +3371,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,

DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

/* FIXME... with storage location caching, only need to invalidate
* if new properties are established (may shadow existing chains)?
*/
#if 0
duk_propcache_invalidate(thr);
#endif

/*
* Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
Expand Down Expand Up @@ -3664,6 +3678,23 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,

lookup:

DUK_ASSERT(curr != NULL);
orig_base = curr;

{
/* FIXME: when base is primitive, we cache the "wrong" property,
* which is fine.
*/
duk_tval *storage;
storage = duk_propcache_lookup(thr, orig_base, key);
DUK_D(DUK_DPRINT("propcache PUTPROP lookup: %!O %!O -> %p", orig_base, key, (void *) storage));
if (storage) {
DUK_D(DUK_DPRINT("cached PUTPROP lookup %!O -> old value %!T", key, storage));
DUK_TVAL_SET_TVAL_UPDREF(thr, storage, tv_val);
goto success_no_arguments_exotic;
}
}

/*
* Check whether the property already exists in the prototype chain.
* Note that the actual write goes into the original base object
Expand Down Expand Up @@ -3888,6 +3919,14 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,

if (desc.e_idx >= 0) {
tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);

/* FIXME argument exotic condition... */
if (1) { /* FIXME: condition */
/* FIXME: other conditions, e.g. not a getter */
DUK_D(DUK_DPRINT("insert propcache PUTPROP %!O", key));
duk_propcache_insert(thr, orig_base, key, tv);
}

DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; e_idx may be invalidated */
/* don't touch property attributes or hash part */
Expand Down Expand Up @@ -4090,6 +4129,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,

write_to_entry_part:

/* Must invalidate: new property may affect existing inheritance
* chains.
*/
duk_propcache_invalidate(thr);


/*
* Write to entry part
*/
Expand Down

0 comments on commit 7c60b28

Please sign in to comment.