http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b8103f03/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/b8103f03/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/b8103f03/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/b8103f03/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/b8103f03/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 */

Reply via email to