Esempio n. 1
0
/* for thread dumping */
static char duk__get_tval_summary_char(duk_tval *tv) {
	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED:
		if (DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) {
			return '.';
		}
		return 'u';
	case DUK_TAG_NULL:
		return 'n';
	case DUK_TAG_BOOLEAN:
		return 'b';
	case DUK_TAG_STRING:
		return 's';
	case DUK_TAG_OBJECT: {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);

		if (DUK_HOBJECT_IS_ARRAY(h)) {
			return 'A';
		} else if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
			return 'C';
		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
			return 'N';
		} else if (DUK_HOBJECT_IS_THREAD(h)) {
			return 'T';
		}
		return 'O';
	}
	case DUK_TAG_BUFFER: {
		return 'B';
	}
	case DUK_TAG_POINTER: {
		return 'P';
	}
	default:
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		return 'd';
	}

	DUK_UNREACHABLE();
}
Esempio n. 2
0
DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
	duk_fixedbuffer *fb = st->fb;
	duk_uint_fast32_t i;
	duk_tval *tv;
	duk_hstring *key;
	duk_bool_t first = 1;
	const char *brace1 = "{";
	const char *brace2 = "}";
	duk_bool_t pushed_loopstack = 0;

	if (duk_fb_is_full(fb)) {
		return;
	}

	duk__print_shared_heaphdr(st, &h->hdr);

	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
		brace1 = "[";
		brace2 = "]";
	}

	if (!h) {
		duk_fb_put_cstring(fb, "NULL");
		goto finished;
	}

	if (st->depth >= st->depth_limit) {
		const char *subtype = "generic";

		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
			subtype = "compfunc";
		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
			subtype = "natfunc";
		} else if (DUK_HOBJECT_IS_THREAD(h)) {
			subtype = "thread";
		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
			subtype = "bufobj";
		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
			subtype = "array";
		}
		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
		return;
	}

	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
		if (st->loop_stack[i] == h) {
			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
			return;
		}
	}

	/* after this, return paths should 'goto finished' for decrement */
	st->depth++;

	if (st->loop_stack_index >= st->loop_stack_limit) {
		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
		goto finished;
	}
	st->loop_stack[st->loop_stack_index++] = h;
	pushed_loopstack = 1;

	/*
	 *  Notation: double underscore used for internal properties which are not
	 *  stored in the property allocation (e.g. '__valstack').
	 */

	duk_fb_put_cstring(fb, brace1);

	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
		duk_uint32_t a_limit;

		a_limit = DUK_HOBJECT_GET_ASIZE(h);
		if (st->internal) {
			/* dump all allocated entries, unused entries print as 'unused',
			 * note that these may extend beyond current 'length' and look
			 * a bit funny.
			 */
		} else {
			/* leave out trailing 'unused' elements */
			while (a_limit > 0) {
				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
				if (!DUK_TVAL_IS_UNUSED(tv)) {
					break;
				}
				a_limit--;
			}
		}

		for (i = 0; i < a_limit; i++) {
			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
			DUK__COMMA();
			duk__print_tval(st, tv);
		}
		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
			if (!key) {
				continue;
			}
			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
				continue;
			}
			DUK__COMMA();
			duk__print_hstring(st, key, 0);
			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
				duk_fb_sprintf(fb, "[get:%p,set:%p]",
				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
			} else {
				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
				duk__print_tval(st, tv);
			}
			if (st->heavy) {
				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
			}
		}
	}
	if (st->internal) {
		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
		}
		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
		}
		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
		}
		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
		}
		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
		}
		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
		}
		if (DUK_HOBJECT_HAS_THREAD(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
		}
		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
		}
		if (DUK_HOBJECT_HAS_STRICT(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
		}
		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
		}
		if (DUK_HOBJECT_HAS_NEWENV(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
		}
		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
		}
		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
		}
		if (DUK_HOBJECT_HAS_ENVRECCLOSED(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_dukfunc:true");
		}
		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
		}
	}

	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
		duk_harray *a = (duk_harray *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
		duk_hcompfunc *f = (duk_hcompfunc *) h;
		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
#endif
		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
		duk_hnatfunc *f = (duk_hnatfunc *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
		duk_hbufobj *b = (duk_hbufobj *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
#endif
	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
		duk_hthread *t = (duk_hthread *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
		/* XXX: print built-ins array? */

	}
#if defined(DUK_USE_REFERENCE_COUNTING)
	if (st->internal) {
		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
	}
#endif
	if (st->internal) {
		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
	}

	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */

	/* prototype should be last, for readability */
	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
		if (st->follow_proto) {
			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
		} else {
			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
		}
	}

	duk_fb_put_cstring(fb, brace2);

#if defined(DUK_USE_HOBJECT_HASH_PART)
	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
			if (i > 0) {
				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
			}
			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
				duk_fb_sprintf(fb, "u");
			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
				duk_fb_sprintf(fb, "d");
			} else {
				duk_fb_sprintf(fb, "%ld", (long) h_idx);
			}
		}
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
	}
#endif

 finished:
	st->depth--;
	if (pushed_loopstack) {
		st->loop_stack_index--;
		st->loop_stack[st->loop_stack_index] = NULL;
	}
}