nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ald...@apache.org
Subject [17/52] [partial] nifi-minifi-cpp git commit: Remove libxml2, civetweb thirdparty.
Date Thu, 04 May 2017 19:06:25 GMT
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b26ac36e/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_hashstring.c
----------------------------------------------------------------------
diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_hashstring.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_hashstring.c
deleted file mode 100644
index 5cad795..0000000
--- a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_hashstring.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  String hash computation (interning).
- *
- *  String hashing is performance critical because a string hash is computed
- *  for all new strings which are candidates to be added to the string table.
- *  However, strings actually added to the string table go through a codepoint
- *  length calculation which dominates performance because it goes through
- *  every byte of the input string (but only for strings added).
- *
- *  The string hash algorithm should be fast, but on the other hand provide
- *  good enough hashes to ensure both string table and object property table
- *  hash tables work reasonably well (i.e., there aren't too many collisions
- *  with real world inputs).  Unless the hash is cryptographic, it's always
- *  possible to craft inputs with maximal hash collisions.
- *
- *  NOTE: The hash algorithms must match src/dukutil.py:duk_heap_hashstring()
- *  for ROM string support!
- */
-
-#include "duk_internal.h"
-
-#if defined(DUK_USE_STRHASH_DENSE)
-/* Constants for duk_hashstring(). */
-#define DUK__STRHASH_SHORTSTRING   4096L
-#define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
-#define DUK__STRHASH_BLOCKSIZE     256L
-
-DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
-	duk_uint32_t hash;
-
-	/* Use Murmurhash2 directly for short strings, and use "block skipping"
-	 * for long strings: hash an initial part and then sample the rest of
-	 * the string with reasonably sized chunks.  An initial offset for the
-	 * sampling is computed based on a hash of the initial part of the string;
-	 * this is done to (usually) avoid the case where all long strings have
-	 * certain offset ranges which are never sampled.
-	 *
-	 * Skip should depend on length and bound the total time to roughly
-	 * logarithmic.  With current values:
-	 *
-	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
-	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
-	 *
-	 * XXX: It would be better to compute the skip offset more "smoothly"
-	 * instead of having a few boundary values.
-	 */
-
-	/* note: mixing len into seed improves hashing when skipping */
-	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
-
-	if (len <= DUK__STRHASH_SHORTSTRING) {
-		hash = duk_util_hashbytes(str, len, str_seed);
-	} else {
-		duk_size_t off;
-		duk_size_t skip;
-
-		if (len <= DUK__STRHASH_MEDIUMSTRING) {
-			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
-		} else {
-			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
-		}
-
-		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
-		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
-
-		/* XXX: inefficient loop */
-		while (off < len) {
-			duk_size_t left = len - off;
-			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
-			hash ^= duk_util_hashbytes(str + off, now, str_seed);
-			off += skip;
-		}
-	}
-
-#if defined(DUK_USE_STRHASH16)
-	/* Truncate to 16 bits here, so that a computed hash can be compared
-	 * against a hash stored in a 16-bit field.
-	 */
-	hash &= 0x0000ffffUL;
-#endif
-	return hash;
-}
-
-#undef DUK__STRHASH_SHORTSTRING
-#undef DUK__STRHASH_MEDIUMSTRING
-#undef DUK__STRHASH_BLOCKSIZE
-#else  /* DUK_USE_STRHASH_DENSE */
-DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
-	duk_uint32_t hash;
-	duk_size_t step;
-	duk_size_t off;
-
-	/* Slightly modified "Bernstein hash" from:
-	 *
-	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
-	 *
-	 * Modifications: string skipping and reverse direction similar to
-	 * Lua 5.1.5, and different hash initializer.
-	 *
-	 * The reverse direction ensures last byte it always included in the
-	 * hash which is a good default as changing parts of the string are
-	 * more often in the suffix than in the prefix.
-	 */
-
-	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
-	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
-	for (off = len; off >= step; off -= step) {
-		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
-		hash = (hash * 33) + str[off - 1];
-	}
-
-#if defined(DUK_USE_STRHASH16)
-	/* Truncate to 16 bits here, so that a computed hash can be compared
-	 * against a hash stored in a 16-bit field.
-	 */
-	hash &= 0x0000ffffUL;
-#endif
-	return hash;
-}
-#endif  /* DUK_USE_STRHASH_DENSE */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b26ac36e/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_markandsweep.c
----------------------------------------------------------------------
diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_markandsweep.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_markandsweep.c
deleted file mode 100644
index fa7b553..0000000
--- a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_markandsweep.c
+++ /dev/null
@@ -1,1421 +0,0 @@
-/*
- *  Mark-and-sweep garbage collection.
- */
-
-#include "duk_internal.h"
-
-#ifdef DUK_USE_MARK_AND_SWEEP
-
-DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
-DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
-
-/*
- *  Misc
- */
-
-/* Select a thread for mark-and-sweep use.
- *
- * XXX: This needs to change later.
- */
-DUK_LOCAL duk_hthread *duk__get_temp_hthread(duk_heap *heap) {
-	if (heap->curr_thread) {
-		return heap->curr_thread;
-	}
-	return heap->heap_thread;  /* may be NULL, too */
-}
-
-/*
- *  Marking functions for heap types: mark children recursively
- */
-
-DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
-	DUK_UNREF(heap);
-	DUK_UNREF(h);
-
-	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
-	DUK_ASSERT(h);
-
-	/* nothing to process */
-}
-
-DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
-	duk_uint_fast32_t i;
-
-	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
-
-	DUK_ASSERT(h);
-
-	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
-
-	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
-		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
-		if (!key) {
-			continue;
-		}
-		duk__mark_heaphdr(heap, (duk_heaphdr *) key);
-		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
-			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
-			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
-		} else {
-			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
-		}
-	}
-
-	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
-		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
-	}
-
-	/* hash part is a 'weak reference' and does not contribute */
-
-	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
-
-	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
-		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
-		duk_tval *tv, *tv_end;
-		duk_hobject **fn, **fn_end;
-
-		/* 'data' is reachable through every compiled function which
-		 * contains a reference.
-		 */
-
-		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f));
-
-		if (DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f) != NULL) {
-			tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, f);
-			tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, f);
-			while (tv < tv_end) {
-				duk__mark_tval(heap, tv);
-				tv++;
-			}
-
-			fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, f);
-			fn_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f);
-			while (fn < fn_end) {
-				duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
-				fn++;
-			}
-		} else {
-			/* May happen in some out-of-memory corner cases. */
-			DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping marking"));
-		}
-	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
-		duk_hnativefunction *f = (duk_hnativefunction *) h;
-		DUK_UNREF(f);
-		/* nothing to mark */
-	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
-		duk_hbufferobject *b = (duk_hbufferobject *) h;
-		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
-	} else if (DUK_HOBJECT_IS_THREAD(h)) {
-		duk_hthread *t = (duk_hthread *) h;
-		duk_tval *tv;
-
-		tv = t->valstack;
-		while (tv < t->valstack_top) {
-			duk__mark_tval(heap, tv);
-			tv++;
-		}
-
-		for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
-			duk_activation *act = t->callstack + i;
-			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
-			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
-			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
-#endif
-		}
-
-#if 0  /* nothing now */
-		for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
-			duk_catcher *cat = t->catchstack + i;
-		}
-#endif
-
-		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
-
-		/* XXX: duk_small_uint_t would be enough for this loop */
-		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
-			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
-		}
-	}
-}
-
-/* recursion tracking happens here only */
-DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
-	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
-	                     (void *) h,
-	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
-	if (!h) {
-		return;
-	}
-#if defined(DUK_USE_ROM_OBJECTS)
-	if (DUK_HEAPHDR_HAS_READONLY(h)) {
-		DUK_DDD(DUK_DDDPRINT("readonly object %p, skip", (void *) h));
-		return;
-	}
-#endif
-	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
-		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
-		return;
-	}
-	DUK_HEAPHDR_SET_REACHABLE(h);
-
-	if (heap->mark_and_sweep_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
-		/* log this with a normal debug level because this should be relatively rare */
-		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
-		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
-		DUK_HEAPHDR_SET_TEMPROOT(h);
-		return;
-	}
-
-	heap->mark_and_sweep_recursion_depth++;
-
-	switch ((int) DUK_HEAPHDR_GET_TYPE(h)) {
-	case DUK_HTYPE_STRING:
-		duk__mark_hstring(heap, (duk_hstring *) h);
-		break;
-	case DUK_HTYPE_OBJECT:
-		duk__mark_hobject(heap, (duk_hobject *) h);
-		break;
-	case DUK_HTYPE_BUFFER:
-		/* nothing to mark */
-		break;
-	default:
-		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
-		DUK_UNREACHABLE();
-	}
-
-	heap->mark_and_sweep_recursion_depth--;
-}
-
-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));
-	}
-}
-
-/*
- *  Mark the heap.
- */
-
-DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
-	duk_small_uint_t i;
-
-	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
-
-	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
-	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
-
-	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
-		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
-		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
-	}
-
-	duk__mark_tval(heap, &heap->lj.value1);
-	duk__mark_tval(heap, &heap->lj.value2);
-
-#if defined(DUK_USE_DEBUGGER_SUPPORT)
-	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
-		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
-	}
-#endif
-}
-
-/*
- *  Mark refzero_list objects.
- *
- *  Objects on the refzero_list have no inbound references.  They might have
- *  outbound references to objects that we might free, which would invalidate
- *  any references held by the refzero objects.  A refzero object might also
- *  be rescued by refcount finalization.  Refzero objects are treated as
- *  reachability roots to ensure they (or anything they point to) are not
- *  freed in mark-and-sweep.
- */
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-DUK_LOCAL void duk__mark_refzero_list(duk_heap *heap) {
-	duk_heaphdr *hdr;
-
-	DUK_DD(DUK_DDPRINT("duk__mark_refzero_list: %p", (void *) heap));
-
-	hdr = heap->refzero_list;
-	while (hdr) {
-		duk__mark_heaphdr(heap, hdr);
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-}
-#endif
-
-/*
- *  Mark unreachable, finalizable objects.
- *
- *  Such objects will be moved aside and their finalizers run later.  They have
- *  to be treated as reachability roots for their properties etc to remain
- *  allocated.  This marking is only done for unreachable values which would
- *  be swept later (refzero_list is thus excluded).
- *
- *  Objects are first marked FINALIZABLE and only then marked as reachability
- *  roots; otherwise circular references might be handled inconsistently.
- */
-
-DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
-	duk_hthread *thr;
-	duk_heaphdr *hdr;
-	duk_size_t count_finalizable = 0;
-
-	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
-
-	thr = duk__get_temp_hthread(heap);
-	DUK_ASSERT(thr != NULL);
-
-	hdr = heap->heap_allocated;
-	while (hdr) {
-		/* A finalizer is looked up from the object and up its prototype chain
-		 * (which allows inherited finalizers).  A prototype loop must not cause
-		 * an error to be thrown here; duk_hobject_hasprop_raw() will ignore a
-		 * prototype loop silently and indicate that the property doesn't exist.
-		 */
-
-		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
-		    DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_OBJECT &&
-		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
-		    duk_hobject_hasprop_raw(thr, (duk_hobject *) hdr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
-
-			/* heaphdr:
-			 *  - is not reachable
-			 *  - is an object
-			 *  - is not a finalized object
-			 *  - has a finalizer
-			 */
-
-			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
-			                   "finalized -> mark as finalizable "
-			                   "and treat as a reachability root: %p",
-			                   (void *) hdr));
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
-			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
-			count_finalizable ++;
-		}
-
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-
-	if (count_finalizable == 0) {
-		return;
-	}
-
-	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
-	                   (long) count_finalizable));
-
-	hdr = heap->heap_allocated;
-	while (hdr) {
-		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
-			duk__mark_heaphdr(heap, hdr);
-		}
-
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-
-	/* Caller will finish the marking process if we hit a recursion limit. */
-}
-
-/*
- *  Mark objects on finalize_list.
- *
- */
-
-DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
-	duk_heaphdr *hdr;
-#ifdef DUK_USE_DEBUG
-	duk_size_t count_finalize_list = 0;
-#endif
-
-	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
-
-	hdr = heap->finalize_list;
-	while (hdr) {
-		duk__mark_heaphdr(heap, hdr);
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-#ifdef DUK_USE_DEBUG
-		count_finalize_list++;
-#endif
-	}
-
-#ifdef DUK_USE_DEBUG
-	if (count_finalize_list > 0) {
-		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
-		                 (long) count_finalize_list));
-	}
-#endif
-}
-
-/*
- *  Fallback marking handler if recursion limit is reached.
- *
- *  Iterates 'temproots' until recursion limit is no longer hit.  Note
- *  that temproots may reside either in heap allocated list or the
- *  refzero work list.  This is a slow scan, but guarantees that we
- *  finish with a bounded C stack.
- *
- *  Note that nodes may have been marked as temproots before this
- *  scan begun, OR they may have been marked during the scan (as
- *  we process nodes recursively also during the scan).  This is
- *  intended behavior.
- */
-
-#ifdef DUK_USE_DEBUG
-DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
-#else
-DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
-#endif
-	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
-		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
-		return;
-	}
-
-	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
-	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
-	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* done so that duk__mark_heaphdr() works correctly */
-	duk__mark_heaphdr(heap, hdr);
-
-#ifdef DUK_USE_DEBUG
-	(*count)++;
-#endif
-}
-
-DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
-	duk_heaphdr *hdr;
-#ifdef DUK_USE_DEBUG
-	duk_size_t count;
-#endif
-
-	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
-
-	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
-		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
-
-#ifdef DUK_USE_DEBUG
-		count = 0;
-#endif
-		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
-
-		hdr = heap->heap_allocated;
-		while (hdr) {
-#ifdef DUK_USE_DEBUG
-			duk__handle_temproot(heap, hdr, &count);
-#else
-			duk__handle_temproot(heap, hdr);
-#endif
-			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-		}
-
-		/* must also check refzero_list */
-#ifdef DUK_USE_REFERENCE_COUNTING
-		hdr = heap->refzero_list;
-		while (hdr) {
-#ifdef DUK_USE_DEBUG
-			duk__handle_temproot(heap, hdr, &count);
-#else
-			duk__handle_temproot(heap, hdr);
-#endif
-			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-		}
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-
-#ifdef DUK_USE_DEBUG
-		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
-#endif
-	}
-}
-
-/*
- *  Finalize refcounts for heap elements just about to be freed.
- *  This must be done for all objects before freeing to avoid any
- *  stale pointer dereferences.
- *
- *  Note that this must deduce the set of objects to be freed
- *  identically to duk__sweep_heap().
- */
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
-	duk_hthread *thr;
-	duk_heaphdr *hdr;
-
-	thr = duk__get_temp_hthread(heap);
-	DUK_ASSERT(thr != NULL);
-
-	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p, hthread=%p",
-	                   (void *) heap, (void *) thr));
-
-	hdr = heap->heap_allocated;
-	while (hdr) {
-		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
-			/*
-			 *  Unreachable object about to be swept.  Finalize target refcounts
-			 *  (objects which the unreachable object points to) without doing
-			 *  refzero processing.  Recursive decrefs are also prevented when
-			 *  refzero processing is disabled.
-			 *
-			 *  Value cannot be a finalizable object, as they have been made
-			 *  temporarily reachable for this round.
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
-			duk_heaphdr_refcount_finalize(thr, hdr);
-		}
-
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-}
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-
-/*
- *  Clear (reachable) flags of refzero work list.
- */
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap) {
-	duk_heaphdr *hdr;
-
-	DUK_DD(DUK_DDPRINT("duk__clear_refzero_list_flags: %p", (void *) heap));
-
-	hdr = heap->refzero_list;
-	while (hdr) {
-		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-}
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-
-/*
- *  Clear (reachable) flags of finalize_list
- *
- *  We could mostly do in the sweep phase when we move objects from the
- *  heap into the finalize_list.  However, if a finalizer run is skipped
- *  during a mark-and-sweep, the objects on the finalize_list will be marked
- *  reachable during the next mark-and-sweep.  Since they're already on the
- *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
- *  here.  (This now overlaps with the sweep handling in a harmless way.)
- */
-
-DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
-	duk_heaphdr *hdr;
-
-	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
-
-	hdr = heap->finalize_list;
-	while (hdr) {
-		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-}
-
-/*
- *  Sweep stringtable
- */
-
-#if defined(DUK_USE_STRTAB_CHAIN)
-
-/* XXX: skip count_free w/o debug? */
-#if defined(DUK_USE_HEAPPTR16)
-DUK_LOCAL void duk__sweep_string_chain16(duk_heap *heap, duk_uint16_t *slot, duk_size_t *count_keep, duk_size_t *count_free) {
-	duk_uint16_t h16 = *slot;
-	duk_hstring *h;
-	duk_uint16_t null16 = heap->heapptr_null16;
-
-	if (h16 == null16) {
-		/* nop */
-		return;
-	}
-	h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, h16);
-	DUK_ASSERT(h != NULL);
-
-	if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
-		DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
-		(*count_keep)++;
-	} else {
-#if defined(DUK_USE_REFERENCE_COUNTING)
-		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
-#endif
-		/* deal with weak references first */
-		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
-		*slot = null16;
-
-		/* free inner references (these exist e.g. when external
-		 * strings are enabled)
-		 */
-		duk_free_hstring_inner(heap, h);
-		DUK_FREE(heap, h);
-		(*count_free)++;
-	}
-}
-#else  /* DUK_USE_HEAPPTR16 */
-DUK_LOCAL void duk__sweep_string_chain(duk_heap *heap, duk_hstring **slot, duk_size_t *count_keep, duk_size_t *count_free) {
-	duk_hstring *h = *slot;
-
-	if (h == NULL) {
-		/* nop */
-		return;
-	}
-
-	if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
-		DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
-		(*count_keep)++;
-	} else {
-#if defined(DUK_USE_REFERENCE_COUNTING)
-		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
-#endif
-		/* deal with weak references first */
-		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
-		*slot = NULL;
-
-		/* free inner references (these exist e.g. when external
-		 * strings are enabled)
-		 */
-		duk_free_hstring_inner(heap, h);
-		DUK_FREE(heap, h);
-		(*count_free)++;
-	}
-}
-#endif  /* DUK_USE_HEAPPTR16 */
-
-DUK_LOCAL void duk__sweep_stringtable_chain(duk_heap *heap, duk_size_t *out_count_keep) {
-	duk_strtab_entry *e;
-	duk_uint_fast32_t i;
-	duk_size_t count_free = 0;
-	duk_size_t count_keep = 0;
-	duk_size_t j, n;
-#if defined(DUK_USE_HEAPPTR16)
-	duk_uint16_t *lst;
-#else
-	duk_hstring **lst;
-#endif
-
-	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
-
-	/* Non-zero refcounts should not happen for unreachable strings,
-	 * because we refcount finalize all unreachable objects which
-	 * should have decreased unreachable string refcounts to zero
-	 * (even for cycles).
-	 */
-
-	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
-		e = heap->strtable + i;
-		if (e->listlen == 0) {
-#if defined(DUK_USE_HEAPPTR16)
-			duk__sweep_string_chain16(heap, &e->u.str16, &count_keep, &count_free);
-#else
-			duk__sweep_string_chain(heap, &e->u.str, &count_keep, &count_free);
-#endif
-		} else {
-#if defined(DUK_USE_HEAPPTR16)
-			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
-#else
-			lst = e->u.strlist;
-#endif
-			for (j = 0, n = e->listlen; j < n; j++) {
-#if defined(DUK_USE_HEAPPTR16)
-				duk__sweep_string_chain16(heap, lst + j, &count_keep, &count_free);
-#else
-				duk__sweep_string_chain(heap, lst + j, &count_keep, &count_free);
-#endif
-			}
-		}
-	}
-
-	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
-	                 (long) count_free, (long) count_keep));
-	*out_count_keep = count_keep;
-}
-#endif  /* DUK_USE_STRTAB_CHAIN */
-
-#if defined(DUK_USE_STRTAB_PROBE)
-DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep) {
-	duk_hstring *h;
-	duk_uint_fast32_t i;
-#ifdef DUK_USE_DEBUG
-	duk_size_t count_free = 0;
-#endif
-	duk_size_t count_keep = 0;
-
-	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
-
-	for (i = 0; i < heap->st_size; i++) {
-#if defined(DUK_USE_HEAPPTR16)
-		h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
-#else
-		h = heap->strtable[i];
-#endif
-		if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
-			continue;
-		} else if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
-			DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
-			count_keep++;
-			continue;
-		}
-
-#ifdef DUK_USE_DEBUG
-		count_free++;
-#endif
-
-#if defined(DUK_USE_REFERENCE_COUNTING)
-		/* Non-zero refcounts should not happen for unreachable strings,
-		 * because we refcount finalize all unreachable objects which
-		 * should have decreased unreachable string refcounts to zero
-		 * (even for cycles).
-		 */
-		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
-#endif
-
-		DUK_DDD(DUK_DDDPRINT("sweep string, not reachable: %p", (void *) h));
-
-		/* deal with weak references first */
-		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
-
-		/* remove the string (mark DELETED), could also call
-		 * duk_heap_string_remove() but that would be slow and
-		 * pointless because we already know the slot.
-		 */
-#if defined(DUK_USE_HEAPPTR16)
-		heap->strtable16[i] = heap->heapptr_deleted16;
-#else
-		heap->strtable[i] = DUK_STRTAB_DELETED_MARKER(heap);
-#endif
-
-		/* free inner references (these exist e.g. when external
-		 * strings are enabled)
-		 */
-		duk_free_hstring_inner(heap, (duk_hstring *) h);
-
-		/* finally free the struct itself */
-		DUK_FREE(heap, h);
-	}
-
-#ifdef DUK_USE_DEBUG
-	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
-	                 (long) count_free, (long) count_keep));
-#endif
-	*out_count_keep = count_keep;
-}
-#endif  /* DUK_USE_STRTAB_PROBE */
-
-/*
- *  Sweep heap
- */
-
-DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
-	duk_heaphdr *prev;  /* last element that was left in the heap */
-	duk_heaphdr *curr;
-	duk_heaphdr *next;
-#ifdef DUK_USE_DEBUG
-	duk_size_t count_free = 0;
-	duk_size_t count_finalize = 0;
-	duk_size_t count_rescue = 0;
-#endif
-	duk_size_t count_keep = 0;
-
-	DUK_UNREF(flags);
-	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
-
-	prev = NULL;
-	curr = heap->heap_allocated;
-	heap->heap_allocated = NULL;
-	while (curr) {
-		/* Strings and ROM objects are never placed on the heap allocated list. */
-		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
-
-		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
-
-		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
-			/*
-			 *  Reachable object, keep
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("sweep, reachable: %p", (void *) curr));
-
-			if (DUK_HEAPHDR_HAS_FINALIZABLE(curr)) {
-				/*
-				 *  If object has been marked finalizable, move it to the
-				 *  "to be finalized" work list.  It will be collected on
-				 *  the next mark-and-sweep if it is still unreachable
-				 *  after running the finalizer.
-				 */
-
-				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
-				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
-				DUK_DDD(DUK_DDDPRINT("object has finalizer, move to finalization work list: %p", (void *) curr));
-
-#ifdef DUK_USE_DOUBLE_LINKED_HEAP
-				if (heap->finalize_list) {
-					DUK_HEAPHDR_SET_PREV(heap, heap->finalize_list, curr);
-				}
-				DUK_HEAPHDR_SET_PREV(heap, curr, NULL);
-#endif
-				DUK_HEAPHDR_SET_NEXT(heap, curr, heap->finalize_list);
-				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
-				heap->finalize_list = curr;
-#ifdef DUK_USE_DEBUG
-				count_finalize++;
-#endif
-			} else {
-				/*
-				 *  Object will be kept; queue object back to heap_allocated (to tail)
-				 */
-
-				if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
-					/*
-					 *  Object's finalizer was executed on last round, and
-					 *  object has been happily rescued.
-					 */
-
-					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
-					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
-					DUK_DD(DUK_DDPRINT("object rescued during mark-and-sweep finalization: %p", (void *) curr));
-#ifdef DUK_USE_DEBUG
-					count_rescue++;
-#endif
-				} else {
-					/*
-					 *  Plain, boring reachable object.
-					 */
-					DUK_DD(DUK_DDPRINT("keep object: %!iO", curr));
-					count_keep++;
-				}
-
-				if (!heap->heap_allocated) {
-					heap->heap_allocated = curr;
-				}
-				if (prev) {
-					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
-				}
-#ifdef DUK_USE_DOUBLE_LINKED_HEAP
-				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
-#endif
-				DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
-				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
-				prev = curr;
-			}
-
-			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
-			DUK_HEAPHDR_CLEAR_FINALIZED(curr);
-			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
-
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
-
-			curr = next;
-		} else {
-			/*
-			 *  Unreachable object, free
-			 */
-
-			DUK_DDD(DUK_DDDPRINT("sweep, not reachable: %p", (void *) curr));
-
-#if defined(DUK_USE_REFERENCE_COUNTING)
-			/* Non-zero refcounts should not happen because we refcount
-			 * finalize all unreachable objects which should cancel out
-			 * refcounts (even for cycles).
-			 */
-			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
-#endif
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
-
-			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
-				DUK_DDD(DUK_DDDPRINT("finalized object not rescued: %p", (void *) curr));
-			}
-
-			/* Note: object cannot be a finalizable unreachable object, as
-			 * they have been marked temporarily reachable for this round,
-			 * and are handled above.
-			 */
-
-#ifdef DUK_USE_DEBUG
-			count_free++;
-#endif
-
-			/* weak refs should be handled here, but no weak refs for
-			 * any non-string objects exist right now.
-			 */
-
-			/* free object and all auxiliary (non-heap) allocs */
-			duk_heap_free_heaphdr_raw(heap, curr);
-
-			curr = next;
-		}
-	}
-	if (prev) {
-		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
-	}
-	DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
-
-#ifdef DUK_USE_DEBUG
-	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
-	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
-#endif
-	*out_count_keep = count_keep;
-}
-
-/*
- *  Run (object) finalizers in the "to be finalized" work list.
- */
-
-DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags) {
-	duk_heaphdr *curr;
-	duk_heaphdr *next;
-#ifdef DUK_USE_DEBUG
-	duk_size_t count = 0;
-#endif
-	duk_hthread *thr;
-
-	DUK_DD(DUK_DDPRINT("duk__run_object_finalizers: %p", (void *) heap));
-
-	thr = duk__get_temp_hthread(heap);
-	DUK_ASSERT(thr != NULL);
-
-	curr = heap->finalize_list;
-	while (curr) {
-		DUK_DDD(DUK_DDDPRINT("mark-and-sweep finalize: %p", (void *) curr));
-
-		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* only objects have finalizers */
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));                /* flags have been already cleared */
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* No finalizers for ROM objects */
-
-		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
-			 * become reachable (i.e. rescued).  FINALIZED prevents the
-			 * finalizer from being executed again before that.
-			 */
-			duk_hobject_run_finalizer(thr, (duk_hobject *) curr);  /* must never longjmp */
-			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
-		} else {
-			/* Used during heap destruction: don't actually run finalizers
-			 * because we're heading into forced finalization.  Instead,
-			 * queue finalizable objects back to the heap_allocated list.
-			 */
-			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
-		}
-
-		/* queue back to heap_allocated */
-		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
-		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
-
-		curr = next;
-#ifdef DUK_USE_DEBUG
-		count++;
-#endif
-	}
-
-	/* finalize_list will always be processed completely */
-	heap->finalize_list = NULL;
-
-#ifdef DUK_USE_DEBUG
-	DUK_D(DUK_DPRINT("mark-and-sweep finalize objects: %ld finalizers called", (long) count));
-#endif
-}
-
-/*
- *  Object compaction.
- *
- *  Compaction is assumed to never throw an error.
- */
-
-DUK_LOCAL int duk__protected_compact_object(duk_context *ctx) {
-	/* XXX: for threads, compact value stack, call stack, catch stack? */
-
-	duk_hobject *obj = duk_get_hobject(ctx, -1);
-	DUK_ASSERT(obj != NULL);
-	duk_hobject_compact_props((duk_hthread *) ctx, obj);
-	return 0;
-}
-
-#ifdef DUK_USE_DEBUG
-DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {
-#else
-DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
-#endif
-	duk_heaphdr *curr;
-#ifdef DUK_USE_DEBUG
-	duk_size_t old_size, new_size;
-#endif
-	duk_hobject *obj;
-
-	DUK_UNREF(heap);
-
-	curr = start;
-	while (curr) {
-		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
-
-		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
-			goto next;
-		}
-		obj = (duk_hobject *) curr;
-
-#ifdef DUK_USE_DEBUG
-		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
-		                                      DUK_HOBJECT_GET_ASIZE(obj),
-		                                      DUK_HOBJECT_GET_HSIZE(obj));
-#endif
-
-		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
-		duk_push_hobject((duk_context *) thr, obj);
-		/* XXX: disable error handlers for duration of compaction? */
-		duk_safe_call((duk_context *) thr, duk__protected_compact_object, 1, 0);
-
-#ifdef DUK_USE_DEBUG
-		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
-		                                      DUK_HOBJECT_GET_ASIZE(obj),
-		                                      DUK_HOBJECT_GET_HSIZE(obj));
-#endif
-
-#ifdef DUK_USE_DEBUG
-		(*p_count_compact)++;
-		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
-#endif
-
-	 next:
-		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
-#ifdef DUK_USE_DEBUG
-		(*p_count_check)++;
-#endif
-	}
-}
-
-DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
-	/* XXX: which lists should participate?  to be finalized? */
-#ifdef DUK_USE_DEBUG
-	duk_size_t count_check = 0;
-	duk_size_t count_compact = 0;
-	duk_size_t count_bytes_saved = 0;
-#endif
-	duk_hthread *thr;
-
-	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
-
-	thr = duk__get_temp_hthread(heap);
-	DUK_ASSERT(thr != NULL);
-
-#ifdef DUK_USE_DEBUG
-	duk__compact_object_list(heap, thr, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
-	duk__compact_object_list(heap, thr, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk__compact_object_list(heap, thr, heap->refzero_list, &count_check, &count_compact, &count_bytes_saved);
-#endif
-#else
-	duk__compact_object_list(heap, thr, heap->heap_allocated);
-	duk__compact_object_list(heap, thr, heap->finalize_list);
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk__compact_object_list(heap, thr, heap->refzero_list);
-#endif
-#endif
-
-#ifdef DUK_USE_DEBUG
-	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
-	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
-#endif
-}
-
-/*
- *  Assertion helpers.
- */
-
-#ifdef DUK_USE_ASSERTIONS
-DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
-	duk_heaphdr *hdr;
-
-	hdr = heap->heap_allocated;
-	while (hdr) {
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
-		/* may have FINALIZED */
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-	hdr = heap->refzero_list;
-	while (hdr) {
-		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));
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-}
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
-	duk_heaphdr *hdr = heap->heap_allocated;
-	while (hdr) {
-		if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
-		    DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
-			/* An object may be in heap_allocated list with a zero
-			 * refcount if it has just been finalized and is waiting
-			 * to be collected by the next cycle.
-			 */
-		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
-			/* An object may be in heap_allocated list with a zero
-			 * refcount also if it is a temporary object created by
-			 * a finalizer; because finalization now runs inside
-			 * mark-and-sweep, such objects will not be queued to
-			 * refzero_list and will thus appear here with refcount
-			 * zero.
-			 */
-#if 0  /* this case can no longer occur because refcount is unsigned */
-		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) < 0) {
-			DUK_D(DUK_DPRINT("invalid refcount: %ld, %p -> %!O",
-			                 (hdr != NULL ? (long) DUK_HEAPHDR_GET_REFCOUNT(hdr) : (long) 0),
-			                 (void *) hdr, (duk_heaphdr *) hdr));
-			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(hdr) > 0);
-#endif
-		}
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-}
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-#endif  /* DUK_USE_ASSERTIONS */
-
-/*
- *  Finalizer torture.  Do one fake finalizer call which causes side effects
- *  similar to one or more finalizers on actual objects.
- */
-
-#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
-DUK_LOCAL duk_ret_t duk__markandsweep_fake_finalizer(duk_context *ctx) {
-	DUK_D(DUK_DPRINT("fake mark-and-sweep torture finalizer executed"));
-
-	/* Require a lot of stack to force a value stack grow/shrink.
-	 * Recursive mark-and-sweep is prevented by allocation macros
-	 * so this won't trigger another mark-and-sweep.
-	 */
-	duk_require_stack(ctx, 100000);
-
-	/* XXX: do something to force a callstack grow/shrink, perhaps
-	 * just a manual forced resize or a forced relocating realloc?
-	 */
-
-	return 0;
-}
-
-DUK_LOCAL void duk__markandsweep_torture_finalizer(duk_hthread *thr) {
-	duk_context *ctx;
-	duk_int_t rc;
-
-	DUK_ASSERT(thr != NULL);
-	ctx = (duk_context *) thr;
-
-	/* Avoid fake finalization when callstack limit has been reached.
-	 * Otherwise a callstack limit error will be created, then refzero'ed.
-	 */
-	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
-	    thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
-		DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake mark-and-sweep torture finalizer"));
-		return;
-	}
-
-	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
-	duk_push_c_function(ctx, duk__markandsweep_fake_finalizer, 0 /*nargs*/);
-	rc = duk_pcall(ctx, 0 /*nargs*/);
-	DUK_UNREF(rc);  /* ignored */
-	duk_pop(ctx);
-}
-#endif  /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
-
-/*
- *  Main mark-and-sweep function.
- *
- *  'flags' represents the features requested by the caller.  The current
- *  heap->mark_and_sweep_base_flags is ORed automatically into the flags;
- *  the base flags mask typically prevents certain mark-and-sweep operations
- *  to avoid trouble.
- */
-
-DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
-	duk_hthread *thr;
-	duk_size_t count_keep_obj;
-	duk_size_t count_keep_str;
-#ifdef DUK_USE_VOLUNTARY_GC
-	duk_size_t tmp;
-#endif
-
-	/* 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).
-	 */
-
-	/* If thr != NULL, the thr may still be in the middle of
-	 * initialization.
-	 * XXX: Improve the thread viability test.
-	 */
-	thr = duk__get_temp_hthread(heap);
-	if (thr == NULL) {
-		DUK_D(DUK_DPRINT("gc skipped because we don't have a temp thread"));
-
-		/* reset voluntary gc trigger count */
-#ifdef DUK_USE_VOLUNTARY_GC
-		heap->mark_and_sweep_trigger_counter = DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP;
-#endif
-		return 0;  /* OK */
-	}
-
-	/* If debugger is paused, garbage collection is disabled by default. */
-	/* XXX: will need a force flag if garbage collection is triggered
-	 * explicitly during paused state.
-	 */
-#if defined(DUK_USE_DEBUGGER_SUPPORT)
-	if (DUK_HEAP_IS_PAUSED(heap)) {
-		/* Checking this here rather that in memory alloc primitives
-		 * reduces checking code there but means a failed allocation
-		 * will go through a few retries before giving up.  That's
-		 * fine because this only happens during debugging.
-		 */
-		DUK_D(DUK_DPRINT("gc skipped because debugger is paused"));
-		return 0;
-	}
-#endif
-
-	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
-	                 (unsigned long) flags, (unsigned long) (flags | heap->mark_and_sweep_base_flags)));
-
-	flags |= heap->mark_and_sweep_base_flags;
-
-	/*
-	 *  Assertions before
-	 */
-
-#ifdef DUK_USE_ASSERTIONS
-	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
-	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
-	DUK_ASSERT(heap->mark_and_sweep_recursion_depth == 0);
-	duk__assert_heaphdr_flags(heap);
-#ifdef DUK_USE_REFERENCE_COUNTING
-	/* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
-	 * finalizer may trigger a mark-and-sweep.
-	 */
-	duk__assert_valid_refcounts(heap);
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-#endif  /* DUK_USE_ASSERTIONS */
-
-	/*
-	 *  Begin
-	 */
-
-	DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
-
-	/*
-	 *  Mark roots, hoping that recursion limit is not normally hit.
-	 *  If recursion limit is hit, run additional reachability rounds
-	 *  starting from "temproots" until marking is complete.
-	 *
-	 *  Marking happens in two phases: first we mark actual reachability
-	 *  roots (and run "temproots" to complete the process).  Then we
-	 *  check which objects are unreachable and are finalizable; such
-	 *  objects are marked as FINALIZABLE and marked as reachability
-	 *  (and "temproots" is run again to complete the process).
-	 *
-	 *  The heap finalize_list must also be marked as a reachability root.
-	 *  There may be objects on the list from a previous round if the
-	 *  previous run had finalizer skip flag.
-	 */
-
-	duk__mark_roots_heap(heap);               /* main reachability roots */
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk__mark_refzero_list(heap);             /* refzero_list treated as reachability roots */
-#endif
-	duk__mark_temproots_by_heap_scan(heap);   /* temproots */
-
-	duk__mark_finalizable(heap);              /* mark finalizable as reachability roots */
-	duk__mark_finalize_list(heap);            /* mark finalizer work list as reachability roots */
-	duk__mark_temproots_by_heap_scan(heap);   /* temproots */
-
-	/*
-	 *  Sweep garbage and remove marking flags, and move objects with
-	 *  finalizers to the finalizer work list.
-	 *
-	 *  Objects to be swept need to get their refcounts finalized before
-	 *  they are swept.  In other words, their target object refcounts
-	 *  need to be decreased.  This has to be done before freeing any
-	 *  objects to avoid decref'ing dangling pointers (which may happen
-	 *  even without bugs, e.g. with reference loops)
-	 *
-	 *  Because strings don't point to other heap objects, similar
-	 *  finalization is not necessary for strings.
-	 */
-
-	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk__finalize_refcounts(heap);
-#endif
-	duk__sweep_heap(heap, flags, &count_keep_obj);
-#if defined(DUK_USE_STRTAB_CHAIN)
-	duk__sweep_stringtable_chain(heap, &count_keep_str);
-#elif defined(DUK_USE_STRTAB_PROBE)
-	duk__sweep_stringtable_probe(heap, &count_keep_str);
-#else
-#error internal error, invalid strtab options
-#endif
-#ifdef DUK_USE_REFERENCE_COUNTING
-	duk__clear_refzero_list_flags(heap);
-#endif
-	duk__clear_finalize_list_flags(heap);
-
-	/*
-	 *  Object compaction (emergency only).
-	 *
-	 *  Object compaction is a separate step after sweeping, as there is
-	 *  more free memory for it to work with.  Also, currently compaction
-	 *  may insert new objects into the heap allocated list and the string
-	 *  table which we don't want to do during a sweep (the reachability
-	 *  flags of such objects would be incorrect).  The objects inserted
-	 *  are currently:
-	 *
-	 *    - a temporary duk_hbuffer for a new properties allocation
-	 *    - if array part is abandoned, string keys are interned
-	 *
-	 *  The object insertions go to the front of the list, so they do not
-	 *  cause an infinite loop (they are not compacted).
-	 */
-
-	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
-	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
-		duk__compact_objects(heap);
-	}
-
-	/*
-	 *  String table resize check.
-	 *
-	 *  Note: this may silently (and safely) fail if GC is caused by an
-	 *  allocation call in stringtable resize_hash().  Resize_hash()
-	 *  will prevent a recursive call to itself by setting the
-	 *  DUK_MS_FLAG_NO_STRINGTABLE_RESIZE in heap->mark_and_sweep_base_flags.
-	 */
-
-	/* XXX: stringtable emergency compaction? */
-
-	/* XXX: remove this feature entirely? it would only matter for
-	 * emergency GC.  Disable for lowest memory builds.
-	 */
-#if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
-	if (!(flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE)) {
-		DUK_DD(DUK_DDPRINT("resize stringtable: %p", (void *) heap));
-		duk_heap_force_strtab_resize(heap);
-	} else {
-		DUK_D(DUK_DPRINT("stringtable resize skipped because DUK_MS_FLAG_NO_STRINGTABLE_RESIZE is set"));
-	}
-#endif
-
-	/*
-	 *  Finalize objects in the finalization work list.  Finalized
-	 *  objects are queued back to heap_allocated with FINALIZED set.
-	 *
-	 *  Since finalizers may cause arbitrary side effects, they are
-	 *  prevented during string table and object property allocation
-	 *  resizing using the DUK_MS_FLAG_NO_FINALIZERS flag in
-	 *  heap->mark_and_sweep_base_flags.  In this case the objects
-	 *  remain in the finalization work list after mark-and-sweep
-	 *  exits and they may be finalized on the next pass.
-	 *
-	 *  Finalization currently happens inside "MARKANDSWEEP_RUNNING"
-	 *  protection (no mark-and-sweep may be triggered by the
-	 *  finalizers).  As a side effect:
-	 *
-	 *    1) an out-of-memory error inside a finalizer will not
-	 *       cause a mark-and-sweep and may cause the finalizer
-	 *       to fail unnecessarily
-	 *
-	 *    2) any temporary objects whose refcount decreases to zero
-	 *       during finalization will not be put into refzero_list;
-	 *       they can only be collected by another mark-and-sweep
-	 *
-	 *  This is not optimal, but since the sweep for this phase has
-	 *  already happened, this is probably good enough for now.
-	 */
-
-#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
-	/* Cannot simulate individual finalizers because finalize_list only
-	 * contains objects with actual finalizers.  But simulate side effects
-	 * from finalization by doing a bogus function call and resizing the
-	 * stacks.
-	 */
-	if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
-		DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, DUK_MS_FLAG_NO_FINALIZERS is set"));
-	} else if (!(thr->valstack != NULL && thr->callstack != NULL && thr->catchstack != NULL)) {
-		DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, thread not yet viable"));
-	} else {
-		DUK_D(DUK_DPRINT("run mark-and-sweep torture finalizer"));
-		duk__markandsweep_torture_finalizer(thr);
-	}
-#endif  /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
-
-	if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
-		DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
-	} else {
-		duk__run_object_finalizers(heap, flags);
-	}
-
-	/*
-	 *  Finish
-	 */
-
-	DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
-
-	/*
-	 *  Assertions after
-	 */
-
-#ifdef DUK_USE_ASSERTIONS
-	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
-	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
-	DUK_ASSERT(heap->mark_and_sweep_recursion_depth == 0);
-	duk__assert_heaphdr_flags(heap);
-#ifdef DUK_USE_REFERENCE_COUNTING
-	/* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
-	 * finalizer may trigger a mark-and-sweep.
-	 */
-	duk__assert_valid_refcounts(heap);
-#endif  /* DUK_USE_REFERENCE_COUNTING */
-#endif  /* DUK_USE_ASSERTIONS */
-
-	/*
-	 *  Reset trigger counter
-	 */
-
-#ifdef DUK_USE_VOLUNTARY_GC
-	tmp = (count_keep_obj + count_keep_str) / 256;
-	heap->mark_and_sweep_trigger_counter = (duk_int_t) (
-	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
-	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
-	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
-	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->mark_and_sweep_trigger_counter));
-#else
-	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
-	                 (long) count_keep_obj, (long) count_keep_str));
-#endif
-
-	return 0;  /* OK */
-}
-
-#else  /* DUK_USE_MARK_AND_SWEEP */
-
-/* no mark-and-sweep gc */
-
-#endif  /* DUK_USE_MARK_AND_SWEEP */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b26ac36e/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_memory.c
----------------------------------------------------------------------
diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_memory.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_memory.c
deleted file mode 100644
index c0d7030..0000000
--- a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_memory.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- *  Memory allocation handling.
- */
-
-#include "duk_internal.h"
-
-/*
- *  Helpers
- *
- *  The fast path checks are done within a macro to ensure "inlining"
- *  while the slow path actions use a helper (which won't typically be
- *  inlined in size optimized builds).
- */
-
-#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
-#define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { \
-		(heap)->mark_and_sweep_trigger_counter--; \
-		if ((heap)->mark_and_sweep_trigger_counter <= 0) { \
-			duk__run_voluntary_gc(heap); \
-		} \
-	} while (0)
-
-DUK_LOCAL void duk__run_voluntary_gc(duk_heap *heap) {
-	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_DD(DUK_DDPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
-	} else {
-		duk_small_uint_t flags;
-		duk_bool_t rc;
-
-		DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
-		flags = 0;
-		rc = duk_heap_mark_and_sweep(heap, flags);
-		DUK_UNREF(rc);
-	}
-}
-#else
-#define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */
-#endif  /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
-
-/*
- *  Allocate memory with garbage collection
- */
-
-#ifdef DUK_USE_MARK_AND_SWEEP
-DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
-	void *res;
-	duk_bool_t rc;
-	duk_small_int_t i;
-
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
-
-#ifdef DUK_USE_GC_TORTURE
-	/* simulate alloc failure on every alloc (except when mark-and-sweep is running) */
-	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
-		res = NULL;
-		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->alloc_func(heap->heap_udata, size);
-	if (res || size == 0) {
-		/* for zero size allocations NULL is allowed */
-		return res;
-	}
-#ifdef DUK_USE_GC_TORTURE
- skip_attempt:
-#endif
-
-	DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
-
-	/*
-	 *  Avoid a GC if GC is already running.  This can happen at a late
-	 *  stage in a GC when we try to e.g. resize the stringtable
-	 *  or compact objects.
-	 */
-
-	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
-		return NULL;
-	}
-
-	/*
-	 *  Retry with several GC attempts.  Initial attempts are made without
-	 *  emergency mode; later attempts use emergency mode which minimizes
-	 *  memory allocations forcibly.
-	 */
-
-	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
-		duk_small_uint_t flags;
-
-		flags = 0;
-		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
-			flags |= DUK_MS_FLAG_EMERGENCY;
-		}
-
-		rc = duk_heap_mark_and_sweep(heap, flags);
-		DUK_UNREF(rc);
-
-		res = heap->alloc_func(heap->heap_udata, size);
-		if (res) {
-			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
-			                 (long) (i + 1), (long) size));
-			return res;
-		}
-	}
-
-	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
-	return NULL;
-}
-#else  /* DUK_USE_MARK_AND_SWEEP */
-/*
- *  Compared to a direct macro expansion this wrapper saves a few
- *  instructions because no heap dereferencing is required.
- */
-DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	return heap->alloc_func(heap->heap_udata, size);
-}
-#endif  /* DUK_USE_MARK_AND_SWEEP */
-
-DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
-	void *res;
-
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT_DISABLE(size >= 0);
-
-	res = DUK_ALLOC(heap, size);
-	if (res) {
-		/* assume memset with zero size is OK */
-		DUK_MEMZERO(res, size);
-	}
-	return res;
-}
-
-/*
- *  Reallocate memory with garbage collection
- */
-
-#ifdef DUK_USE_MARK_AND_SWEEP
-DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
-	void *res;
-	duk_bool_t rc;
-	duk_small_int_t i;
-
-	DUK_ASSERT(heap != NULL);
-	/* ptr may be NULL */
-	DUK_ASSERT_DISABLE(newsize >= 0);
-
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
-
-#ifdef DUK_USE_GC_TORTURE
-	/* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
-	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
-		res = NULL;
-		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
-	if (res || newsize == 0) {
-		/* for zero size allocations NULL is allowed */
-		return res;
-	}
-#ifdef DUK_USE_GC_TORTURE
- skip_attempt:
-#endif
-
-	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
-
-	/*
-	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
-	 */
-
-	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
-		return NULL;
-	}
-
-	/*
-	 *  Retry with several GC attempts.  Initial attempts are made without
-	 *  emergency mode; later attempts use emergency mode which minimizes
-	 *  memory allocations forcibly.
-	 */
-
-	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
-		duk_small_uint_t flags;
-
-		flags = 0;
-		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
-			flags |= DUK_MS_FLAG_EMERGENCY;
-		}
-
-		rc = duk_heap_mark_and_sweep(heap, flags);
-		DUK_UNREF(rc);
-
-		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
-		if (res || newsize == 0) {
-			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
-			                 (long) (i + 1), (long) newsize));
-			return res;
-		}
-	}
-
-	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
-	return NULL;
-}
-#else  /* DUK_USE_MARK_AND_SWEEP */
-/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
-DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
-	DUK_ASSERT(heap != NULL);
-	/* ptr may be NULL */
-	DUK_ASSERT_DISABLE(newsize >= 0);
-
-	return heap->realloc_func(heap->heap_udata, ptr, newsize);
-}
-#endif  /* DUK_USE_MARK_AND_SWEEP */
-
-/*
- *  Reallocate memory with garbage collection, using a callback to provide
- *  the current allocated pointer.  This variant is used when a mark-and-sweep
- *  (e.g. finalizers) might change the original pointer.
- */
-
-#ifdef DUK_USE_MARK_AND_SWEEP
-DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
-	void *res;
-	duk_bool_t rc;
-	duk_small_int_t i;
-
-	DUK_ASSERT(heap != NULL);
-	DUK_ASSERT_DISABLE(newsize >= 0);
-
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
-
-#ifdef DUK_USE_GC_TORTURE
-	/* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
-	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
-		res = NULL;
-		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
-	if (res || newsize == 0) {
-		/* for zero size allocations NULL is allowed */
-		return res;
-	}
-#ifdef DUK_USE_GC_TORTURE
- skip_attempt:
-#endif
-
-	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
-
-	/*
-	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
-	 */
-
-	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
-		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
-		return NULL;
-	}
-
-	/*
-	 *  Retry with several GC attempts.  Initial attempts are made without
-	 *  emergency mode; later attempts use emergency mode which minimizes
-	 *  memory allocations forcibly.
-	 */
-
-	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
-		duk_small_uint_t flags;
-
-#ifdef DUK_USE_ASSERTIONS
-		void *ptr_pre;  /* ptr before mark-and-sweep */
-		void *ptr_post;
-#endif
-
-#ifdef DUK_USE_ASSERTIONS
-		ptr_pre = cb(heap, ud);
-#endif
-		flags = 0;
-		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
-			flags |= DUK_MS_FLAG_EMERGENCY;
-		}
-
-		rc = duk_heap_mark_and_sweep(heap, flags);
-		DUK_UNREF(rc);
-#ifdef DUK_USE_ASSERTIONS
-		ptr_post = cb(heap, ud);
-		if (ptr_pre != ptr_post) {
-			/* useful for debugging */
-			DUK_DD(DUK_DDPRINT("note: base pointer changed by mark-and-sweep: %p -> %p",
-			                   (void *) ptr_pre, (void *) ptr_post));
-		}
-#endif
-
-		/* Note: key issue here is to re-lookup the base pointer on every attempt.
-		 * The pointer being reallocated may change after every mark-and-sweep.
-		 */
-
-		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
-		if (res || newsize == 0) {
-			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
-			                 (long) (i + 1), (long) newsize));
-			return res;
-		}
-	}
-
-	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
-	return NULL;
-}
-#else  /* DUK_USE_MARK_AND_SWEEP */
-/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
-DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
-	return heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
-}
-#endif  /* DUK_USE_MARK_AND_SWEEP */
-
-/*
- *  Free memory
- */
-
-#ifdef DUK_USE_MARK_AND_SWEEP
-DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
-	DUK_ASSERT(heap != NULL);
-	/* ptr may be NULL */
-
-	/* Must behave like a no-op with NULL and any pointer returned from
-	 * malloc/realloc with zero size.
-	 */
-	heap->free_func(heap->heap_udata, ptr);
-
-	/* Count free operations toward triggering a GC but never actually trigger
-	 * a GC from a free.  Otherwise code which frees internal structures would
-	 * need to put in NULLs at every turn to ensure the object is always in
-	 * consistent state for a mark-and-sweep.
-	 */
-#ifdef DUK_USE_VOLUNTARY_GC
-	heap->mark_and_sweep_trigger_counter--;
-#endif
-}
-#else
-/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
-DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
-	DUK_ASSERT(heap != NULL);
-	/* ptr may be NULL */
-
-	/* Note: must behave like a no-op with NULL and any pointer
-	 * returned from malloc/realloc with zero size.
-	 */
-	heap->free_func(heap->heap_udata, ptr);
-}
-#endif

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b26ac36e/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_misc.c
----------------------------------------------------------------------
diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_misc.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_misc.c
deleted file mode 100644
index f4edd2c..0000000
--- a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_misc.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  Support functions for duk_heap.
- */
-
-#include "duk_internal.h"
-
-#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
-/* arbitrary remove only works with double linked heap, and is only required by
- * reference counting so far.
- */
-DUK_INTERNAL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
-	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
-
-	if (DUK_HEAPHDR_GET_PREV(heap, hdr)) {
-		DUK_HEAPHDR_SET_NEXT(heap, DUK_HEAPHDR_GET_PREV(heap, hdr), DUK_HEAPHDR_GET_NEXT(heap, hdr));
-	} else {
-		heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-	if (DUK_HEAPHDR_GET_NEXT(heap, hdr)) {
-		DUK_HEAPHDR_SET_PREV(heap, DUK_HEAPHDR_GET_NEXT(heap, hdr), DUK_HEAPHDR_GET_PREV(heap, hdr));
-	} else {
-		;
-	}
-
-	/* The prev/next pointers of the removed duk_heaphdr are left as garbage.
-	 * It's up to the caller to ensure they're written before inserting the
-	 * object back.
-	 */
-}
-#endif
-
-DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
-	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
-
-#ifdef DUK_USE_DOUBLE_LINKED_HEAP
-	if (heap->heap_allocated) {
-		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, heap->heap_allocated) == NULL);
-		DUK_HEAPHDR_SET_PREV(heap, heap->heap_allocated, hdr);
-	}
-	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
-#endif
-	DUK_HEAPHDR_SET_NEXT(heap, hdr, heap->heap_allocated);
-	heap->heap_allocated = hdr;
-}
-
-#ifdef DUK_USE_INTERRUPT_COUNTER
-DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
-	duk_hthread *curr_thr;
-
-	DUK_ASSERT(heap != NULL);
-
-	if (new_thr != NULL) {
-		curr_thr = heap->curr_thread;
-		if (curr_thr == NULL) {
-			/* For initial entry use default value; zero forces an
-			 * interrupt before executing the first insturction.
-			 */
-			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
-			new_thr->interrupt_counter = 0;
-			new_thr->interrupt_init = 0;
-		} else {
-			/* Copy interrupt counter/init value state to new thread (if any).
-			 * It's OK for new_thr to be the same as curr_thr.
-			 */
-#if defined(DUK_USE_DEBUG)
-			if (new_thr != curr_thr) {
-				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
-			}
-#endif
-			new_thr->interrupt_counter = curr_thr->interrupt_counter;
-			new_thr->interrupt_init = curr_thr->interrupt_init;
-		}
-	} else {
-		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
-	}
-
-	heap->curr_thread = new_thr;  /* may be NULL */
-}
-#endif  /* DUK_USE_INTERRUPT_COUNTER */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b26ac36e/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_refcount.c
----------------------------------------------------------------------
diff --git a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_refcount.c b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_refcount.c
deleted file mode 100644
index 4580dc1..0000000
--- a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_refcount.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- *  Reference counting implementation.
- */
-
-#include "duk_internal.h"
-
-#ifdef DUK_USE_REFERENCE_COUNTING
-
-#ifndef DUK_USE_DOUBLE_LINKED_HEAP
-#error internal error, reference counting requires a double linked heap
-#endif
-
-/*
- *  Misc
- */
-
-DUK_LOCAL void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
-	/* tail insert: don't disturb head in case refzero is running */
-
-	if (heap->refzero_list != NULL) {
-		duk_heaphdr *hdr_prev;
-
-		hdr_prev = heap->refzero_list_tail;
-		DUK_ASSERT(hdr_prev != NULL);
-		DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(heap, hdr_prev) == NULL);
-
-		DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
-		DUK_HEAPHDR_SET_PREV(heap, hdr, hdr_prev);
-		DUK_HEAPHDR_SET_NEXT(heap, hdr_prev, hdr);
-		DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
-		DUK_ASSERT_HEAPHDR_LINKS(heap, hdr_prev);
-		heap->refzero_list_tail = hdr;
-	} else {
-		DUK_ASSERT(heap->refzero_list_tail == NULL);
-		DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
-		DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
-		DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
-		heap->refzero_list = hdr;
-		heap->refzero_list_tail = hdr;
-	}
-}
-
-/*
- *  Heap object refcount finalization.
- *
- *  When an object is about to be freed, all other objects it refers to must
- *  be decref'd.  Refcount finalization does NOT free the object or its inner
- *  allocations (mark-and-sweep shares these helpers), it just manipulates
- *  the refcounts.
- *
- *  Note that any of the decref's may cause a refcount to drop to zero, BUT
- *  it will not be processed inline; instead, because refzero is already
- *  running, the objects will just be queued to refzero list and processed
- *  later.  This eliminates C recursion.
- */
-
-DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
-	duk_uint_fast32_t i;
-
-	DUK_ASSERT(h);
-	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
-
-	/* XXX: better to get base and walk forwards? */
-
-	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
-		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
-		if (!key) {
-			continue;
-		}
-		duk_heaphdr_decref(thr, (duk_heaphdr *) key);
-		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)) {
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, h, i));
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, h, i));
-		} else {
-			duk_tval_decref(thr, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i));
-		}
-	}
-
-	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
-		duk_tval_decref(thr, DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i));
-	}
-
-	/* hash part is a 'weak reference' and does not contribute */
-
-	duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h));
-
-	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
-		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
-		duk_tval *tv, *tv_end;
-		duk_hobject **funcs, **funcs_end;
-
-		if (DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL) {
-			tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, f);
-			tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, f);
-			while (tv < tv_end) {
-				duk_tval_decref(thr, tv);
-				tv++;
-			}
-
-			funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, f);
-			funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
-			while (funcs < funcs_end) {
-				duk_heaphdr_decref(thr, (duk_heaphdr *) *funcs);
-				funcs++;
-			}
-		} else {
-			/* May happen in some out-of-memory corner cases. */
-			DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping decref"));
-		}
-
-		duk_heaphdr_decref(thr, (duk_heaphdr *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f));
-	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
-		duk_hnativefunction *f = (duk_hnativefunction *) h;
-		DUK_UNREF(f);
-		/* nothing to finalize */
-	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
-		duk_hbufferobject *b = (duk_hbufferobject *) h;
-		if (b->buf) {
-			duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf);
-		}
-	} else if (DUK_HOBJECT_IS_THREAD(h)) {
-		duk_hthread *t = (duk_hthread *) h;
-		duk_tval *tv;
-
-		tv = t->valstack;
-		while (tv < t->valstack_top) {
-			duk_tval_decref(thr, tv);
-			tv++;
-		}
-
-		for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
-			duk_activation *act = t->callstack + i;
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->var_env);
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->lex_env);
-#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->prev_caller);
-#endif
-		}
-
-#if 0  /* nothing now */
-		for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
-			duk_catcher *cat = t->catchstack + i;
-		}
-#endif
-
-		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
-			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->builtins[i]);
-		}
-
-		duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->resumer);
-	}
-}
-
-DUK_INTERNAL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr) {
-	DUK_ASSERT(hdr);
-
-	switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
-	case DUK_HTYPE_OBJECT:
-		duk__refcount_finalize_hobject(thr, (duk_hobject *) hdr);
-		break;
-	case DUK_HTYPE_BUFFER:
-		/* nothing to finalize */
-		break;
-	case DUK_HTYPE_STRING:
-		/* cannot happen: strings are not put into refzero list (they don't even have the next/prev pointers) */
-	default:
-		DUK_UNREACHABLE();
-	}
-}
-
-#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
-DUK_LOCAL duk_ret_t duk__refcount_fake_finalizer(duk_context *ctx) {
-	DUK_UNREF(ctx);
-	DUK_D(DUK_DPRINT("fake refcount torture finalizer executed"));
-#if 0
-	DUK_DD(DUK_DDPRINT("fake torture finalizer for: %!T", duk_get_tval(ctx, 0)));
-#endif
-	/* Require a lot of stack to force a value stack grow/shrink. */
-	duk_require_stack(ctx, 100000);
-
-	/* XXX: do something to force a callstack grow/shrink, perhaps
-	 * just a manual forced resize?
-	 */
-	return 0;
-}
-
-DUK_LOCAL void duk__refcount_run_torture_finalizer(duk_hthread *thr, duk_hobject *obj) {
-	duk_context *ctx;
-	duk_int_t rc;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(obj != NULL);
-	ctx = (duk_context *) thr;
-
-	/* Avoid fake finalization for the duk__refcount_fake_finalizer function
-	 * itself, otherwise we're in infinite recursion.
-	 */
-	if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
-		if (((duk_hnativefunction *) obj)->func == duk__refcount_fake_finalizer) {
-			DUK_DD(DUK_DDPRINT("avoid fake torture finalizer for duk__refcount_fake_finalizer itself"));
-			return;
-		}
-	}
-	/* Avoid fake finalization when callstack limit has been reached.
-	 * Otherwise a callstack limit error will be created, then refzero'ed,
-	 * and we're in an infinite loop.
-	 */
-	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
-	    thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
-		DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake torture finalizer"));
-		return;
-	}
-
-	/* Run fake finalizer.  Avoid creating new refzero queue entries
-	 * so that we are not forced into a forever loop.
-	 */
-	duk_push_c_function(ctx, duk__refcount_fake_finalizer, 1 /*nargs*/);
-	duk_push_hobject(ctx, obj);
-	rc = duk_pcall(ctx, 1);
-	DUK_UNREF(rc);  /* ignored */
-	duk_pop(ctx);
-}
-#endif  /* DUK_USE_REFZERO_FINALIZER_TORTURE */
-
-/*
- *  Refcount memory freeing loop.
- *
- *  Frees objects in the refzero_pending list until the list becomes
- *  empty.  When an object is freed, its references get decref'd and
- *  may cause further objects to be queued for freeing.
- *
- *  This could be expanded to allow incremental freeing: just bail out
- *  early and resume at a future alloc/decref/refzero.
- */
-
-DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr) {
-	duk_heaphdr *h1, *h2;
-	duk_heap *heap;
-	duk_int_t count = 0;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->heap != NULL);
-	heap = thr->heap;
-	DUK_ASSERT(heap != NULL);
-
-	/*
-	 *  Detect recursive invocation
-	 */
-
-	if (DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)) {
-		DUK_DDD(DUK_DDDPRINT("refzero free running, skip run"));
-		return;
-	}
-
-	/*
-	 *  Churn refzero_list until empty
-	 */
-
-	DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap);
-	while (heap->refzero_list) {
-		duk_hobject *obj;
-		duk_bool_t rescued = 0;
-
-		/*
-		 *  Pick an object from the head (don't remove yet).
-		 */
-
-		h1 = heap->refzero_list;
-		obj = (duk_hobject *) h1;
-		DUK_DD(DUK_DDPRINT("refzero processing %p: %!O", (void *) h1, (duk_heaphdr *) h1));
-		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, h1) == NULL);
-		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT);  /* currently, always the case */
-
-#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
-		/* Torture option to shake out finalizer side effect issues:
-		 * make a bogus function call for every finalizable object,
-		 * essentially simulating the case where everything has a
-		 * finalizer.
-		 */
-		DUK_DD(DUK_DDPRINT("refzero torture enabled, fake finalizer"));
-		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
-		DUK_HEAPHDR_PREINC_REFCOUNT(h1);  /* bump refcount to prevent refzero during finalizer processing */
-		duk__refcount_run_torture_finalizer(thr, obj);  /* must never longjmp */
-		DUK_HEAPHDR_PREDEC_REFCOUNT(h1);  /* remove artificial bump */
-		DUK_ASSERT_DISABLE(h1->h_refcount >= 0);  /* refcount is unsigned, so always true */
-#endif
-
-		/*
-		 *  Finalizer check.
-		 *
-		 *  Note: running a finalizer may have arbitrary side effects, e.g.
-		 *  queue more objects on refzero_list (tail), or even trigger a
-		 *  mark-and-sweep.
-		 *
-		 *  Note: quick reject check should match vast majority of
-		 *  objects and must be safe (not throw any errors, ever).
-		 */
-
-		/* An object may have FINALIZED here if it was finalized by mark-and-sweep
-		 * on a previous run and refcount then decreased to zero.  We won't run the
-		 * finalizer again here.
-		 */
-
-		/* A finalizer is looked up from the object and up its prototype chain
-		 * (which allows inherited finalizers).
-		 */
-		if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
-			DUK_DDD(DUK_DDDPRINT("object has a finalizer, run it"));
-
-			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
-			DUK_HEAPHDR_PREINC_REFCOUNT(h1);  /* bump refcount to prevent refzero during finalizer processing */
-
-			duk_hobject_run_finalizer(thr, obj);  /* must never longjmp */
-			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));  /* duk_hobject_run_finalizer() sets */
-
-			DUK_HEAPHDR_PREDEC_REFCOUNT(h1);  /* remove artificial bump */
-			DUK_ASSERT_DISABLE(h1->h_refcount >= 0);  /* refcount is unsigned, so always true */
-
-			if (DUK_HEAPHDR_GET_REFCOUNT(h1) != 0) {
-				DUK_DDD(DUK_DDDPRINT("-> object refcount after finalization non-zero, object will be rescued"));
-				rescued = 1;
-			} else {
-				DUK_DDD(DUK_DDDPRINT("-> object refcount still zero after finalization, object will be freed"));
-			}
-		}
-
-		/* Refzero head is still the same.  This is the case even if finalizer
-		 * inserted more refzero objects; they are inserted to the tail.
-		 */
-		DUK_ASSERT(h1 == heap->refzero_list);
-
-		/*
-		 *  Remove the object from the refzero list.  This cannot be done
-		 *  before a possible finalizer has been executed; the finalizer
-		 *  may trigger a mark-and-sweep, and mark-and-sweep must be able
-		 *  to traverse a complete refzero_list.
-		 */
-
-		h2 = DUK_HEAPHDR_GET_NEXT(heap, h1);
-		if (h2) {
-			DUK_HEAPHDR_SET_PREV(heap, h2, NULL);  /* not strictly necessary */
-			heap->refzero_list = h2;
-		} else {
-			heap->refzero_list = NULL;
-			heap->refzero_list_tail = NULL;
-		}
-
-		/*
-		 *  Rescue or free.
-		 */
-
-		if (rescued) {
-			/* yes -> move back to heap allocated */
-			DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
-			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h1));
-			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));
-			DUK_HEAPHDR_CLEAR_FINALIZED(h1);
-			h2 = heap->heap_allocated;
-			DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
-			if (h2) {
-				DUK_HEAPHDR_SET_PREV(heap, h2, h1);
-			}
-			DUK_HEAPHDR_SET_NEXT(heap, h1, h2);
-			DUK_ASSERT_HEAPHDR_LINKS(heap, h1);
-			DUK_ASSERT_HEAPHDR_LINKS(heap, h2);
-			heap->heap_allocated = h1;
-		} else {
-			/* no -> decref members, then free */
-			duk__refcount_finalize_hobject(thr, obj);
-			duk_heap_free_heaphdr_raw(heap, h1);
-		}
-
-		count++;
-	}
-	DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap);
-
-	DUK_DDD(DUK_DDDPRINT("refzero processed %ld objects", (long) count));
-
-	/*
-	 *  Once the whole refzero cascade has been freed, check for
-	 *  a voluntary mark-and-sweep.
-	 */
-
-#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
-	/* 'count' is more or less comparable to normal trigger counter update
-	 * which happens in memory block (re)allocation.
-	 */
-	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));
-	}
-#endif  /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
-}
-
-/*
- *  Incref and decref functions.
- *
- *  Decref may trigger immediate refzero handling, which may free and finalize
- *  an arbitrary number of objects.
- *
- */
-
-DUK_INTERNAL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
-	duk_heap *heap;
-
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(h != NULL);
-
-	heap = thr->heap;
-	DUK_DDD(DUK_DDDPRINT("refzero %p: %!O", (void *) h, (duk_heaphdr *) h));
-
-	/*
-	 *  Refzero handling is skipped entirely if (1) mark-and-sweep is
-	 *  running or (2) execution is paused in the debugger.  The objects
-	 *  are left in the heap, and will be freed by mark-and-sweep or
-	 *  eventual heap destruction.
-	 *
-	 *  This is necessary during mark-and-sweep because refcounts are also
-	 *  updated during the sweep phase (otherwise objects referenced by a
-	 *  swept object would have incorrect refcounts) which then calls here.
-	 *  This could be avoided by using separate decref macros in
-	 *  mark-and-sweep; however, mark-and-sweep also calls finalizers which
-	 *  would use the ordinary decref macros anyway and still call this
-	 *  function.
-	 *
-	 *  This check must be enabled also when mark-and-sweep support has been
-	 *  disabled: the flag is also used in heap destruction when running
-	 *  finalizers for remaining objects, and the flag prevents objects from
-	 *  being moved around in heap linked lists.
-	 */
-
-	/* XXX: ideally this would be just one flag (maybe a derived one) so
-	 * that a single bit test is sufficient to check the condition.
-	 */
-#if defined(DUK_USE_DEBUGGER_SUPPORT)
-	if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) || DUK_HEAP_IS_PAUSED(heap))) {
-#else
-	if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap))) {
-#endif
-		DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h));
-		return;
-	}
-
-	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
-	case DUK_HTYPE_STRING:
-		/*
-		 *  Strings have no internal references but do have "weak"
-		 *  references in the string cache.  Also note that strings
-		 *  are not on the heap_allocated list like other heap
-		 *  elements.
-		 */
-
-		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
-		duk_heap_string_remove(heap, (duk_hstring *) h);
-		duk_heap_free_heaphdr_raw(heap, h);
-		break;
-
-	case DUK_HTYPE_OBJECT:
-		/*
-		 *  Objects have internal references.  Must finalize through
-		 *  the "refzero" work list.
-		 */
-
-		duk_heap_remove_any_from_heap_allocated(heap, h);
-		duk__queue_refzero(heap, h);
-		duk__refzero_free_pending(thr);
-		break;
-
-	case DUK_HTYPE_BUFFER:
-		/*
-		 *  Buffers have no internal references.  However, a dynamic
-		 *  buffer has a separate allocation for the buffer.  This is
-		 *  freed by duk_heap_free_heaphdr_raw().
-		 */
-
-		duk_heap_remove_any_from_heap_allocated(heap, h);
-		duk_heap_free_heaphdr_raw(heap, h);
-		break;
-
-	default:
-		DUK_D(DUK_DPRINT("invalid heap type in decref: %ld", (long) DUK_HEAPHDR_GET_TYPE(h)));
-		DUK_UNREACHABLE();
-	}
-}
-
-#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
-DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
-	DUK_ASSERT(tv != NULL);
-
-	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(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);
-	}
-}
-#endif
-
-#if 0  /* unused */
-DUK_INTERNAL void duk_tval_incref_allownull(duk_tval *tv) {
-	if (tv == NULL) {
-		return;
-	}
-	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(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);
-	}
-}
-#endif
-
-DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(tv != NULL);
-
-	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(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);
-	}
-}
-
-#if 0  /* unused */
-DUK_INTERNAL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv) {
-	DUK_ASSERT(thr != NULL);
-
-	if (tv == NULL) {
-		return;
-	}
-	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(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);
-	}
-}
-#endif
-
-#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
-DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
-	DUK_ASSERT(h != NULL);
-	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
-
-	DUK_HEAPHDR_PREINC_REFCOUNT(h);
-}
-#endif
-
-#if 0  /* unused */
-DUK_INTERNAL void duk_heaphdr_incref_allownull(duk_heaphdr *h) {
-	if (h == NULL) {
-		return;
-	}
-	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
-
-	DUK_HEAPHDR_PREINC_REFCOUNT(h);
-}
-#endif
-
-DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->heap != NULL);
-	DUK_ASSERT(h != NULL);
-	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-	DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
-
-#if defined(DUK_USE_ROM_OBJECTS)
-	if (DUK_HEAPHDR_HAS_READONLY(h)) {
-		return;
-	}
-#endif
-	if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
-		return;
-	}
-	duk_heaphdr_refzero(thr, h);
-}
-
-DUK_INTERNAL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h) {
-	DUK_ASSERT(thr != NULL);
-	DUK_ASSERT(thr->heap != NULL);
-
-	if (h == NULL) {
-		return;
-	}
-	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
-
-#if defined(DUK_USE_ROM_OBJECTS)
-	if (DUK_HEAPHDR_HAS_READONLY(h)) {
-		return;
-	}
-#endif
-	DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
-	if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
-		return;
-	}
-	duk_heaphdr_refzero(thr, h);
-}
-
-#else
-
-/* no refcounting */
-
-#endif  /* DUK_USE_REFERENCE_COUNTING */


Mime
View raw message