changeset 48:91fcf87e570d

duktape: upgrade to 2.0.1
author David Demelier <markand@malikania.fr>
date Mon, 30 Jan 2017 13:45:36 +0100
parents 8a8de065f049
children 424714e0ea58
files VERSION.duktape.txt duktape/duk_config.h duktape/duktape.cpp duktape/duktape.h
diffstat 4 files changed, 156 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/VERSION.duktape.txt	Fri Jan 20 10:44:37 2017 +0100
+++ b/VERSION.duktape.txt	Mon Jan 30 13:45:36 2017 +0100
@@ -1,1 +1,1 @@
-1.6.0
+2.0.1
--- a/duktape/duk_config.h	Fri Jan 20 10:44:37 2017 +0100
+++ b/duktape/duk_config.h	Mon Jan 30 13:45:36 2017 +0100
@@ -1,9 +1,9 @@
 /*
  *  duk_config.h configuration header generated by genconfig.py.
  *
- *  Git commit: 4180966c47d6d87106008dd4338de8d507c8072b
- *  Git describe: v2.0.0
- *  Git branch: master
+ *  Git commit: 3f5e91704aff97c754f6ef5d44aedc5e529d1b16
+ *  Git describe: v2.0.1
+ *  Git branch: v2.0-maintenance
  *
  *  Supported platforms:
  *      - Mac OSX, iPhone, Darwin
--- a/duktape/duktape.cpp	Fri Jan 20 10:44:37 2017 +0100
+++ b/duktape/duktape.cpp	Mon Jan 30 13:45:36 2017 +0100
@@ -1,8 +1,8 @@
 /*
- *  Single source autogenerated distributable for Duktape 2.0.0.
- *
- *  Git commit 4180966c47d6d87106008dd4338de8d507c8072b (v2.0.0).
- *  Git branch master.
+ *  Single source autogenerated distributable for Duktape 2.0.1.
+ *
+ *  Git commit 3f5e91704aff97c754f6ef5d44aedc5e529d1b16 (v2.0.1).
+ *  Git branch v2.0-maintenance.
  *
  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
@@ -10017,7 +10017,7 @@
 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,64,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,
@@ -10194,7 +10194,7 @@
 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,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,236,
@@ -10371,7 +10371,7 @@
 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,64,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,
@@ -20844,6 +20844,86 @@
 	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 +20938,7 @@
 	 */
 
 #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 +25486,7 @@
 	}
 
 	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 +29491,6 @@
 	DUK_ASSERT_TOP(ctx, 1);
 	if (duk_is_undefined(ctx, 0)) {
 		len = 0;
-		final_len = len;
 	} else {
 		duk_hstring *h_input;
 
@@ -29480,6 +29548,8 @@
 		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
@@ -37757,10 +37827,10 @@
 		} 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 */
 
@@ -45126,7 +45196,7 @@
 	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 +45602,12 @@
 		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 +45616,10 @@
 			 */
 			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 +45773,11 @@
 		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 */
@@ -47157,6 +47241,12 @@
 		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 +47256,9 @@
 		} \
 	} 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 +47275,7 @@
 	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 +47332,7 @@
 /* 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
@@ -68816,7 +68910,7 @@
 			break;
 		}
 		default: {
-			DUK_UNREACHABLE();
+			/* Possible with DUK_OP_EXP. */
 			goto skip_fastint;
 		}
 		}
@@ -74975,12 +75069,12 @@
  */
 
 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 +75086,29 @@
 	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;
-			}
-			res = new_res;
+		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);
+			}
 		} else {
 			goto parse_fail;
 		}
--- a/duktape/duktape.h	Fri Jan 20 10:44:37 2017 +0100
+++ b/duktape/duktape.h	Mon Jan 30 13:45:36 2017 +0100
@@ -1,13 +1,13 @@
 /*
- *  Duktape public API for Duktape 2.0.0.
+ *  Duktape public API for Duktape 2.0.1.
  *
  *  See the API reference for documentation on call semantics.
  *  The exposed API is inside the DUK_API_PUBLIC_H_INCLUDED
  *  include guard.  Other parts of the header are Duktape
  *  internal and related to platform/compiler/feature detection.
  *
- *  Git commit 4180966c47d6d87106008dd4338de8d507c8072b (v2.0.0).
- *  Git branch master.
+ *  Git commit 3f5e91704aff97c754f6ef5d44aedc5e529d1b16 (v2.0.1).
+ *  Git branch v2.0-maintenance.
  *
  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
@@ -253,16 +253,16 @@
  * development snapshots have 99 for patch level (e.g. 0.10.99 would be a
  * development version after 0.10.0 but before the next official release).
  */
-#define DUK_VERSION                       20000L
+#define DUK_VERSION                       20001L
 
 /* Git commit, describe, and branch for Duktape build.  Useful for
  * non-official snapshot builds so that application code can easily log
  * which Duktape snapshot was used.  Not available in the Ecmascript
  * environment.
  */
-#define DUK_GIT_COMMIT                    "4180966c47d6d87106008dd4338de8d507c8072b"
-#define DUK_GIT_DESCRIBE                  "v2.0.0"
-#define DUK_GIT_BRANCH                    "master"
+#define DUK_GIT_COMMIT                    "3f5e91704aff97c754f6ef5d44aedc5e529d1b16"
+#define DUK_GIT_DESCRIBE                  "v2.0.1"
+#define DUK_GIT_BRANCH                    "v2.0-maintenance"
 
 /* Duktape debug protocol version used by this build. */
 #define DUK_DEBUG_PROTOCOL_VERSION        2