JavaScript-Duktape

 view release on metacpan or  search on metacpan

lib/JavaScript/Duktape/C/lib/duktape.c  view on Meta::CPAN

			 *  function valued properties of built-in objects now.
			 */

#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
		 lightfunc_skip:
#endif

			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
			                                                         DUK__PROP_FLAGS_BITS,
			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
			defprop_flags |= DUK_DEFPROP_FORCE |
			                 DUK_DEFPROP_HAVE_VALUE |
			                 DUK_DEFPROP_HAVE_WRITABLE |
			                 DUK_DEFPROP_HAVE_ENUMERABLE |
			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);

			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);

			/* [ (builtin objects) ] */
		}
	}

	/*
	 *  Special post-tweaks, for cases not covered by the init data format.
	 *
	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
	 *    toGMTString is required to have the same Function object as
	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
	 *    this, V8 does not (the Function objects are distinct).
	 *
	 *  - Make DoubleError non-extensible.
	 *
	 *  - Add info about most important effective compile options to Duktape.
	 *
	 *  - Possibly remove some properties (values or methods) which are not
	 *    desirable with current feature options but are not currently
	 *    conditional in init data.
	 */

#if defined(DUK_USE_DATE_BUILTIN)
	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
#endif

	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);

#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
#endif

#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
#endif

	/* XXX: relocate */
	duk_push_string(thr,
			/* Endianness indicator */
#if defined(DUK_USE_INTEGER_LE)
	                "l"
#elif defined(DUK_USE_INTEGER_BE)
	                "b"
#elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
	                "m"
#else
	                "?"
#endif
#if defined(DUK_USE_DOUBLE_LE)
	                "l"
#elif defined(DUK_USE_DOUBLE_BE)
	                "b"
#elif defined(DUK_USE_DOUBLE_ME)
	                "m"
#else
	                "?"
#endif
	                " "
			/* Packed or unpacked tval */
#if defined(DUK_USE_PACKED_TVAL)
	                "p"
#else
	                "u"
#endif
#if defined(DUK_USE_FASTINT)
			"f"
#endif
			" "
			/* Low memory/performance options */
#if defined(DUK_USE_STRTAB_PTRCOMP)
			"s"
#endif
#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
			"n"
#endif
#if defined(DUK_USE_HEAPPTR16)
			"h"
#endif
#if defined(DUK_USE_DATAPTR16)
			"d"
#endif
#if defined(DUK_USE_FUNCPTR16)
			"f"
#endif
#if defined(DUK_USE_REFCOUNT16)
			"R"
#endif
#if defined(DUK_USE_STRHASH16)
			"H"
#endif
#if defined(DUK_USE_STRLEN16)
			"S"
#endif
#if defined(DUK_USE_BUFLEN16)
			"B"
#endif
#if defined(DUK_USE_OBJSIZES16)

lib/JavaScript/Duktape/C/lib/duktape.c  view on Meta::CPAN

/* Inner executor, performance critical. */
DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
	 * Critical for performance.  It would be safest to make this volatile,
	 * but that eliminates performance benefits; aliasing guarantees
	 * should be enough though.
	 */
	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */

	/* Hot variables for interpretation.  Critical for performance,
	 * but must add sparingly to minimize register shuffling.
	 */
	duk_hthread *thr;             /* stable */
	duk_tval *consts;             /* stable */
	duk_uint_fast32_t ins;
	/* 'funcs' is quite rarely used, so no local for it */
#if defined(DUK_USE_EXEC_FUN_LOCAL)
	duk_hcompfunc *fun;
#else
	/* 'fun' is quite rarely used, so no local for it */
#endif

#if defined(DUK_USE_INTERRUPT_COUNTER)
	duk_int_t int_ctr;
#endif

#if defined(DUK_USE_ASSERTIONS)
	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
#endif

	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
	 * either 8 or 16.  Heap allocation checks this even without asserts
	 * enabled now because it can't be autodetected in duk_config.h.
	 */
#if 1
#if defined(DUK_USE_PACKED_TVAL)
	DUK_ASSERT(sizeof(duk_tval) == 8);
#else
	DUK_ASSERT(sizeof(duk_tval) == 16);
#endif
#endif

	DUK_GC_TORTURE(entry_thread->heap);

	/*
	 *  Restart execution by reloading thread state.
	 *
	 *  Note that 'thr' and any thread configuration may have changed,
	 *  so all local variables are suspect and we need to reinitialize.
	 *
	 *  The number of local variables should be kept to a minimum: if
	 *  the variables are spilled, they will need to be loaded from
	 *  memory anyway.
	 *
	 *  Any 'goto restart_execution;' code path in opcode dispatch must
	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
	 *  takes place.
	 *
	 *  The interpreter must be very careful with memory pointers, as
	 *  many pointers are not guaranteed to be 'stable' and may be
	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
	 *  memory allocation or a property access).
	 *
	 *  The following are assumed to have stable pointers:
	 *    - the current thread
	 *    - the current function
	 *    - the bytecode, constant table, inner function table of the
	 *      current function (as they are a part of the function allocation)
	 *
	 *  The following are assumed to have semi-stable pointers:
	 *    - the current activation entry: stable as long as callstack
	 *      is not changed (reallocated by growing or shrinking), or
	 *      by any garbage collection invocation (through finalizers)
	 *    - Note in particular that ANY DECREF can invalidate the
	 *      activation pointer, so for the most part a fresh lookup
	 *      is required
	 *
	 *  The following are not assumed to have stable pointers at all:
	 *    - the value stack (registers) of the current thread
	 *
	 *  See execution.rst for discussion.
	 */

 restart_execution:

	/* Lookup current thread; use the stable 'entry_thread' for this to
	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
	 * fine for this, so using 'entry_thread' is just to silence warnings.
	 */
	thr = entry_thread->heap->curr_thread;
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));

	DUK_GC_TORTURE(thr->heap);

	thr->ptr_curr_pc = &curr_pc;

	/* Relookup and initialize dispatch loop variables.  Debugger check. */
	{
		duk_activation *act;
#if !defined(DUK_USE_EXEC_FUN_LOCAL)
		duk_hcompfunc *fun;
#endif

		/* Assume interrupt init/counter are properly initialized here. */
		/* Assume that thr->valstack_bottom has been set-up before getting here. */

		act = thr->callstack_curr;
		DUK_ASSERT(act != NULL);
		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
		DUK_ASSERT(fun != NULL);
		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
		DUK_ASSERT(consts != NULL);

#if defined(DUK_USE_DEBUGGER_SUPPORT)
		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
			duk__executor_recheck_debugger(thr, act, fun);

lib/JavaScript/Duktape/C/lib/duktape.c  view on Meta::CPAN


	duk_uint_t error_count = 0;

	duk_double_t d1, d2;
	duk_small_uint_t u;

	duk_double_t d1v, d2v;
	duk_small_uint_t uv;

	/* Test without volatiles */

	d1 = 1.0;
	u = (duk_small_uint_t) d1;
	d2 = (duk_double_t) u;

	if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
		DUK__FAILED("double to duk_small_uint_t cast failed");
	}

	/* Same test with volatiles */

	d1v = 1.0;
	uv = (duk_small_uint_t) d1v;
	d2v = (duk_double_t) uv;

	if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
		DUK__FAILED("double to duk_small_uint_t cast failed");
	}

	return error_count;
}

DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
	/*
	 *  This test fails on an exotic ARM target; double-to-uint
	 *  cast is incorrectly clamped to -signed- int highest value.
	 *
	 *  https://github.com/svaarala/duktape/issues/336
	 */

	duk_uint_t error_count = 0;
	duk_double_t dv;
	duk_uint32_t uv;

	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
	uv = (duk_uint32_t) dv;

	if (uv != 0xdeadbeefUL) {
		DUK__FAILED("double to duk_uint32_t cast failed");
	}

	return error_count;
}

/*
 *  Minimal test of user supplied allocation functions
 *
 *    - Basic alloc + realloc + free cycle
 *
 *    - Realloc to significantly larger size to (hopefully) trigger a
 *      relocation and check that relocation copying works
 */

DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
                                               duk_realloc_function realloc_func,
                                               duk_free_function free_func,
                                               void *udata) {
	duk_uint_t error_count = 0;
	void *ptr;
	void *new_ptr;
	duk_small_int_t i, j;
	unsigned char x;

	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
		return 0;
	}

	for (i = 1; i <= 256; i++) {
		ptr = alloc_func(udata, (duk_size_t) i);
		if (ptr == NULL) {
			DUK_D(DUK_DPRINT("alloc failed, ignore"));
			continue;  /* alloc failed, ignore */
		}
		for (j = 0; j < i; j++) {
			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
		}
		new_ptr = realloc_func(udata, ptr, 1024);
		if (new_ptr == NULL) {
			DUK_D(DUK_DPRINT("realloc failed, ignore"));
			free_func(udata, ptr);
			continue;  /* realloc failed, ignore */
		}
		ptr = new_ptr;
		for (j = 0; j < i; j++) {
			x = ((unsigned char *) ptr)[j];
			if (x != (unsigned char) (0x80 + j)) {
				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
				                 (long) j, (unsigned long) x));
				DUK__FAILED("byte compare after realloc");
				break;
			}
		}
		free_func(udata, ptr);
	}

	return error_count;
}

/*
 *  Self test main
 */

DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
                                               duk_realloc_function realloc_func,
                                               duk_free_function free_func,
                                               void *udata) {
	duk_uint_t error_count = 0;

	DUK_D(DUK_DPRINT("self test starting"));

	error_count += duk__selftest_types();



( run in 1.210 second using v1.01-cache-2.11-cpan-71847e10f99 )