Пример #1
0
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 */
}
Пример #2
0
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 */
}