|
@@ -1,8 +1,8 @@
|
|
|
/*
|
|
|
- * Single source autogenerated distributable for Duktape 2.0.0.
|
|
|
+ * Single source autogenerated distributable for Duktape 2.0.2.
|
|
|
*
|
|
|
- * Git commit 4180966c47d6d87106008dd4338de8d507c8072b (v2.0.0).
|
|
|
- * Git branch master.
|
|
|
+ * Git commit 12e0741b105e53174202b7c15f55a95f6aa0bfb0 (v2.0.2).
|
|
|
+ * Git branch v2.0-maintenance.
|
|
|
*
|
|
|
* See Duktape AUTHORS.rst and LICENSE.txt for copyright and
|
|
|
* licensing information.
|
|
@@ -9919,9 +9919,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
|
|
|
98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
|
|
|
132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
|
|
|
18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
|
|
|
-147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
|
|
|
-116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
|
|
|
-15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
|
|
|
+147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,38,154,121,223,110,76,66,
|
|
|
+53,116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,
|
|
|
+79,15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
|
|
|
255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
|
|
|
255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
|
|
|
141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
|
|
@@ -10017,7 +10017,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
|
|
|
42,240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,
|
|
|
33,186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,
|
|
|
183,1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,
|
|
|
-140,144,230,192,0,0,0,0,0,136,211,64,182,120,43,135,126,16,68,52,174,195,
|
|
|
+140,144,230,192,0,0,0,0,128,136,211,64,182,120,43,135,126,16,68,52,174,195,
|
|
|
144,12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,
|
|
|
32,176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,
|
|
|
35,18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,
|
|
@@ -10096,9 +10096,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
|
|
|
98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
|
|
|
132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
|
|
|
18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
|
|
|
-147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
|
|
|
-116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
|
|
|
-15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
|
|
|
+147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,38,154,121,223,110,76,66,
|
|
|
+53,116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,
|
|
|
+79,15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
|
|
|
255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
|
|
|
255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
|
|
|
141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
|
|
@@ -10194,7 +10194,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
|
|
|
240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,33,
|
|
|
186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,183,
|
|
|
1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,140,
|
|
|
-144,230,192,64,211,136,0,0,0,0,0,182,120,43,135,126,16,68,52,174,195,144,
|
|
|
+144,230,192,64,211,136,128,0,0,0,0,182,120,43,135,126,16,68,52,174,195,144,
|
|
|
12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,32,
|
|
|
176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,35,
|
|
|
18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,236,
|
|
@@ -10273,9 +10273,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
|
|
|
98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
|
|
|
132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
|
|
|
18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
|
|
|
-147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
|
|
|
-116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
|
|
|
-15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
|
|
|
+147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,38,154,121,223,110,76,66,
|
|
|
+53,116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,
|
|
|
+79,15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
|
|
|
255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
|
|
|
255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
|
|
|
141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
|
|
@@ -10371,7 +10371,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
|
|
|
42,240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,
|
|
|
33,186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,
|
|
|
183,1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,
|
|
|
-140,144,230,192,0,136,211,64,0,0,0,0,182,120,43,135,126,16,68,52,174,195,
|
|
|
+140,144,230,192,128,136,211,64,0,0,0,0,182,120,43,135,126,16,68,52,174,195,
|
|
|
144,12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,
|
|
|
32,176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,
|
|
|
35,18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,
|
|
@@ -13742,8 +13742,10 @@ DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) {
|
|
|
DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
|
|
|
|
|
|
act = duk_hthread_get_current_activation(thr);
|
|
|
- DUK_ASSERT(act != NULL); /* because callstack_top > 0 */
|
|
|
- return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
|
|
|
+ if (act != NULL) {
|
|
|
+ return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/* XXX: Make this obsolete by adding a function flag for rejecting a
|
|
@@ -20844,6 +20846,86 @@ DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_context *ctx, duk_size_t len)
|
|
|
return ptr;
|
|
|
}
|
|
|
|
|
|
+#if defined(DUK_USE_ASSERTIONS)
|
|
|
+DUK_LOCAL void duk__validate_push_heapptr(duk_context *ctx, void *ptr) {
|
|
|
+ duk_heaphdr *h;
|
|
|
+ duk_heaphdr *curr;
|
|
|
+ duk_hthread *thr;
|
|
|
+ duk_bool_t found = 0;
|
|
|
+
|
|
|
+ thr = (duk_hthread *) ctx;
|
|
|
+ h = (duk_heaphdr *) ptr;
|
|
|
+ if (h == NULL) {
|
|
|
+ /* Allowed. */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ DUK_ASSERT(h != NULL);
|
|
|
+ DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
|
|
|
+
|
|
|
+ /* One particular problem case is where an object has been
|
|
|
+ * queued for finalization but the finalizer hasn't yet been
|
|
|
+ * executed.
|
|
|
+ *
|
|
|
+ * Corner case: we're running in a finalizer for object X, and
|
|
|
+ * user code calls duk_push_heapptr() for X itself. In this
|
|
|
+ * case X will be in finalize_list, and we can detect the case
|
|
|
+ * by seeing that X's FINALIZED flag is set (which is done before
|
|
|
+ * the finalizer starts executing).
|
|
|
+ */
|
|
|
+ for (curr = thr->heap->finalize_list;
|
|
|
+ curr != NULL;
|
|
|
+ curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
|
|
|
+ if (curr == h) {
|
|
|
+ if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
|
|
|
+ /* Object is currently being finalized. */
|
|
|
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
|
|
|
+ found = 1;
|
|
|
+ } else {
|
|
|
+ DUK_ASSERT(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Also check for the refzero_list; must not be there unless it is
|
|
|
+ * being finalized when duk_push_heapptr() is called.
|
|
|
+ *
|
|
|
+ * Corner case: similar to finalize_list.
|
|
|
+ */
|
|
|
+#if defined(DUK_USE_REFERENCE_COUNTING)
|
|
|
+ for (curr = thr->heap->refzero_list;
|
|
|
+ curr != NULL;
|
|
|
+ curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
|
|
|
+ if (curr == h) {
|
|
|
+ if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
|
|
|
+ /* Object is currently being finalized. */
|
|
|
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
|
|
|
+ found = 1;
|
|
|
+ } else {
|
|
|
+ DUK_ASSERT(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* If not present in finalize_list or refzero_list, the pointer
|
|
|
+ * must be either in heap_allocated or the string table.
|
|
|
+ */
|
|
|
+ if (DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_STRING) {
|
|
|
+ /* Omitted from Duktape 2.0.x maintenance backport. */
|
|
|
+ } else {
|
|
|
+ for (curr = thr->heap->heap_allocated;
|
|
|
+ curr != NULL;
|
|
|
+ curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
|
|
|
+ if (curr == h) {
|
|
|
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
|
|
|
+ found = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ DUK_ASSERT(found != 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif /* DUK_USE_ASSERTIONS */
|
|
|
+
|
|
|
DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
|
|
|
duk_hthread *thr = (duk_hthread *) ctx;
|
|
|
duk_idx_t ret;
|
|
@@ -20858,18 +20940,7 @@ DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
|
|
|
*/
|
|
|
|
|
|
#if defined(DUK_USE_ASSERTIONS)
|
|
|
- {
|
|
|
- /* One particular problem case is where an object has been
|
|
|
- * queued for finalization but the finalizer hasn't been
|
|
|
- * executed.
|
|
|
- */
|
|
|
- duk_heaphdr *curr;
|
|
|
- for (curr = thr->heap->finalize_list;
|
|
|
- curr != NULL;
|
|
|
- curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
|
|
|
- DUK_ASSERT(curr != (duk_heaphdr *) ptr);
|
|
|
- }
|
|
|
- }
|
|
|
+ duk__validate_push_heapptr(ctx, ptr);
|
|
|
#endif
|
|
|
|
|
|
ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
|
|
@@ -25417,7 +25488,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
|
|
|
}
|
|
|
|
|
|
duk_hbufobj_promote_plain(ctx, 0);
|
|
|
- h_obj = duk_known_hobject(ctx, 0);
|
|
|
+ h_obj = duk_require_hobject(ctx, 0);
|
|
|
|
|
|
/* XXX: V8 throws a TypeError for negative values. Would it
|
|
|
* be more useful to interpret negative offsets here from the
|
|
@@ -29422,7 +29493,6 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx) {
|
|
|
DUK_ASSERT_TOP(ctx, 1);
|
|
|
if (duk_is_undefined(ctx, 0)) {
|
|
|
len = 0;
|
|
|
- final_len = len;
|
|
|
} else {
|
|
|
duk_hstring *h_input;
|
|
|
|
|
@@ -29480,6 +29550,8 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx) {
|
|
|
final_len = (duk_size_t) (enc_ctx.out - output);
|
|
|
duk_resize_buffer(ctx, -1, final_len);
|
|
|
/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
|
|
|
+ } else {
|
|
|
+ final_len = 0;
|
|
|
}
|
|
|
|
|
|
/* Standard WHATWG output is a Uint8Array. Here the Uint8Array will
|
|
@@ -30933,7 +31005,6 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
|
|
|
"var_env and lex_env to a fresh env, "
|
|
|
"this_binding to caller's this_binding"));
|
|
|
|
|
|
- act = thr->callstack + thr->callstack_top + level; /* caller */
|
|
|
act_lex_env = act->lex_env;
|
|
|
act = NULL; /* invalidated */
|
|
|
|
|
@@ -37757,10 +37828,10 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx) {
|
|
|
} else {
|
|
|
DUK_MEMCPY((void *) p, (const void *) src, copy_size);
|
|
|
p += copy_size;
|
|
|
- copy_size *= 2;
|
|
|
}
|
|
|
|
|
|
src = (const duk_uint8_t *) buf; /* Use buf as source for larger copies. */
|
|
|
+ copy_size = (duk_size_t) (p - buf);
|
|
|
}
|
|
|
#endif /* DUK_USE_PREFER_SIZE */
|
|
|
|
|
@@ -40451,6 +40522,7 @@ DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
|
|
|
duk_pop_3(ctx);
|
|
|
/* Report next pc/line to be executed. */
|
|
|
duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
|
|
|
}
|
|
|
|
|
@@ -40483,18 +40555,29 @@ DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
|
|
|
duk__debug_write_hstring_safe_top(thr);
|
|
|
duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_LINE_NUMBER);
|
|
|
duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
|
|
|
+ duk_pop_2(ctx);
|
|
|
} else {
|
|
|
- /* For anything other than an Error instance, we calculate the error
|
|
|
- * location directly from the current activation.
|
|
|
+ /* For anything other than an Error instance, we calculate the
|
|
|
+ * error location directly from the current activation if one
|
|
|
+ * exists.
|
|
|
*/
|
|
|
- act = thr->callstack + thr->callstack_top - 1;
|
|
|
- duk_push_tval(ctx, &act->tv_func);
|
|
|
- duk_get_prop_string(ctx, -1, "fileName");
|
|
|
- duk__debug_write_hstring_safe_top(thr);
|
|
|
- pc = duk_hthread_get_act_prev_pc(thr, act);
|
|
|
- duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
|
|
|
+ if (thr->callstack_top > 0) {
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
+ duk_push_tval(ctx, &act->tv_func);
|
|
|
+ duk_get_prop_string(ctx, -1, "fileName");
|
|
|
+ duk__debug_write_hstring_safe_top(thr);
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
+ pc = duk_hthread_get_act_prev_pc(thr, act);
|
|
|
+ duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
|
|
|
+ duk_pop_2(ctx);
|
|
|
+ } else {
|
|
|
+ /* Can happen if duk_throw() is called on an empty
|
|
|
+ * callstack.
|
|
|
+ */
|
|
|
+ duk_debug_write_cstring(thr, "");
|
|
|
+ duk_debug_write_uint(thr, 0);
|
|
|
+ }
|
|
|
}
|
|
|
- duk_pop_2(ctx); /* shared pop */
|
|
|
|
|
|
duk_debug_write_eom(thr);
|
|
|
}
|
|
@@ -45126,7 +45209,7 @@ DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap) {
|
|
|
while (hdr) {
|
|
|
DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
|
|
|
- DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
|
|
|
+ /* DUK_HEAPHDR_HAS_FINALIZED may or may not be set. */
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
|
|
|
hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
|
|
|
}
|
|
@@ -45532,6 +45615,12 @@ DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* No finalizers for ROM objects */
|
|
|
|
|
|
+ /* Keep heap->finalize_list up-to-date during the list walk.
|
|
|
+ * This has no functional impact, but does matter e.g. for
|
|
|
+ * duk_push_heapptr() asserts when assertions are enabled.
|
|
|
+ */
|
|
|
+ heap->finalize_list = curr;
|
|
|
+
|
|
|
if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
|
|
|
/* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
|
|
|
* Next mark-and-sweep will collect the object unless it has
|
|
@@ -45540,6 +45629,10 @@ DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags
|
|
|
*/
|
|
|
duk_hobject_run_finalizer(thr, (duk_hobject *) curr); /* must never longjmp */
|
|
|
DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
|
|
|
+
|
|
|
+ /* XXX: could clear FINALIZED already here; now cleared in
|
|
|
+ * next mark-and-sweep.
|
|
|
+ */
|
|
|
} else {
|
|
|
/* Used during heap destruction: don't actually run finalizers
|
|
|
* because we're heading into forced finalization. Instead,
|
|
@@ -45693,7 +45786,11 @@ DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
|
|
|
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
|
|
|
- DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
|
|
|
+ /* DUK_HEAPHDR_HAS_FINALIZED may be set if we're doing a
|
|
|
+ * refzero finalization and mark-and-sweep gets triggered
|
|
|
+ * during the finalizer.
|
|
|
+ */
|
|
|
+ /* DUK_HEAPHDR_HAS_FINALIZED may or may not be set. */
|
|
|
hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
|
|
|
}
|
|
|
#endif /* DUK_USE_REFERENCE_COUNTING */
|
|
@@ -45796,6 +45893,11 @@ DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t
|
|
|
duk_size_t tmp;
|
|
|
#endif
|
|
|
|
|
|
+ if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
|
|
|
+ DUK_D(DUK_DPRINT("refuse to do a recursive mark-and-sweep"));
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
/* XXX: thread selection for mark-and-sweep is currently a hack.
|
|
|
* If we don't have a thread, the entire mark-and-sweep is now
|
|
|
* skipped (although we could just skip finalizations).
|
|
@@ -46920,12 +47022,17 @@ DUK_INTERNAL void duk_refzero_free_pending(duk_hthread *thr) {
|
|
|
*/
|
|
|
heap->mark_and_sweep_trigger_counter -= count;
|
|
|
if (heap->mark_and_sweep_trigger_counter <= 0) {
|
|
|
- duk_bool_t rc;
|
|
|
- duk_small_uint_t flags = 0; /* not emergency */
|
|
|
- DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
|
|
|
- rc = duk_heap_mark_and_sweep(heap, flags);
|
|
|
- DUK_UNREF(rc);
|
|
|
- DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
|
|
|
+ if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
|
|
|
+ DUK_D(DUK_DPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
|
|
|
+ } else {
|
|
|
+ duk_bool_t rc;
|
|
|
+ duk_small_uint_t flags = 0; /* not emergency */
|
|
|
+
|
|
|
+ DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
|
|
|
+ rc = duk_heap_mark_and_sweep(heap, flags);
|
|
|
+ DUK_UNREF(rc);
|
|
|
+ DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
|
|
|
+ }
|
|
|
}
|
|
|
#endif /* DUK_USE_VOLUNTARY_GC */
|
|
|
}
|
|
@@ -47143,7 +47250,7 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
|
|
|
}
|
|
|
duk_heaphdr_refzero_norz(thr, h);
|
|
|
#else
|
|
|
- duk_heaphdr_decref(thr, h);
|
|
|
+ duk_heaphdr_decref_norz(thr, h);
|
|
|
#endif
|
|
|
}
|
|
|
}
|
|
@@ -47157,6 +47264,12 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
|
|
|
DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
|
|
|
} while (0)
|
|
|
#if defined(DUK_USE_ROM_OBJECTS)
|
|
|
+#define DUK__INCREF_SHARED() do { \
|
|
|
+ if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
|
|
|
+ return; \
|
|
|
+ } \
|
|
|
+ DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
|
|
|
+ } while (0)
|
|
|
#define DUK__DECREF_SHARED() do { \
|
|
|
if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
|
|
|
return; \
|
|
@@ -47166,6 +47279,9 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
|
|
|
} \
|
|
|
} while (0)
|
|
|
#else
|
|
|
+#define DUK__INCREF_SHARED() do { \
|
|
|
+ DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
|
|
|
+ } while (0)
|
|
|
#define DUK__DECREF_SHARED() do { \
|
|
|
if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
|
|
|
return; \
|
|
@@ -47182,7 +47298,7 @@ DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
|
|
|
DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
|
|
|
DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
|
|
|
|
|
|
- DUK_HEAPHDR_PREINC_REFCOUNT(h);
|
|
|
+ DUK__INCREF_SHARED();
|
|
|
}
|
|
|
|
|
|
DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
|
|
@@ -47239,6 +47355,7 @@ DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
|
|
|
/* automatic undefs */
|
|
|
#undef DUK__DECREF_ASSERTS
|
|
|
#undef DUK__DECREF_SHARED
|
|
|
+#undef DUK__INCREF_SHARED
|
|
|
#undef DUK__RZ_BUFFER
|
|
|
#undef DUK__RZ_INLINE
|
|
|
#undef DUK__RZ_OBJECT
|
|
@@ -56437,10 +56554,9 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
|
|
|
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
|
|
|
-1); /* no prototype */
|
|
|
DUK_ASSERT(h1 != NULL);
|
|
|
- duk_dup_m2(ctx);
|
|
|
- duk_dup_top(ctx); /* -> [ ... new_global new_globalenv new_global new_global ] */
|
|
|
- duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
|
|
|
- duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
|
|
|
+ duk_dup_m2(ctx); /* -> [ ... new_global new_globalenv new_global ] */
|
|
|
+ duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
|
|
|
+ /* provideThis=false */
|
|
|
|
|
|
duk_hobject_compact_props(thr, h1);
|
|
|
DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
|
|
@@ -59307,8 +59423,8 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
|
|
|
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
|
|
|
if (func) {
|
|
|
duk__update_func_caller_prop(thr, func);
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
}
|
|
|
- act = thr->callstack + thr->callstack_top - 1;
|
|
|
#endif
|
|
|
|
|
|
/* [ ... func this arg1 ... argN ] */
|
|
@@ -59368,6 +59484,7 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
|
|
|
DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
|
|
|
|
|
|
duk__handle_oldenv_for_call(thr, func, act);
|
|
|
+ /* No need to re-lookup 'act' at present: no side effects. */
|
|
|
|
|
|
DUK_ASSERT(act->lex_env != NULL);
|
|
|
DUK_ASSERT(act->var_env != NULL);
|
|
@@ -59404,6 +59521,7 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
|
|
|
* new value stack bottom, and call the target.
|
|
|
*/
|
|
|
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
|
|
|
/*
|
|
|
* Ecmascript call
|
|
@@ -60533,6 +60651,7 @@ DUK_INTERNAL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr,
|
|
|
*/
|
|
|
|
|
|
duk__handle_oldenv_for_call(thr, func, act);
|
|
|
+ /* No need to re-lookup 'act' at present: no side effects. */
|
|
|
|
|
|
DUK_ASSERT(act->lex_env != NULL);
|
|
|
DUK_ASSERT(act->var_env != NULL);
|
|
@@ -68816,7 +68935,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
|
|
|
break;
|
|
|
}
|
|
|
default: {
|
|
|
- DUK_UNREACHABLE();
|
|
|
+ /* Possible with DUK_OP_EXP. */
|
|
|
goto skip_fastint;
|
|
|
}
|
|
|
}
|
|
@@ -69288,11 +69407,13 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr,
|
|
|
|
|
|
if (op & 0x02) {
|
|
|
duk_push_number(ctx, y); /* -> [ ... x this y ] */
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(ctx, -1), is_strict);
|
|
|
duk_pop_2(ctx); /* -> [ ... x ] */
|
|
|
} else {
|
|
|
duk_pop_2(ctx); /* -> [ ... ] */
|
|
|
duk_push_number(ctx, y); /* -> [ ... y ] */
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(ctx, -1), is_strict);
|
|
|
}
|
|
|
|
|
@@ -69675,7 +69796,9 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
|
|
|
* which we simply ignore.
|
|
|
*/
|
|
|
|
|
|
+ DUK_ASSERT(resumee->resumer == NULL);
|
|
|
resumee->resumer = thr;
|
|
|
+ DUK_HTHREAD_INCREF(thr, thr);
|
|
|
resumee->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
thr->state = DUK_HTHREAD_STATE_RESUMED;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
|
|
@@ -69705,7 +69828,9 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
|
|
|
|
|
|
duk__reconfig_valstack_ecma_return(resumee, act_idx);
|
|
|
|
|
|
+ DUK_ASSERT(resumee->resumer == NULL);
|
|
|
resumee->resumer = thr;
|
|
|
+ DUK_HTHREAD_INCREF(thr, thr);
|
|
|
resumee->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
thr->state = DUK_HTHREAD_STATE_RESUMED;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
|
|
@@ -69741,7 +69866,9 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
|
|
|
DUK_ERROR_INTERNAL(thr);
|
|
|
}
|
|
|
|
|
|
+ DUK_ASSERT(resumee->resumer == NULL);
|
|
|
resumee->resumer = thr;
|
|
|
+ DUK_HTHREAD_INCREF(thr, thr);
|
|
|
resumee->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
thr->state = DUK_HTHREAD_STATE_RESUMED;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
|
|
@@ -69796,6 +69923,7 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
|
|
|
if (thr->heap->lj.iserror) {
|
|
|
thr->state = DUK_HTHREAD_STATE_YIELDED;
|
|
|
thr->resumer = NULL;
|
|
|
+ DUK_HTHREAD_DECREF_NORZ(thr, resumer);
|
|
|
resumer->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
|
|
|
thr = resumer;
|
|
@@ -69811,6 +69939,7 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
|
|
|
|
|
|
thr->state = DUK_HTHREAD_STATE_YIELDED;
|
|
|
thr->resumer = NULL;
|
|
|
+ DUK_HTHREAD_DECREF_NORZ(thr, resumer);
|
|
|
resumer->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
|
|
|
#if 0
|
|
@@ -69927,6 +70056,7 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
|
|
|
DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
|
|
|
|
|
|
thr->resumer = NULL;
|
|
|
+ DUK_HTHREAD_DECREF_NORZ(thr, resumer);
|
|
|
resumer->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
|
|
|
thr = resumer;
|
|
@@ -70188,6 +70318,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr,
|
|
|
DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
|
|
|
|
|
|
thr->resumer = NULL;
|
|
|
+ DUK_HTHREAD_DECREF(thr, resumer);
|
|
|
resumer->state = DUK_HTHREAD_STATE_RUNNING;
|
|
|
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
|
|
|
#if 0
|
|
@@ -72201,9 +72332,15 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
|
|
|
|
|
|
act = thr->callstack + thr->callstack_top - 1;
|
|
|
if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
|
|
|
- /* already declared, must update binding value */
|
|
|
- tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
|
|
|
- duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
|
|
|
+ if (is_undef_value) {
|
|
|
+ /* Already declared but no initializer value
|
|
|
+ * (e.g. 'var xyz;'), no-op.
|
|
|
+ */
|
|
|
+ } else {
|
|
|
+ /* Already declared, update value. */
|
|
|
+ tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
|
|
|
+ duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
duk_pop(ctx);
|
|
@@ -72296,6 +72433,7 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
|
|
|
if (act->lex_env == NULL) {
|
|
|
DUK_ASSERT(act->var_env == NULL);
|
|
|
duk_js_init_activation_environment_records_delayed(thr, act);
|
|
|
+ act = thr->callstack + thr->callstack_top - 1;
|
|
|
}
|
|
|
DUK_ASSERT(act->lex_env != NULL);
|
|
|
DUK_ASSERT(act->var_env != NULL);
|
|
@@ -72637,11 +72775,11 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
|
|
|
|
|
|
DUK_DDD(DUK_DDDPRINT("activating object env: %!iT",
|
|
|
(duk_tval *) duk_get_tval(ctx, -1)));
|
|
|
- DUK_ASSERT(act->lex_env != NULL);
|
|
|
new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
|
|
|
DUK_ASSERT(new_env != NULL);
|
|
|
|
|
|
act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
|
|
|
+ DUK_ASSERT(act->lex_env != NULL);
|
|
|
DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env); /* side effects */
|
|
|
|
|
|
act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
|
|
@@ -74975,12 +75113,12 @@ DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
|
|
|
*/
|
|
|
|
|
|
DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx) {
|
|
|
- duk_uarridx_t res, new_res;
|
|
|
+ duk_uarridx_t res;
|
|
|
|
|
|
if (blen == 0 || blen > 10) {
|
|
|
goto parse_fail;
|
|
|
}
|
|
|
- if (str[0] == (duk_uint8_t) '0' && blen > 1) {
|
|
|
+ if (str[0] == DUK_ASC_0 && blen > 1) {
|
|
|
goto parse_fail;
|
|
|
}
|
|
|
|
|
@@ -74992,13 +75130,29 @@ DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *
|
|
|
res = 0;
|
|
|
while (blen-- > 0) {
|
|
|
duk_uint8_t c = *str++;
|
|
|
- if (c >= (duk_uint8_t) '0' && c <= (duk_uint8_t) '9') {
|
|
|
- new_res = res * 10 + (duk_uint32_t) (c - (duk_uint8_t) '0');
|
|
|
- if (new_res < res) {
|
|
|
- /* overflow, more than 32 bits -> not an array index */
|
|
|
- goto parse_fail;
|
|
|
+ if (c >= DUK_ASC_0 && c <= DUK_ASC_9) {
|
|
|
+ /* Careful overflow handling. When multiplying by 10:
|
|
|
+ * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
|
|
|
+ * 0...9 is safe.
|
|
|
+ * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
|
|
|
+ * 0...5 is safe, 6...9 overflows.
|
|
|
+ * - 0x1999999a x 10 = 0x100000004: always overflow.
|
|
|
+ */
|
|
|
+ if (DUK_UNLIKELY(res >= 0x19999999UL)) {
|
|
|
+ if (res >= 0x1999999aUL) {
|
|
|
+ /* Always overflow. */
|
|
|
+ goto parse_fail;
|
|
|
+ }
|
|
|
+ DUK_ASSERT(res == 0x19999999UL);
|
|
|
+ c -= DUK_ASC_0;
|
|
|
+ if (c >= 6) {
|
|
|
+ goto parse_fail;
|
|
|
+ }
|
|
|
+ res = 0xfffffffaUL + c;
|
|
|
+ DUK_ASSERT(res >= 0xfffffffaUL && res <= 0xffffffffUL);
|
|
|
+ } else {
|
|
|
+ res = res * 10U + (duk_uint32_t) (c - DUK_ASC_0);
|
|
|
}
|
|
|
- res = new_res;
|
|
|
} else {
|
|
|
goto parse_fail;
|
|
|
}
|
|
@@ -75566,7 +75720,10 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
|
|
|
duk_context *ctx = (duk_context *) thr;
|
|
|
duk_hobject *func;
|
|
|
duk_hobject *env;
|
|
|
+ duk_size_t act_off;
|
|
|
|
|
|
+ DUK_ASSERT(act != NULL);
|
|
|
+ act_off = (duk_size_t) ((duk_uint8_t *) act - (duk_uint8_t *) thr->callstack);
|
|
|
func = DUK_ACT_GET_FUNC(act);
|
|
|
DUK_ASSERT(func != NULL);
|
|
|
DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound functions are never in act 'func' */
|
|
@@ -75581,6 +75738,7 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
|
|
|
|
|
|
env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
|
|
|
DUK_ASSERT(env != NULL);
|
|
|
+ act = (duk_activation *) ((duk_uint8_t *) thr->callstack + act_off);
|
|
|
|
|
|
DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
|
|
|
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
|
|
@@ -76828,6 +76986,10 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
|
|
|
duk_bool_t is_func_decl) {
|
|
|
duk_hobject *env;
|
|
|
duk_tval tv_val_copy;
|
|
|
+ duk_size_t act_off;
|
|
|
+
|
|
|
+ DUK_ASSERT(act != NULL);
|
|
|
+ act_off = (duk_size_t) ((duk_uint8_t *) act - (duk_uint8_t *) thr->callstack);
|
|
|
|
|
|
/*
|
|
|
* Make a value copy of the input val. This ensures that
|
|
@@ -76844,6 +77006,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
|
|
|
if (!act->var_env) {
|
|
|
DUK_ASSERT(act->lex_env == NULL);
|
|
|
duk_js_init_activation_environment_records_delayed(thr, act);
|
|
|
+ act = (duk_activation *) ((duk_uint8_t *) thr->callstack + act_off);
|
|
|
}
|
|
|
DUK_ASSERT(act->lex_env != NULL);
|
|
|
DUK_ASSERT(act->var_env != NULL);
|