Пример #1
0
void duk_heap_tval_decref(duk_hthread *thr, duk_tval *tv) {
#if 0
	DUK_DDD(DUK_DDDPRINT("tval decref %p (%ld->%ld): %!T",
	                     (void *) tv,
	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) DUK_TVAL_GET_HEAPHDR(tv)->h_refcount : (long) 0),
	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) (DUK_TVAL_GET_HEAPHDR(tv)->h_refcount - 1) : (long) 0),
	                     (duk_tval *) tv));
#endif

	if (!tv) {
		return;
	}

	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk_heap_heaphdr_decref(thr, DUK_TVAL_GET_HEAPHDR(tv));
	}
}
Пример #2
0
DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
	if (!tv) {
		return;
	}
	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk__mark_heaphdr(heap, DUK_TVAL_GET_HEAPHDR(tv));
	}
}
Пример #3
0
DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
		duk_heaphdr_decref(thr, h);
	}
}
Пример #4
0
DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
		DUK_HEAPHDR_PREINC_REFCOUNT(h);
	}
}
Пример #5
0
void duk_heap_tval_incref(duk_tval *tv) {
#if 0
	DUK_DDD(DUK_DDDPRINT("tval incref %p (%ld->%ld): %!T",
	                     (void *) tv,
	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) DUK_TVAL_GET_HEAPHDR(tv)->h_refcount : (long) 0),
	                     (tv != NULL && DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? (long) (DUK_TVAL_GET_HEAPHDR(tv)->h_refcount + 1) : (long) 0),
	                     (duk_tval *) tv));
#endif

	if (!tv) {
		return;
	}

	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		if (h) {
			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
			DUK_ASSERT_DISABLE(h->h_refcount >= 0);
			h->h_refcount++;
		}
	}
}
Пример #6
0
int duk_builtin_duk_object_addr(duk_context *ctx) {
	duk_tval *tv;
	void *p;

	tv = duk_get_tval(ctx, 0);
	if (!tv || !DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		return 0;  /* undefined */
	}
	p = (void *) DUK_TVAL_GET_HEAPHDR(tv);

	/* any heap allocated value (string, object, buffer) has a stable pointer */
	duk_push_sprintf(ctx, "%p", p);
	return 1;
}
Пример #7
0
int duk_builtin_duk_object_refc(duk_context *ctx) {
#ifdef DUK_USE_REFERENCE_COUNTING
	duk_tval *tv = duk_get_tval(ctx, 0);
	duk_heaphdr *h;
	if (!tv) {
		return 0;
	}
	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		return 0;
	}
	h = DUK_TVAL_GET_HEAPHDR(tv);
	duk_push_int(ctx, DUK_HEAPHDR_GET_REFCOUNT(h));
	return 1;
#else
	return 0;
#endif
}
Пример #8
0
/* Raw helper to extract internal information / statistics about a value.
 * The return values are version specific and must not expose anything
 * that would lead to security issues (e.g. exposing compiled function
 * 'data' buffer might be an issue).  Currently only counts and sizes and
 * such are given so there should not be a security impact.
 */
duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
	duk_tval *tv;
	duk_heaphdr *h;
	duk_int_t i, n;

	tv = duk_get_tval(ctx, 0);
	DUK_ASSERT(tv != NULL);  /* because arg count is 1 */

	duk_push_array(ctx);  /* -> [ val arr ] */

	/* type tag (public) */
	duk_push_int(ctx, duk_get_type(ctx, 0));

	/* address */
	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		h = DUK_TVAL_GET_HEAPHDR(tv);
		duk_push_pointer(ctx, (void *) h);
	} else {
		goto done;
	}
	DUK_ASSERT(h != NULL);

	/* refcount */
#ifdef DUK_USE_REFERENCE_COUNTING
	duk_push_int(ctx, DUK_HEAPHDR_GET_REFCOUNT(h));
#else
	duk_push_undefined(ctx);
#endif

	/* heaphdr size and additional allocation size, followed by
	 * type specific stuff (with varying value count)
	 */
	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_STRING: {
		duk_hstring *h_str = (duk_hstring *) h;
		duk_push_int(ctx, (int) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1));
		break;
	}
	case DUK_HTYPE_OBJECT: {
		duk_hobject *h_obj = (duk_hobject *) h;
		duk_int_t hdr_size;
		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
			hdr_size = (duk_int_t) sizeof(duk_hcompiledfunction);
		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
			hdr_size = (duk_int_t) sizeof(duk_hnativefunction);
		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
			hdr_size = (duk_int_t) sizeof(duk_hthread);
		} else {
			hdr_size = (duk_int_t) sizeof(duk_hobject);
		}
		duk_push_int(ctx, (int) hdr_size);
		duk_push_int(ctx, (int) DUK_HOBJECT_E_ALLOC_SIZE(h_obj));
		duk_push_int(ctx, (int) h_obj->e_size);
		duk_push_int(ctx, (int) h_obj->e_used);
		duk_push_int(ctx, (int) h_obj->a_size);
		duk_push_int(ctx, (int) h_obj->h_size);
		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
			duk_hbuffer *h_data = ((duk_hcompiledfunction *) h_obj)->data;
			if (h_data) {
				duk_push_int(ctx, DUK_HBUFFER_GET_SIZE(h_data));
			} else {
				duk_push_int(ctx, 0);
			}
		}
		break;
	}
	case DUK_HTYPE_BUFFER: {
		duk_hbuffer *h_buf = (duk_hbuffer *) h;
		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
			/* XXX: when usable_size == 0, dynamic buf ptr may now be NULL, in which case
			 * the second allocation does not exist.
			 */
			duk_hbuffer_dynamic *h_dyn = (duk_hbuffer_dynamic *) h;
			duk_push_int(ctx, (int) (sizeof(duk_hbuffer_dynamic)));
			duk_push_int(ctx, (int) (DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(h_dyn)));
		} else {
			duk_push_int(ctx, (int) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1));
		}
		break;

	}
	}

 done:
	/* set values into ret array */
	/* FIXME: primitive to make array from valstack slice */
	n = duk_get_top(ctx);
	for (i = 2; i < n; i++) {
		duk_dup(ctx, i);
		duk_put_prop_index(ctx, 1, i - 2);
	}
	duk_dup(ctx, 1);
	return 1;
}
Пример #9
0
/* Raw helper to extract internal information / statistics about a value.
 * The return values are version specific and must not expose anything
 * that would lead to security issues (e.g. exposing compiled function
 * 'data' buffer might be an issue).  Currently only counts and sizes and
 * such are given so there should not be a security impact.
 */
DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_tval *tv;
	duk_heaphdr *h;
	duk_int_t i, n;

	DUK_UNREF(thr);

	/* result array */
	duk_push_array(ctx);  /* -> [ val arr ] */

	/* type tag (public) */
	duk_push_int(ctx, duk_get_type(ctx, 0));

	/* address */
	tv = duk_get_tval(ctx, 0);
	DUK_ASSERT(tv != NULL);  /* because arg count is 1 */
	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		h = DUK_TVAL_GET_HEAPHDR(tv);
		duk_push_pointer(ctx, (void *) h);
	} else {
		/* internal type tag */
		duk_push_int(ctx, (duk_int_t) DUK_TVAL_GET_TAG(tv));
		goto done;
	}
	DUK_ASSERT(h != NULL);

	/* refcount */
#ifdef DUK_USE_REFERENCE_COUNTING
	duk_push_size_t(ctx, DUK_HEAPHDR_GET_REFCOUNT(h));
#else
	duk_push_undefined(ctx);
#endif

	/* heaphdr size and additional allocation size, followed by
	 * type specific stuff (with varying value count)
	 */
	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_STRING: {
		duk_hstring *h_str = (duk_hstring *) h;
		duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1));
		break;
	}
	case DUK_HTYPE_OBJECT: {
		duk_hobject *h_obj = (duk_hobject *) h;
		duk_small_uint_t hdr_size;
		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
			hdr_size = (duk_small_uint_t) sizeof(duk_hcompiledfunction);
		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
			hdr_size = (duk_small_uint_t) sizeof(duk_hnativefunction);
		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
			hdr_size = (duk_small_uint_t) sizeof(duk_hthread);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
			hdr_size = (duk_small_uint_t) sizeof(duk_hbufferobject);
#endif
		} else {
			hdr_size = (duk_small_uint_t) sizeof(duk_hobject);
		}
		duk_push_uint(ctx, (duk_uint_t) hdr_size);
		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj));
		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
		/* Note: e_next indicates the number of gc-reachable entries
		 * in the entry part, and also indicates the index where the
		 * next new property would be inserted.  It does *not* indicate
		 * the number of non-NULL keys present in the object.  That
		 * value could be counted separately but requires a pass through
		 * the key list.
		 */
		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, (duk_hcompiledfunction *) h_obj);
			if (h_data) {
				duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_data));
			} else {
				duk_push_uint(ctx, 0);
			}
		}
		break;
	}
	case DUK_HTYPE_BUFFER: {
		duk_hbuffer *h_buf = (duk_hbuffer *) h;
		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
				duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_external)));
			} else {
				/* When alloc_size == 0 the second allocation may not
				 * actually exist.
				 */
				duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_dynamic)));
			}
			duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_GET_SIZE(h_buf)));
		} else {
			duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1));
		}
		break;

	}
	}

 done:
	/* set values into ret array */
	/* XXX: primitive to make array from valstack slice */
	n = duk_get_top(ctx);
	for (i = 2; i < n; i++) {
		duk_dup(ctx, i);
		duk_put_prop_index(ctx, 1, i - 2);
	}
	duk_dup(ctx, 1);
	return 1;
}