static void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) { duk_uint_fast32_t i; DUK_ASSERT(h); DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT); /* XXX: better to get base and walk forwards? */ for (i = 0; i < (duk_uint_fast32_t) h->e_next; i++) { duk_hstring *key = DUK_HOBJECT_E_GET_KEY(h, i); if (!key) { continue; } duk_heap_heaphdr_decref(thr, (duk_heaphdr *) key); if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(h, i)) { duk_heap_heaphdr_decref(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_GETTER(h, i)); duk_heap_heaphdr_decref(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_SETTER(h, i)); } else { duk_heap_tval_decref(thr, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(h, i)); } } for (i = 0; i < (duk_uint_fast32_t) h->a_size; i++) { duk_heap_tval_decref(thr, DUK_HOBJECT_A_GET_VALUE_PTR(h, i)); } /* hash part is a 'weak reference' and does not contribute */ duk_heap_heaphdr_decref(thr, (duk_heaphdr *) h->prototype); if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) { duk_hcompiledfunction *f = (duk_hcompiledfunction *) h; duk_tval *tv, *tv_end; duk_hobject **funcs, **funcs_end; DUK_ASSERT(f->data != NULL); /* compiled functions must be created 'atomically' */ tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(f); tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(f); while (tv < tv_end) { duk_heap_tval_decref(thr, tv); tv++; } funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(f); funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(f); while (funcs < funcs_end) { duk_heap_heaphdr_decref(thr, (duk_heaphdr *) *funcs); funcs++; } duk_heap_heaphdr_decref(thr, (duk_heaphdr *) f->data); } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) { duk_hnativefunction *f = (duk_hnativefunction *) h; DUK_UNREF(f); /* nothing to finalize */ } else if (DUK_HOBJECT_IS_THREAD(h)) { duk_hthread *t = (duk_hthread *) h; duk_tval *tv; tv = t->valstack; while (tv < t->valstack_end) { duk_heap_tval_decref(thr, tv); tv++; } for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) { duk_activation *act = t->callstack + i; duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->func); duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->var_env); duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->lex_env); #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY duk_heap_heaphdr_decref(thr, (duk_heaphdr *) act->prev_caller); #endif } #if 0 /* nothing now */ for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) { duk_catcher *cat = t->catchstack + i; } #endif for (i = 0; i < DUK_NUM_BUILTINS; i++) { duk_heap_heaphdr_decref(thr, (duk_heaphdr *) t->builtins[i]); } duk_heap_heaphdr_decref(thr, (duk_heaphdr *) t->resumer); } }
DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) { duk_uint_fast32_t i; DUK_ASSERT(h); DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT); /* XXX: better to get base and walk forwards? */ for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) { duk_hstring *key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i); if (!key) { continue; } duk_heaphdr_decref(thr, (duk_heaphdr *) key); if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)) { duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, h, i)); duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, h, i)); } else { duk_tval_decref(thr, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i)); } } for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) { duk_tval_decref(thr, DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i)); } /* hash part is a 'weak reference' and does not contribute */ duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h)); /* XXX: rearrange bits to allow a switch case to be used here? */ /* XXX: add a fast path for objects (and arrays)? */ /* DUK_HOBJECT_IS_ARRAY(h): needs no special handling now as there are * no extra fields in need of decref. */ if (DUK_HOBJECT_IS_COMPFUNC(h)) { duk_hcompfunc *f = (duk_hcompfunc *) h; duk_tval *tv, *tv_end; duk_hobject **funcs, **funcs_end; DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL); /* compiled functions must be created 'atomically' */ tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f); tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f); while (tv < tv_end) { duk_tval_decref(thr, tv); tv++; } funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f); funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f); while (funcs < funcs_end) { duk_heaphdr_decref(thr, (duk_heaphdr *) *funcs); funcs++; } duk_heaphdr_decref(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(thr->heap, f)); } else if (DUK_HOBJECT_IS_NATFUNC(h)) { duk_hnatfunc *f = (duk_hnatfunc *) h; DUK_UNREF(f); /* nothing to finalize */ } else if (DUK_HOBJECT_IS_BUFOBJ(h)) { duk_hbufobj *b = (duk_hbufobj *) h; if (b->buf) { duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf); } } else if (DUK_HOBJECT_IS_THREAD(h)) { duk_hthread *t = (duk_hthread *) h; duk_tval *tv; tv = t->valstack; while (tv < t->valstack_top) { duk_tval_decref(thr, tv); tv++; } for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) { duk_activation *act = t->callstack + i; duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_ACT_GET_FUNC(act)); duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->var_env); duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->lex_env); #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->prev_caller); #endif } #if 0 /* nothing now */ for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) { duk_catcher *cat = t->catchstack + i; } #endif for (i = 0; i < DUK_NUM_BUILTINS; i++) { duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->builtins[i]); } duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->resumer); } }