void duk_hthread_catchstack_unwind(duk_hthread *thr, int new_top) { int idx; DUK_ASSERT(thr); DUK_ASSERT(thr->heap); DUK_ASSERT(new_top >= 0); DUK_ASSERT(new_top <= thr->catchstack_top); /* cannot grow */ /* * Since there are no references in the catcher structure, * unwinding is quite simple. The only thing we need to * look out for is popping a possible lexical environment * established for an active catch clause. */ idx = thr->catchstack_top; while (idx > new_top) { duk_catcher *p; duk_activation *act; duk_hobject *env; idx--; DUK_ASSERT(idx >= 0 && idx < thr->catchstack_size); p = &thr->catchstack[idx]; if (DUK_CAT_HAS_LEXENV_ACTIVE(p)) { DUK_DDDPRINT("unwinding catchstack idx %d: lexical environment active", idx); /* FIXME: Here we have a nasty dependency: the need to manipulate * the callstack means that catchstack must always be unwound by * the caller before unwinding the callstack. This should be fixed * later. */ act = &thr->callstack[p->callstack_index]; DUK_ASSERT(act >= thr->callstack); DUK_ASSERT(act < &thr->callstack[thr->callstack_top]); DUK_ASSERT(act->lex_env != NULL); /* must be, since env was created */ DUK_DDDPRINT("callstack_index=%d, lex_env=%!iO", p->callstack_index, act->lex_env); env = act->lex_env; act->lex_env = env->prototype; DUK_HOBJECT_DECREF(thr, env); } } thr->catchstack_top = new_top; /* note: any entries above the catchstack top are garbage and not zeroed */ }
void duk_hthread_catchstack_unwind(duk_hthread *thr, int new_top) { int idx; /* FIXME: typing of 'new_top' and 'idx' */ DUK_DDDPRINT("unwind catchstack top of thread %p from %d to %d", (void *) thr, (thr != NULL ? (int) thr->catchstack_top : (int) -1), (int) new_top); DUK_ASSERT(thr); DUK_ASSERT(thr->heap); DUK_ASSERT(new_top >= 0); DUK_ASSERT((duk_size_t) new_top <= thr->catchstack_top); /* cannot grow */ /* * Since there are no references in the catcher structure, * unwinding is quite simple. The only thing we need to * look out for is popping a possible lexical environment * established for an active catch clause. */ idx = thr->catchstack_top; while (idx > new_top) { duk_catcher *p; duk_activation *act; duk_hobject *env; idx--; DUK_ASSERT(idx >= 0); DUK_ASSERT((duk_size_t) idx < thr->catchstack_size); p = &thr->catchstack[idx]; if (DUK_CAT_HAS_LEXENV_ACTIVE(p)) { DUK_DDDPRINT("unwinding catchstack idx %d, callstack idx %d, callstack top %d: lexical environment active", idx, p->callstack_index, thr->callstack_top); /* FIXME: Here we have a nasty dependency: the need to manipulate * the callstack means that catchstack must always be unwound by * the caller before unwinding the callstack. This should be fixed * later. */ /* Note that multiple catchstack entries may refer to the same * callstack entry. */ act = &thr->callstack[p->callstack_index]; DUK_ASSERT(act >= thr->callstack); DUK_ASSERT(act < &thr->callstack[thr->callstack_top]); DUK_DDDPRINT("catchstack_index=%d, callstack_index=%d, lex_env=%!iO", (int) idx, (int) p->callstack_index, act->lex_env); env = act->lex_env; /* current lex_env of the activation (created for catcher) */ DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */ act->lex_env = env->prototype; /* prototype is lex_env before catcher created */ DUK_HOBJECT_DECREF(thr, env); /* There is no need to decref anything else than 'env': if 'env' * becomes unreachable, refzero will handle decref'ing its prototype. */ } } thr->catchstack_top = new_top; /* note: any entries above the catchstack top are garbage and not zeroed */ }