]>
git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_hobject_finalizer.c
2 * Run an duk_hobject finalizer. Used for both reference counting
3 * and mark-and-sweep algorithms. Must never throw an error.
5 * There is no return value. Any return value or error thrown by
6 * the finalizer is ignored (although errors are debug logged).
10 * - The thread used for calling the finalizer is the same as the
11 * 'thr' argument. This may need to change later.
13 * - The finalizer thread 'top' assertions are there because it is
14 * critical that strict stack policy is observed (i.e. no cruft
15 * left on the finalizer stack).
18 #include "duk_internal.h"
20 DUK_LOCAL duk_ret_t
duk__finalize_helper(duk_context
*ctx
) {
23 DUK_ASSERT(ctx
!= NULL
);
24 thr
= (duk_hthread
*) ctx
;
26 DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
30 /* XXX: Finalizer lookup should traverse the prototype chain (to allow
31 * inherited finalizers) but should not invoke accessors or proxy object
32 * behavior. At the moment this lookup will invoke proxy behavior, so
33 * caller must ensure that this function is not called if the target is
37 duk_get_prop_stridx(ctx
, -1, DUK_STRIDX_INT_FINALIZER
); /* -> [... obj finalizer] */
38 if (!duk_is_callable(ctx
, -1)) {
39 DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
43 duk_push_boolean(ctx
, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr
->heap
));
44 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
45 duk_call(ctx
, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
46 DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
49 /* Note: we rely on duk_safe_call() to fix up the stack for the caller,
50 * so we don't need to pop stuff here. There is no return value;
51 * caller determines rescued status based on object refcount.
55 DUK_INTERNAL
void duk_hobject_run_finalizer(duk_hthread
*thr
, duk_hobject
*obj
) {
56 duk_context
*ctx
= (duk_context
*) thr
;
58 #ifdef DUK_USE_ASSERTIONS
62 DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj
));
64 DUK_ASSERT(thr
!= NULL
);
65 DUK_ASSERT(ctx
!= NULL
);
66 DUK_ASSERT(obj
!= NULL
);
67 DUK_ASSERT_VALSTACK_SPACE(thr
, 1);
69 #ifdef DUK_USE_ASSERTIONS
70 entry_top
= duk_get_top(ctx
);
73 * Get and call the finalizer. All of this must be wrapped
74 * in a protected call, because even getting the finalizer
75 * may trigger an error (getter may throw one, for instance).
78 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr
*) obj
));
79 if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr
*) obj
)) {
80 DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj
));
83 DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr
*) obj
); /* ensure never re-entered until rescue cycle complete */
84 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj
)) {
85 /* This shouldn't happen; call sites should avoid looking up
86 * _Finalizer "through" a Proxy, but ignore if we come here
87 * with a Proxy to avoid finalizer re-entry.
89 DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
93 /* XXX: use a NULL error handler for the finalizer call? */
95 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
96 duk_push_hobject(ctx
, obj
); /* this also increases refcount by one */
97 rc
= duk_safe_call(ctx
, duk__finalize_helper
, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
98 DUK_ASSERT_TOP(ctx
, entry_top
+ 2); /* duk_safe_call discipline */
100 if (rc
!= DUK_EXEC_SUCCESS
) {
101 /* Note: we ask for one return value from duk_safe_call to get this
102 * error debugging here.
104 DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
105 (void *) obj
, (duk_tval
*) duk_get_tval(ctx
, -1)));
107 duk_pop_2(ctx
); /* -> [...] */
109 DUK_ASSERT_TOP(ctx
, entry_top
);