DUK_INTERNAL void duk_heap_free(duk_heap *heap) { DUK_D(DUK_DPRINT("free heap: %p", (void *) heap)); #if defined(DUK_USE_DEBUG) duk_heap_dump_strtab(heap); #endif #if defined(DUK_USE_DEBUGGER_SUPPORT) /* Detach a debugger if attached (can be called multiple times) * safely. */ duk_debug_do_detach(heap); #endif /* Execute finalizers before freeing the heap, even for reachable * objects, and regardless of whether or not mark-and-sweep is * enabled. This gives finalizers the chance to free any native * resources like file handles, allocations made outside Duktape, * etc. * * XXX: this perhaps requires an execution time limit. */ DUK_D(DUK_DPRINT("execute finalizers before freeing heap")); #ifdef DUK_USE_MARK_AND_SWEEP /* run mark-and-sweep a few times just in case (unreachable * object finalizers run already here) */ duk_heap_mark_and_sweep(heap, 0); duk_heap_mark_and_sweep(heap, 0); #endif duk__free_run_finalizers(heap); /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object * are on the heap allocated list. */ DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap)); duk__free_allocated(heap); #ifdef DUK_USE_REFERENCE_COUNTING DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap)); duk__free_refzero_list(heap); #endif #ifdef DUK_USE_MARK_AND_SWEEP DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap)); duk__free_markandsweep_finalize_list(heap); #endif DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap)); duk__free_stringtable(heap); DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap)); heap->free_func(heap->heap_udata, heap); }
DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) { duk_hthread *thr; thr = (duk_hthread *) ctx; DUK_ASSERT(ctx != NULL); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->heap != NULL); /* Can be called muliple times with no harm. */ duk_debug_do_detach(thr->heap); }
DUK_INTERNAL void duk_heap_free(duk_heap *heap) { DUK_D(DUK_DPRINT("free heap: %p", (void *) heap)); #if defined(DUK_USE_DEBUG) duk_heap_dump_strtab(heap); #endif #if defined(DUK_USE_DEBUGGER_SUPPORT) /* Detach a debugger if attached (can be called multiple times) * safely. */ /* XXX: Add a flag to reject an attempt to re-attach? Otherwise * the detached callback may immediately reattach. */ duk_debug_do_detach(heap); #endif /* Execute finalizers before freeing the heap, even for reachable * objects, and regardless of whether or not mark-and-sweep is * enabled. This gives finalizers the chance to free any native * resources like file handles, allocations made outside Duktape, * etc. This is quite tricky to get right, so that all finalizer * guarantees are honored. * * XXX: this perhaps requires an execution time limit. */ DUK_D(DUK_DPRINT("execute finalizers before freeing heap")); #if defined(DUK_USE_MARK_AND_SWEEP) /* Run mark-and-sweep a few times just in case (unreachable object * finalizers run already here). The last round must rescue objects * from the previous round without running any more finalizers. This * ensures rescued objects get their FINALIZED flag cleared so that * their finalizer is called once more in forced finalization to * satisfy finalizer guarantees. However, we don't want to run any * more finalizer because that'd required one more loop, and so on. */ DUK_D(DUK_DPRINT("forced gc #1 in heap destruction")); duk_heap_mark_and_sweep(heap, 0); DUK_D(DUK_DPRINT("forced gc #2 in heap destruction")); duk_heap_mark_and_sweep(heap, 0); DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)")); duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS); /* skip finalizers; queue finalizable objects to heap_allocated */ #endif DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* rescue no longer supported */ duk__free_run_finalizers(heap); /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object * are on the heap allocated list. */ DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap)); duk__free_allocated(heap); #if defined(DUK_USE_REFERENCE_COUNTING) DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap)); duk__free_refzero_list(heap); #endif #if defined(DUK_USE_MARK_AND_SWEEP) DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap)); duk__free_markandsweep_finalize_list(heap); #endif DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap)); duk__free_stringtable(heap); DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap)); heap->free_func(heap->heap_udata, heap); }