http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_alloc.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_alloc.c
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_alloc.c
new file mode 100644
index 0000000..425ad33
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_alloc.c
@@ -0,0 +1,132 @@
+/*
+ *  duk_hbuffer allocation and freeing.
+ */
+
+#include "duk_internal.h"
+
+/* Allocate a new duk_hbuffer of a certain type and return a pointer to it
+ * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
+ * allocation successful).
+ */
+DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, 
duk_small_uint_t flags, void **out_bufdata) {
+       duk_hbuffer *res = NULL;
+       duk_size_t header_size;
+       duk_size_t alloc_size;
+
+       DUK_ASSERT(heap != NULL);
+       DUK_ASSERT(out_bufdata != NULL);
+
+       DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
+
+       /* Size sanity check.  Should not be necessary because caller is
+        * required to check this, but we don't want to cause a segfault
+        * if the size wraps either in duk_size_t computation or when
+        * storing the size in a 16-bit field.
+        */
+       if (size > DUK_HBUFFER_MAX_BYTELEN) {
+               DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", 
(long) size));
+               return NULL;  /* no need to write 'out_bufdata' */
+       }
+
+       if (flags & DUK_BUF_FLAG_EXTERNAL) {
+               header_size = sizeof(duk_hbuffer_external);
+               alloc_size = sizeof(duk_hbuffer_external);
+       } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
+               header_size = sizeof(duk_hbuffer_dynamic);
+               alloc_size = sizeof(duk_hbuffer_dynamic);
+       } else {
+               header_size = sizeof(duk_hbuffer_fixed);
+               alloc_size = sizeof(duk_hbuffer_fixed) + size;
+               DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no 
wrapping */
+       }
+
+       res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
+       if (!res) {
+               goto error;
+       }
+
+       /* zero everything unless requested not to do so */
+#if defined(DUK_USE_ZERO_BUFFER_DATA)
+       DUK_MEMZERO((void *) res,
+                   (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
+#else
+       DUK_MEMZERO((void *) res, header_size);
+#endif
+
+       if (flags & DUK_BUF_FLAG_EXTERNAL) {
+               duk_hbuffer_external *h;
+               h = (duk_hbuffer_external *) res;
+               DUK_UNREF(h);
+               *out_bufdata = NULL;
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+#if defined(DUK_USE_HEAPPTR16)
+/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
+#else
+               DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
+#endif
+#endif
+               DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
+       } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
+               duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
+               void *ptr;
+
+               if (size > 0) {
+                       DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc 
external with size zero */
+                       DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, 
alloc actual buffer"));
+#ifdef DUK_USE_ZERO_BUFFER_DATA
+                       ptr = DUK_ALLOC_ZEROED(heap, size);
+#else
+                       ptr = DUK_ALLOC(heap, size);
+#endif
+                       if (!ptr) {
+                               /* Because size > 0, NULL check is correct */
+                               goto error;
+                       }
+                       *out_bufdata = ptr;
+
+                       DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
+               } else {
+                       *out_bufdata = NULL;
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+#if defined(DUK_USE_HEAPPTR16)
+/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
+#else
+                       DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
+#endif
+#endif
+                       DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == 
NULL);
+               }
+       } else {
+               *out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
+       }
+
+       DUK_HBUFFER_SET_SIZE(res, size);
+
+       DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
+       if (flags & DUK_BUF_FLAG_DYNAMIC) {
+               DUK_HBUFFER_SET_DYNAMIC(res);
+               if (flags & DUK_BUF_FLAG_EXTERNAL) {
+                       DUK_HBUFFER_SET_EXTERNAL(res);
+               }
+       } else {
+               DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
+       }
+        DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
+
+       DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
+       return res;
+
+ error:
+       DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
+
+       DUK_FREE(heap, res);
+       return NULL;  /* no need to write 'out_bufdata' */
+}
+
+/* For indirect allocs. */
+
+DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
+       duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
+       DUK_UNREF(heap);
+       return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_ops.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_ops.c
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_ops.c
new file mode 100644
index 0000000..4cdf598
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbuffer_ops.c
@@ -0,0 +1,82 @@
+/*
+ *  duk_hbuffer operations such as resizing and inserting/appending data to
+ *  a dynamic buffer.
+ *
+ *  Append operations append to the end of the buffer and they are relatively
+ *  efficient: the buffer is grown with a "spare" part relative to the buffer
+ *  size to minimize reallocations.  Insert operations need to move existing
+ *  data forward in the buffer with memmove() and are not very efficient.
+ *  They are used e.g. by the regexp compiler to "backpatch" regexp bytecode.
+ */
+
+#include "duk_internal.h"
+
+/*
+ *  Resizing
+ */
+
+DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic 
*buf, duk_size_t new_size) {
+       void *res;
+       duk_size_t prev_size;
+
+       DUK_ASSERT(thr != NULL);
+       DUK_ASSERT(buf != NULL);
+       DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
+       DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
+
+       /*
+        *  Maximum size check
+        */
+
+       if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
+               DUK_ERROR_RANGE(thr, "buffer too long");
+       }
+
+       /*
+        *  Note: use indirect realloc variant just in case mark-and-sweep
+        *  (finalizers) might resize this same buffer during garbage
+        *  collection.
+        */
+
+       res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, 
(void *) buf, new_size);
+       if (res != NULL || new_size == 0) {
+               /* 'res' may be NULL if new allocation size is 0. */
+
+               DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
+                                    (void *) 
DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
+                                    (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
+                                    (void *) res,
+                                    (long) new_size));
+
+               /*
+                *  The entire allocated buffer area, regardless of actual used
+                *  size, is kept zeroed in resizes for simplicity.  If the 
buffer
+                *  is grown, zero the new part.
+                */
+
+               prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
+               if (new_size > prev_size) {
+                       DUK_ASSERT(new_size - prev_size > 0);
+#ifdef DUK_USE_ZERO_BUFFER_DATA
+                       DUK_MEMZERO((void *) ((char *) res + prev_size),
+                                   (duk_size_t) (new_size - prev_size));
+#endif
+               }
+
+               DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
+               DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
+       } else {
+               DUK_ERROR_ALLOC_DEFMSG(thr);
+       }
+
+       DUK_ASSERT(res != NULL || new_size == 0);
+}
+
+DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic 
*buf) {
+       DUK_ASSERT(thr != NULL);
+       DUK_ASSERT(buf != NULL);
+       DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
+       DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
+
+       duk_hbuffer_resize(thr, buf, 0);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject.h
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject.h
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject.h
new file mode 100644
index 0000000..dd93902
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject.h
@@ -0,0 +1,133 @@
+/*
+ *  Heap Buffer object representation.  Used for all Buffer variants.
+ */
+
+#ifndef DUK_HBUFFEROBJECT_H_INCLUDED
+#define DUK_HBUFFEROBJECT_H_INCLUDED
+
+/* All element accessors are host endian now (driven by TypedArray spec). */
+#define DUK_HBUFFEROBJECT_ELEM_UINT8           0
+#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED    1
+#define DUK_HBUFFEROBJECT_ELEM_INT8            2
+#define DUK_HBUFFEROBJECT_ELEM_UINT16          3
+#define DUK_HBUFFEROBJECT_ELEM_INT16           4
+#define DUK_HBUFFEROBJECT_ELEM_UINT32          5
+#define DUK_HBUFFEROBJECT_ELEM_INT32           6
+#define DUK_HBUFFEROBJECT_ELEM_FLOAT32         7
+#define DUK_HBUFFEROBJECT_ELEM_FLOAT64         8
+#define DUK_HBUFFEROBJECT_ELEM_MAX             8
+
+#define DUK_ASSERT_HBUFFEROBJECT_VALID(h) do { \
+               DUK_ASSERT((h) != NULL); \
+               DUK_ASSERT((h)->shift <= 3); \
+               DUK_ASSERT((h)->elem_type <= DUK_HBUFFEROBJECT_ELEM_MAX); \
+               DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_UINT8) || \
+                          ((h)->shift == 0 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) || \
+                          ((h)->shift == 0 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_INT8) || \
+                          ((h)->shift == 1 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_UINT16) || \
+                          ((h)->shift == 1 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_INT16) || \
+                          ((h)->shift == 2 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_UINT32) || \
+                          ((h)->shift == 2 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_INT32) || \
+                          ((h)->shift == 2 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_FLOAT32) || \
+                          ((h)->shift == 3 && (h)->elem_type == 
DUK_HBUFFEROBJECT_ELEM_FLOAT64)); \
+               DUK_ASSERT((h)->is_view == 0 || (h)->is_view == 1); \
+               DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) (h))); \
+               if ((h)->buf == NULL) { \
+                       DUK_ASSERT((h)->offset == 0); \
+                       DUK_ASSERT((h)->length == 0); \
+               } else { \
+                       /* No assertions for offset or length; in particular, \
+                        * it's OK for length to be longer than underlying \
+                        * buffer.  Just ensure they don't wrap when added. \
+                        */ \
+                       DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
+               } \
+       } while (0)
+
+/* Get the current data pointer (caller must ensure buf != NULL) as a
+ * duk_uint8_t ptr.
+ */
+#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap,h) \
+       (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+       (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + 
(h)->offset))
+
+/* True if slice is full, i.e. offset is zero and length covers the entire
+ * buffer.  This status may change independently of the duk_hbufferobject if
+ * the underlying buffer is dynamic and changes without the hbufferobject
+ * being changed.
+ */
+#define DUK_HBUFFEROBJECT_FULL_SLICE(h) \
+       (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+       ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+/* Validate that the whole slice [0,length[ is contained in the underlying
+ * buffer.  Caller must ensure 'buf' != NULL.
+ */
+#define DUK_HBUFFEROBJECT_VALID_SLICE(h) \
+       (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+       ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+/* Validate byte read/write for virtual 'offset', i.e. check that the
+ * offset, taking into account h->offset, is within the underlying
+ * buffer size.  This is a safety check which is needed to ensure
+ * that even a misconfigured duk_hbufferobject never causes memory
+ * unsafe behavior (e.g. if an underlying dynamic buffer changes
+ * after being setup).  Caller must ensure 'buf' != NULL.
+ */
+#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_INCL(h,off) \
+       (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+       ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h,off) \
+       (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
+       ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
+
+/* Clamp an input byte length (already assumed to be within the nominal
+ * duk_hbufferobject 'length') to the current dynamic buffer limits to
+ * yield a byte length limit that's safe for memory accesses.  This value
+ * can be invalidated by any side effect because it may trigger a user
+ * callback that resizes the underlying buffer.
+ */
+#define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h,len) \
+       (DUK_ASSERT_EXPR((h) != NULL), \
+       duk_hbufferobject_clamp_bytelength((h), (len)))
+
+struct duk_hbufferobject {
+       /* Shared object part. */
+       duk_hobject obj;
+
+       /* Underlying buffer (refcounted), may be NULL. */
+       duk_hbuffer *buf;
+
+       /* Slice and accessor information.
+        *
+        * Because the underlying buffer may be dynamic, these may be
+        * invalidated by the buffer being modified so that both offset
+        * and length should be validated before every access.  Behavior
+        * when the underlying buffer has changed doesn't need to be clean:
+        * virtual 'length' doesn't need to be affected, reads can return
+        * zero/NaN, and writes can be ignored.
+        *
+        * Note that a data pointer cannot be precomputed because 'buf' may
+        * be dynamic and its pointer unstable.
+        */
+
+       duk_uint_t offset;       /* byte offset to buf */
+       duk_uint_t length;       /* byte index limit for element access, 
exclusive */
+       duk_uint8_t shift;       /* element size shift:
+                                 *   0 = u8/i8
+                                 *   1 = u16/i16
+                                 *   2 = u32/i32/float
+                                 *   3 = double
+                                 */
+       duk_uint8_t elem_type;   /* element type */
+       duk_uint8_t is_view;
+};
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL_DECL duk_uint_t 
duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len);
+#endif
+DUK_INTERNAL_DECL void duk_hbufferobject_push_validated_read(duk_context *ctx, 
duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
+DUK_INTERNAL_DECL void duk_hbufferobject_validated_write(duk_context *ctx, 
duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
+
+#endif  /* DUK_HBUFFEROBJECT_H_INCLUDED */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject_misc.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject_misc.c
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject_misc.c
new file mode 100644
index 0000000..f692918
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hbufferobject_misc.c
@@ -0,0 +1,20 @@
+#include "duk_internal.h"
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject 
*h_bufobj, duk_uint_t len) {
+       duk_uint_t buf_size;
+       duk_uint_t buf_avail;
+
+       DUK_ASSERT(h_bufobj != NULL);
+       DUK_ASSERT(h_bufobj->buf != NULL);
+
+       buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
+       if (h_bufobj->offset > buf_size) {
+               /* Slice starting point is beyond current length. */
+               return 0;
+       }
+       buf_avail = buf_size - h_bufobj->offset;
+
+       return buf_avail >= len ? len : buf_avail;
+}
+#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hcompiledfunction.h
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hcompiledfunction.h
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hcompiledfunction.h
new file mode 100644
index 0000000..04b9ea1
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_hcompiledfunction.h
@@ -0,0 +1,239 @@
+/*
+ *  Heap compiled function (Ecmascript function) representation.
+ *
+ *  There is a single data buffer containing the Ecmascript function's
+ *  bytecode, constants, and inner functions.
+ */
+
+#ifndef DUK_HCOMPILEDFUNCTION_H_INCLUDED
+#define DUK_HCOMPILEDFUNCTION_H_INCLUDED
+
+/*
+ *  Field accessor macros
+ */
+
+/* XXX: casts could be improved, especially for GET/SET DATA */
+
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
+       ((duk_hbuffer_fixed *) (void *) 
DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
+#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
+               (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void 
*) (v)); \
+       } while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h)  \
+       ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, 
(h)->funcs16)))
+#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v)  do { \
+               (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void 
*) (v)); \
+       } while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h)  \
+       ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, 
(h)->bytecode16)))
+#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v)  do { \
+               (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, 
(void *) (v)); \
+       } while (0)
+#else
+#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
+       ((duk_hbuffer_fixed *) (void *) (h)->data)
+#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
+               (h)->data = (duk_hbuffer *) (v); \
+       } while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h)  \
+       ((h)->funcs)
+#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v)  do { \
+               (h)->funcs = (v); \
+       } while (0)
+#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h)  \
+       ((h)->bytecode)
+#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v)  do { \
+               (h)->bytecode = (v); \
+       } while (0)
+#endif
+
+/*
+ *  Accessor macros for function specific data areas
+ */
+
+/* Note: assumes 'data' is always a fixed buffer */
+#define DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE(heap,h)  \
+       DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), 
DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h)))
+
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap,h)  \
+       ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), 
(h)))
+
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap,h)  \
+       DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))
+
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap,h)  \
+       DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))
+
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap,h)  \
+       ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h)))
+
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap,h)  \
+       ((duk_hobject **) (void *) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), 
(h)))
+
+/* XXX: double evaluation of DUK_HCOMPILEDFUNCTION_GET_DATA() */
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap,h)  \
+       ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), 
DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \
+                       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) 
DUK_HCOMPILEDFUNCTION_GET_DATA((heap), h))))
+
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap,h)  \
+       ( \
+        (duk_size_t) \
+        ( \
+          ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END((heap), 
(h))) - \
+          ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE((heap), 
(h))) \
+        ) \
+       )
+
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(heap,h)  \
+       ( \
+        (duk_size_t) \
+        ( \
+          ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END((heap), 
(h))) - \
+          ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((heap), 
(h))) \
+        ) \
+       )
+
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap,h)  \
+       ( \
+        (duk_size_t) \
+        ( \
+          ((const duk_uint8_t *) 
DUK_HCOMPILEDFUNCTION_GET_CODE_END((heap),(h))) - \
+          ((const duk_uint8_t *) 
DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((heap),(h))) \
+        ) \
+       )
+
+#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap,h)  \
+       ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE((heap), (h)) / 
sizeof(duk_tval)))
+
+#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap,h)  \
+       ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE((heap), (h)) / 
sizeof(duk_hobject *)))
+
+#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap,h)  \
+       ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE((heap), (h)) / 
sizeof(duk_instr_t)))
+
+
+/*
+ *  Main struct
+ */
+
+struct duk_hcompiledfunction {
+       /* shared object part */
+       duk_hobject obj;
+
+       /*
+        *  Pointers to function data area for faster access.  Function
+        *  data is a buffer shared between all closures of the same
+        *  "template" function.  The data buffer is always fixed (non-
+        *  dynamic, hence stable), with a layout as follows:
+        *
+        *    constants (duk_tval)
+        *    inner functions (duk_hobject *)
+        *    bytecode (duk_instr_t)
+        *
+        *  Note: bytecode end address can be computed from 'data' buffer
+        *  size.  It is not strictly necessary functionally, assuming
+        *  bytecode never jumps outside its allocated area.  However,
+        *  it's a safety/robustness feature for avoiding the chance of
+        *  executing random data as bytecode due to a compiler error.
+        *
+        *  Note: values in the data buffer must be incref'd (they will
+        *  be decref'd on release) for every compiledfunction referring
+        *  to the 'data' element.
+        */
+
+       /* Data area, fixed allocation, stable data ptrs. */
+#if defined(DUK_USE_HEAPPTR16)
+       duk_uint16_t data16;
+#else
+       duk_hbuffer *data;
+#endif
+
+       /* No need for constants pointer (= same as data).
+        *
+        * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
+        * 4-byte aligned because 'constants' are duk_tvals.  For now the
+        * inner function pointers are not compressed, so that 'bytecode' will
+        * also be 4-byte aligned.
+        */
+#if defined(DUK_USE_HEAPPTR16)
+       duk_uint16_t funcs16;
+       duk_uint16_t bytecode16;
+#else
+       duk_hobject **funcs;
+       duk_instr_t *bytecode;
+#endif
+
+       /*
+        *  'nregs' registers are allocated on function entry, at most 'nargs'
+        *  are initialized to arguments, and the rest to undefined.  Arguments
+        *  above 'nregs' are not mapped to registers.  All registers in the
+        *  active stack range must be initialized because they are GC 
reachable.
+        *  'nargs' is needed so that if the function is given more than 'nargs'
+        *  arguments, the additional arguments do not 'clobber' registers
+        *  beyond 'nregs' which must be consistently initialized to undefined.
+        *
+        *  Usually there is no need to know which registers are mapped to
+        *  local variables.  Registers may be allocated to variable in any
+        *  way (even including gaps).  However, a register-variable mapping
+        *  must be the same for the duration of the function execution and
+        *  the register cannot be used for anything else.
+        *
+        *  When looking up variables by name, the '_Varmap' map is used.
+        *  When an activation closes, registers mapped to arguments are
+        *  copied into the environment record based on the same map.  The
+        *  reverse map (from register to variable) is not currently needed
+        *  at run time, except for debugging, so it is not maintained.
+        */
+
+       duk_uint16_t nregs;                /* regs to allocate */
+       duk_uint16_t nargs;                /* number of arguments allocated to 
regs */
+
+       /*
+        *  Additional control information is placed into the object itself
+        *  as internal properties to avoid unnecessary fields for the
+        *  majority of functions.  The compiler tries to omit internal
+        *  control fields when possible.
+        *
+        *  Function templates:
+        *
+        *    {
+        *      name: "func",    // declaration, named function expressions
+        *      fileName: <debug info for creating nice errors>
+        *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
+        *      _Formals: [ "arg1", "arg2" ],
+        *      _Source: "function func(arg1, arg2) { ... }",
+        *      _Pc2line: <debug info for pc-to-line mapping>,
+        *    }
+        *
+        *  Function instances:
+        *
+        *    {
+        *      length: 2,
+        *      prototype: { constructor: <func> },
+        *      caller: <thrower>,
+        *      arguments: <thrower>,
+        *      name: "func",    // declaration, named function expressions
+        *      fileName: <debug info for creating nice errors>
+        *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
+        *      _Formals: [ "arg1", "arg2" ],
+        *      _Source: "function func(arg1, arg2) { ... }",
+        *      _Pc2line: <debug info for pc-to-line mapping>,
+        *      _Varenv: <variable environment of closure>,
+        *      _Lexenv: <lexical environment of closure (if differs from 
_Varenv)>
+        *    }
+        *
+        *  More detailed description of these properties can be found
+        *  in the documentation.
+        */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+       /* Line number range for function.  Needed during debugging to
+        * determine active breakpoints.
+        */
+       duk_uint32_t start_line;
+       duk_uint32_t end_line;
+#endif
+};
+
+#endif  /* DUK_HCOMPILEDFUNCTION_H_INCLUDED */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap.h
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap.h
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap.h
new file mode 100644
index 0000000..5f96b1a
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap.h
@@ -0,0 +1,596 @@
+/*
+ *  Heap structure.
+ *
+ *  Heap contains allocated heap objects, interned strings, and built-in
+ *  strings for one or more threads.
+ */
+
+#ifndef DUK_HEAP_H_INCLUDED
+#define DUK_HEAP_H_INCLUDED
+
+/* alloc function typedefs in duktape.h */
+
+/*
+ *  Heap flags
+ */
+
+#define DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING                     (1 << 0)  /* 
mark-and-sweep is currently running */
+#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1 << 1)  /* 
mark-and-sweep marking reached a recursion limit and must use multi-pass 
marking */
+#define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING                     (1 << 2)  /* 
refcount code is processing refzero list */
+#define DUK_HEAP_FLAG_ERRHANDLER_RUNNING                       (1 << 3)  /* an 
error handler (user callback to augment/replace error) is running */
+#define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1 << 4)  /* 
executor interrupt running (used to avoid nested interrupts) */
+#define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1 << 5)  /* 
heap destruction ongoing, finalizer rescue no longer possible */
+
+#define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
+#define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
+               (heap)->flags |= (bits); \
+       } while (0)
+#define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
+               (heap)->flags &= ~(bits); \
+       } while (0)
+
+#define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)            
DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
+#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   
DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
+#define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)            
DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
+#define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap)              
DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
+#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               
DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              
DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
+
+#define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap)            
DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
+#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   
DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
+#define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap)            
DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
+#define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap)              
DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
+#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               
DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              
DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
+
+#define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap)          
DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
+#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) 
DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
+#define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap)          
DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
+#define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap)            
DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
+#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             
DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            
DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
+
+/*
+ *  Longjmp types, also double as identifying continuation type for a rethrow 
(in 'finally')
+ */
+
+#define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
+#define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
+#define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> 
error / normal */
+#define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> 
resumee thread, iserror -> error/normal */
+#define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type 
to indicate a break continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type 
to indicate a continue continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type 
to indicate a return continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a 
normal continuation (for ENDFIN) */
+
+/*
+ *  Mark-and-sweep flags
+ *
+ *  These are separate from heap level flags now but could be merged.
+ *  The heap structure only contains a 'base mark-and-sweep flags'
+ *  field and the GC caller can impose further flags.
+ */
+
+#define DUK_MS_FLAG_EMERGENCY                (1 << 0)   /* emergency mode: try 
extra hard */
+#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE    (1 << 1)   /* don't resize 
stringtable (but may sweep it); needed during stringtable resize */
+#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1 << 2)   /* don't compact 
objects; needed during object property allocation resize */
+#define DUK_MS_FLAG_NO_FINALIZERS            (1 << 3)   /* don't run 
finalizers; leave finalizable objects in finalize_list for next round */
+#define DUK_MS_FLAG_SKIP_FINALIZERS          (1 << 4)   /* don't run 
finalizers; queue finalizable objects back to heap_allocated */
+
+/*
+ *  Thread switching
+ *
+ *  To switch heap->curr_thread, use the macro below so that interrupt counters
+ *  get updated correctly.  The macro allows a NULL target thread because that
+ *  happens e.g. in call handling.
+ */
+
+#if defined(DUK_USE_INTERRUPT_COUNTER)
+#define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), 
(newthr))
+#else
+#define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
+               (heap)->curr_thread = (newthr); \
+       } while (0)
+#endif
+
+/*
+ *  Other heap related defines
+ */
+
+/* Mark-and-sweep interval is relative to combined count of objects and
+ * strings kept in the heap during the latest mark-and-sweep pass.
+ * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
+ * decreased by each (re)allocation attempt (regardless of size), and each
+ * refzero processed object.
+ *
+ * 'SKIP' indicates how many (re)allocations to wait until a retry if
+ * GC is skipped because there is no thread do it with yet (happens
+ * only during init phases).
+ */
+#if defined(DUK_USE_MARK_AND_SWEEP)
+#if defined(DUK_USE_REFERENCE_COUNTING)
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap 
size */
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
+#else
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap 
size */
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
+#endif
+#endif
+
+/* Stringcache is used for speeding up char-offset-to-byte-offset
+ * translations for non-ASCII strings.
+ */
+#define DUK_HEAP_STRCACHE_SIZE                            4
+#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to 
the this length are not cached */
+
+/* helper to insert a (non-string) heap object into heap allocated list */
+#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     
duk_heap_insert_into_heap_allocated((heap),(hdr))
+
+/*
+ *  Stringtable
+ */
+
+/* initial stringtable size, must be prime and higher than 
DUK_UTIL_MIN_HASH_PRIME */
+#define DUK_STRTAB_INITIAL_SIZE            17
+
+/* indicates a deleted string; any fixed non-NULL, non-hstring pointer works */
+#define DUK_STRTAB_DELETED_MARKER(heap)    ((duk_hstring *) heap)
+
+/* resizing parameters */
+#define DUK_STRTAB_MIN_FREE_DIVISOR        4                /* load factor max 
75% */
+#define DUK_STRTAB_MIN_USED_DIVISOR        4                /* load factor min 
25% */
+#define DUK_STRTAB_GROW_ST_SIZE(n)         ((n) + (n))      /* used entries + 
approx 100% -> reset load to 50% */
+
+#define DUK_STRTAB_U32_MAX_STRLEN          10               /* 4'294'967'295 */
+#define DUK_STRTAB_HIGHEST_32BIT_PRIME     0xfffffffbUL
+
+/* probe sequence (open addressing) */
+#define DUK_STRTAB_HASH_INITIAL(hash,h_size)    ((hash) % (h_size))
+#define DUK_STRTAB_HASH_PROBE_STEP(hash)        
DUK_UTIL_GET_HASH_PROBE_STEP((hash))
+
+/* fixed top level hashtable size (separate chaining) */
+#define DUK_STRTAB_CHAIN_SIZE              DUK_USE_STRTAB_CHAIN_SIZE
+
+/*
+ *  Built-in strings
+ */
+
+/* heap string indices are autogenerated in duk_strings.h */
+#if defined(DUK_USE_ROM_STRINGS)
+#define DUK_HEAP_GET_STRING(heap,idx) \
+       ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
+#else  /* DUK_USE_ROM_STRINGS */
+#if defined(DUK_USE_HEAPPTR16)
+#define DUK_HEAP_GET_STRING(heap,idx) \
+       ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, 
(heap)->strs16[(idx)]))
+#else
+#define DUK_HEAP_GET_STRING(heap,idx) \
+       ((heap)->strs[(idx)])
+#endif
+#endif  /* DUK_USE_ROM_STRINGS */
+
+/*
+ *  Raw memory calls: relative to heap, but no GC interaction
+ */
+
+#define DUK_ALLOC_RAW(heap,size) \
+       ((heap)->alloc_func((heap)->heap_udata, (size)))
+
+#define DUK_REALLOC_RAW(heap,ptr,newsize) \
+       ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
+
+#define DUK_FREE_RAW(heap,ptr) \
+       ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
+
+/*
+ *  Memory calls: relative to heap, GC interaction, but no error throwing.
+ *
+ *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
+ *  using the heap->heap_thread.  This thread is also used for running
+ *  mark-and-sweep finalization; this is not ideal because it breaks the
+ *  isolation between multiple global environments.
+ *
+ *  Notes:
+ *
+ *    - DUK_FREE() is required to ignore NULL and any other possible return
+ *      value of a zero-sized alloc/realloc (same as ANSI C free()).
+ *
+ *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
+ *      old size.  Caller must zero the reallocated memory.
+ *
+ *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
+ *      by an allocation failure might invalidate the original 'ptr', thus
+ *      causing a realloc retry to use an invalid pointer.  Example: we're
+ *      reallocating the value stack and a finalizer resizes the same value
+ *      stack during mark-and-sweep.  The indirect variant requests for the
+ *      current location of the pointer being reallocated using a callback
+ *      right before every realloc attempt; this circuitous approach is used
+ *      to avoid strict aliasing issues in a more straightforward indirect
+ *      pointer (void **) approach.  Note: the pointer in the storage
+ *      location is read but is NOT updated; the caller must do that.
+ */
+
+/* callback for indirect reallocs, request for current pointer */
+typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
+
+#define DUK_ALLOC(heap,size)                            
duk_heap_mem_alloc((heap), (size))
+#define DUK_ALLOC_ZEROED(heap,size)                     
duk_heap_mem_alloc_zeroed((heap), (size))
+#define DUK_REALLOC(heap,ptr,newsize)                   
duk_heap_mem_realloc((heap), (ptr), (newsize))
+#define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        
duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
+#define DUK_FREE(heap,ptr)                              
duk_heap_mem_free((heap), (ptr))
+
+/*
+ *  Memory constants
+ */
+
+#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           5   /* Retry 
allocation after mark-and-sweep for this
+                                                              * many times.  A 
single mark-and-sweep round is
+                                                              * not guaranteed 
to free all unreferenced memory
+                                                              * because of 
finalization (in fact, ANY number of
+                                                              * rounds is 
strictly not enough).
+                                                              */
+
+#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from 
this round, use emergency mode
+                                                              * for 
mark-and-sweep.
+                                                              */
+
+/*
+ *  Debugger support
+ */
+
+/* Maximum number of breakpoints.  Only breakpoints that are set are
+ * consulted so increasing this has no performance impact.
+ */
+#define DUK_HEAP_MAX_BREAKPOINTS          16
+
+/* Opcode interval for a Date-based status/peek rate limit check.  Only
+ * relevant when debugger is attached.  Requesting a timestamp may be a
+ * slow operation on some platforms so this shouldn't be too low.  On the
+ * other hand a high value makes Duktape react to a pause request slowly.
+ */
+#define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
+
+/* Milliseconds between status notify and transport peeks. */
+#define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
+
+/* Step types */
+#define DUK_STEP_TYPE_NONE  0
+#define DUK_STEP_TYPE_INTO  1
+#define DUK_STEP_TYPE_OVER  2
+#define DUK_STEP_TYPE_OUT   3
+
+struct duk_breakpoint {
+       duk_hstring *filename;
+       duk_uint32_t line;
+};
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+#define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL)
+#define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \
+               (heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \
+               (heap)->dbg_step_thread = NULL; \
+               (heap)->dbg_step_csindex = 0; \
+               (heap)->dbg_step_startline = 0; \
+       } while (0)
+#define DUK_HEAP_SET_PAUSED(heap) do { \
+               (heap)->dbg_paused = 1; \
+               (heap)->dbg_state_dirty = 1; \
+               DUK_HEAP_CLEAR_STEP_STATE((heap)); \
+       } while (0)
+#define DUK_HEAP_CLEAR_PAUSED(heap) do { \
+               (heap)->dbg_paused = 0; \
+               (heap)->dbg_state_dirty = 1; \
+               DUK_HEAP_CLEAR_STEP_STATE((heap)); \
+       } while (0)
+#define DUK_HEAP_IS_PAUSED(heap) ((heap)->dbg_paused)
+#endif  /* DUK_USE_DEBUGGER_SUPPORT */
+
+/*
+ *  String cache should ideally be at duk_hthread level, but that would
+ *  cause string finalization to slow down relative to the number of
+ *  threads; string finalization must check the string cache for "weak"
+ *  references to the string being finalized to avoid dead pointers.
+ *
+ *  Thus, string caches are now at the heap level now.
+ */
+
+struct duk_strcache {
+       duk_hstring *h;
+       duk_uint32_t bidx;
+       duk_uint32_t cidx;
+};
+
+/*
+ *  Longjmp state, contains the information needed to perform a longjmp.
+ *  Longjmp related values are written to value1, value2, and iserror.
+ */
+
+struct duk_ljstate {
+       duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
+       duk_small_uint_t type;    /* longjmp type */
+       duk_bool_t iserror;       /* isError flag for yield */
+       duk_tval value1;          /* 1st related value (type specific) */
+       duk_tval value2;          /* 2nd related value (type specific) */
+};
+
+/*
+ *  Stringtable entry for fixed size stringtable
+ */
+
+struct duk_strtab_entry {
+#if defined(DUK_USE_HEAPPTR16)
+       /* A 16-bit listlen makes sense with 16-bit heap pointers: there
+        * won't be space for 64k strings anyway.
+        */
+       duk_uint16_t listlen;  /* if 0, 'str16' used, if > 0, 'strlist16' used 
*/
+       union {
+               duk_uint16_t strlist16;
+               duk_uint16_t str16;
+       } u;
+#else
+       duk_size_t listlen;  /* if 0, 'str' used, if > 0, 'strlist' used */
+       union {
+               duk_hstring **strlist;
+               duk_hstring *str;
+       } u;
+#endif
+};
+
+/*
+ *  Main heap structure
+ */
+
+struct duk_heap {
+       duk_small_uint_t flags;
+
+       /* Allocator functions. */
+       duk_alloc_function alloc_func;
+       duk_realloc_function realloc_func;
+       duk_free_function free_func;
+
+       /* Heap udata, used for allocator functions but also for other heap
+        * level callbacks like pointer compression, etc.
+        */
+       void *heap_udata;
+
+       /* Precomputed pointers when using 16-bit heap pointer packing. */
+#if defined(DUK_USE_HEAPPTR16)
+       duk_uint16_t heapptr_null16;
+       duk_uint16_t heapptr_deleted16;
+#endif
+
+       /* Fatal error handling, called e.g. when a longjmp() is needed but
+        * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
+        * declared as "noreturn" because doing that for typedefs is a bit
+        * challenging portability-wise.
+        */
+       duk_fatal_function fatal_func;
+
+       /* allocated heap objects */
+       duk_heaphdr *heap_allocated;
+
+       /* work list for objects whose refcounts are zero but which have not 
been
+        * "finalized"; avoids recursive C calls when refcounts go to zero in a
+        * chain of objects.
+        */
+#if defined(DUK_USE_REFERENCE_COUNTING)
+       duk_heaphdr *refzero_list;
+       duk_heaphdr *refzero_list_tail;
+#endif
+
+#if defined(DUK_USE_MARK_AND_SWEEP)
+       /* mark-and-sweep control */
+#if defined(DUK_USE_VOLUNTARY_GC)
+       duk_int_t mark_and_sweep_trigger_counter;
+#endif
+       duk_int_t mark_and_sweep_recursion_depth;
+
+       /* mark-and-sweep flags automatically active (used for critical 
sections) */
+       duk_small_uint_t mark_and_sweep_base_flags;
+
+       /* work list for objects to be finalized (by mark-and-sweep) */
+       duk_heaphdr *finalize_list;
+#endif
+
+       /* longjmp state */
+       duk_ljstate lj;
+
+       /* marker for detecting internal "double faults", see duk_error_throw.c 
*/
+       duk_bool_t handling_error;
+
+       /* heap thread, used internally and for finalization */
+       duk_hthread *heap_thread;
+
+       /* current thread */
+       duk_hthread *curr_thread;  /* currently running thread */
+
+       /* heap level "stash" object (e.g., various reachability roots) */
+       duk_hobject *heap_object;
+
+       /* duk_handle_call / duk_handle_safe_call recursion depth limiting */
+       duk_int_t call_recursion_depth;
+       duk_int_t call_recursion_limit;
+
+       /* mix-in value for computing string hashes; should be reasonably 
unpredictable */
+       duk_uint32_t hash_seed;
+
+       /* rnd_state for duk_util_tinyrandom.c */
+       duk_uint32_t rnd_state;
+
+       /* For manual debugging: instruction count based on executor and
+        * interrupt counter book-keeping.  Inspect debug logs to see how
+        * they match up.
+        */
+#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
+       duk_int_t inst_count_exec;
+       duk_int_t inst_count_interrupt;
+#endif
+
+       /* debugger */
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+       /* callbacks and udata; dbg_read_cb != NULL is used to indicate 
attached state */
+       duk_debug_read_function dbg_read_cb;                /* required, NULL 
implies detached */
+       duk_debug_write_function dbg_write_cb;              /* required */
+       duk_debug_peek_function dbg_peek_cb;
+       duk_debug_read_flush_function dbg_read_flush_cb;
+       duk_debug_write_flush_function dbg_write_flush_cb;
+       duk_debug_request_function dbg_request_cb;
+       duk_debug_detached_function dbg_detached_cb;
+       void *dbg_udata;
+
+       /* debugger state, only relevant when attached */
+       duk_bool_t dbg_processing;              /* currently processing 
messages or breakpoints: don't enter message processing recursively (e.g. no 
breakpoints when processing debugger eval) */
+       duk_bool_t dbg_paused;                  /* currently paused: talk with 
debug client until step/resume */
+       duk_bool_t dbg_state_dirty;             /* resend state next time 
executor is about to run */
+       duk_bool_t dbg_force_restart;           /* force executor restart to 
recheck breakpoints; used to handle function returns (see GH-303) */
+       duk_bool_t dbg_detaching;               /* debugger detaching; used to 
avoid calling detach handler recursively */
+       duk_small_uint_t dbg_step_type;         /* step type: none, step into, 
step over, step out */
+       duk_hthread *dbg_step_thread;           /* borrowed; NULL if no step 
state (NULLed in unwind) */
+       duk_size_t dbg_step_csindex;            /* callstack index */
+       duk_uint32_t dbg_step_startline;        /* starting line number */
+       duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* 
breakpoints: [0,breakpoint_count[ gc reachable */
+       duk_small_uint_t dbg_breakpoint_count;
+       duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  
/* currently active breakpoints: NULL term, borrowed pointers */
+       /* XXX: make active breakpoints actual copies instead of pointers? */
+
+       /* These are for rate limiting Status notifications and transport 
peeking. */
+       duk_uint32_t dbg_exec_counter;          /* cumulative opcode execution 
count (overflows are OK) */
+       duk_uint32_t dbg_last_counter;          /* value of dbg_exec_counter 
when we last did a Date-based check */
+       duk_double_t dbg_last_time;             /* time when status/peek was 
last done (Date-based rate limit) */
+
+       /* Used to support single-byte stream lookahead. */
+       duk_bool_t dbg_have_next_byte;
+       duk_uint8_t dbg_next_byte;
+#endif
+
+       /* string intern table (weak refs) */
+#if defined(DUK_USE_STRTAB_PROBE)
+#if defined(DUK_USE_HEAPPTR16)
+       duk_uint16_t *strtable16;
+#else
+       duk_hstring **strtable;
+#endif
+       duk_uint32_t st_size;     /* alloc size in elements */
+       duk_uint32_t st_used;     /* used elements (includes DELETED) */
+#endif
+
+       /* XXX: static alloc is OK until separate chaining stringtable
+        * resizing is implemented.
+        */
+#if defined(DUK_USE_STRTAB_CHAIN)
+       duk_strtab_entry strtable[DUK_STRTAB_CHAIN_SIZE];
+#endif
+
+       /* string access cache (codepoint offset -> byte offset) for fast string
+        * character looping; 'weak' reference which needs special handling in 
GC.
+        */
+       duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];
+
+       /* built-in strings */
+#if defined(DUK_USE_ROM_STRINGS)
+       /* No field needed when strings are in ROM. */
+#else
+#if defined(DUK_USE_HEAPPTR16)
+       duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
+#else
+       duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
+#endif
+#endif
+};
+
+/*
+ *  Prototypes
+ */
+
+DUK_INTERNAL_DECL
+duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
+                         duk_realloc_function realloc_func,
+                         duk_free_function free_func,
+                         void *heap_udata,
+                         duk_fatal_function fatal_func);
+DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
+DUK_INTERNAL_DECL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h);
+DUK_INTERNAL_DECL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h);
+DUK_INTERNAL_DECL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h);
+DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr 
*hdr);
+
+DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, 
duk_heaphdr *hdr);
+#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
+DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, 
duk_heaphdr *hdr);
+#endif
+#if defined(DUK_USE_INTERRUPT_COUNTER)
+DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread 
*new_thr);
+#endif
+
+#if 0  /*unused*/
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const 
duk_uint8_t *str, duk_uint32_t blen);
+#endif
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const 
duk_uint8_t *str, duk_uint32_t blen);
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread 
*thr, const duk_uint8_t *str, duk_uint32_t len);
+#if 0  /*unused*/
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, 
duk_uint32_t val);
+#endif
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, 
duk_uint32_t val);
+DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread 
*thr, duk_uint32_t val);
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h);
+#endif
+#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
+DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap);
+#endif
+DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap);
+#if defined(DUK_USE_DEBUG)
+DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap);
+#endif
+
+
+DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, 
duk_hstring *h);
+DUK_INTERNAL_DECL duk_uint_fast32_t 
duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, 
duk_uint_fast32_t char_offset);
+
+#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
+DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t 
size);
+DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, 
duk_size_t newsize);
+DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
+#endif
+
+DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
+DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t 
size);
+DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, 
duk_size_t newsize);
+DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, 
duk_mem_getptr cb, void *ud, duk_size_t newsize);
+DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
+
+#ifdef DUK_USE_REFERENCE_COUNTING
+#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
+#endif
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_tval_incref_allownull(duk_tval *tv);
+#endif
+DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval 
*tv);
+#endif
+#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
+DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
+#endif
+#if 0  /* unused */
+DUK_INTERNAL_DECL void duk_heaphdr_incref_allownull(duk_heaphdr *h);
+#endif
+DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_decref_allownull(duk_hthread *thr, 
duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, 
duk_heaphdr *hdr);
+#else
+/* no refcounting */
+#endif
+
+#if defined(DUK_USE_MARK_AND_SWEEP)
+DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, 
duk_small_uint_t flags);
+#endif
+
+DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const 
duk_uint8_t *str, duk_size_t len);
+
+#endif  /* DUK_HEAP_H_INCLUDED */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_alloc.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_alloc.c
 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_alloc.c
new file mode 100644
index 0000000..b89fe48
--- /dev/null
+++ 
b/thirdparty/civetweb-1.9.1/src/third_party/duktape-1.5.2/src-separate/duk_heap_alloc.c
@@ -0,0 +1,1042 @@
+/*
+ *  duk_heap allocation and freeing.
+ */
+
+#include "duk_internal.h"
+
+/* Constants for built-in string data depacking. */
+#define DUK__BITPACK_LETTER_LIMIT  26
+#define DUK__BITPACK_UNDERSCORE    26
+#define DUK__BITPACK_FF            27
+#define DUK__BITPACK_SWITCH1       29
+#define DUK__BITPACK_SWITCH        30
+#define DUK__BITPACK_SEVENBIT      31
+
+#if defined(DUK_USE_ROM_STRINGS)
+/* Fixed seed value used with ROM strings. */
+#define DUK__FIXED_HASH_SEED       0xabcd1234
+#endif
+
+/*
+ *  Free a heap object.
+ *
+ *  Free heap object and its internal (non-heap) pointers.  Assumes that
+ *  caller has removed the object from heap allocated list or the string
+ *  intern table, and any weak references (which strings may have) have
+ *  been already dealt with.
+ */
+
+DUK_INTERNAL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h) {
+       DUK_ASSERT(heap != NULL);
+       DUK_ASSERT(h != NULL);
+
+       DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
+
+       if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
+               duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
+               DUK_UNREF(f);
+               /* Currently nothing to free; 'data' is a heap object */
+       } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
+               duk_hnativefunction *f = (duk_hnativefunction *) h;
+               DUK_UNREF(f);
+               /* Currently nothing to free */
+       } else if (DUK_HOBJECT_IS_THREAD(h)) {
+               duk_hthread *t = (duk_hthread *) h;
+               DUK_FREE(heap, t->valstack);
+               DUK_FREE(heap, t->callstack);
+               DUK_FREE(heap, t->catchstack);
+               /* Don't free h->resumer because it exists in the heap.
+                * Callstack entries also contain function pointers which
+                * are not freed for the same reason.
+                */
+
+               /* XXX: with 'caller' property the callstack would need
+                * to be unwound to update the 'caller' properties of
+                * functions in the callstack.
+                */
+       }
+}
+
+DUK_INTERNAL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h) {
+       DUK_ASSERT(heap != NULL);
+       DUK_ASSERT(h != NULL);
+
+       if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
+               duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
+               DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) 
DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
+               DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
+       }
+}
+
+DUK_INTERNAL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h) {
+       DUK_ASSERT(heap != NULL);
+       DUK_ASSERT(h != NULL);
+
+       DUK_UNREF(heap);
+       DUK_UNREF(h);
+
+#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
+       if (DUK_HSTRING_HAS_EXTDATA(h)) {
+               DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
+                                    h, 
DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
+               DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) 
DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
+       }
+#endif
+}
+
+DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
+       DUK_ASSERT(heap);
+       DUK_ASSERT(hdr);
+
+       DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) 
DUK_HEAPHDR_GET_TYPE(hdr)));
+
+       switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
+       case DUK_HTYPE_STRING:
+               duk_free_hstring_inner(heap, (duk_hstring *) hdr);
+               break;
+       case DUK_HTYPE_OBJECT:
+               duk_free_hobject_inner(heap, (duk_hobject *) hdr);
+               break;
+       case DUK_HTYPE_BUFFER:
+               duk_free_hbuffer_inner(heap, (duk_hbuffer *) hdr);
+               break;
+       default:
+               DUK_UNREACHABLE();
+       }
+
+       DUK_FREE(heap, hdr);
+}
+
+/*
+ *  Free the heap.
+ *
+ *  Frees heap-related non-heap-tracked allocations such as the
+ *  string intern table; then frees the heap allocated objects;
+ *  and finally frees the heap structure itself.  Reference counts
+ *  and GC markers are ignored (and not updated) in this process,
+ *  and finalizers won't be called.
+ *
+ *  The heap pointer and heap object pointers must not be used
+ *  after this call.
+ */
+
+DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
+       duk_heaphdr *curr;
+       duk_heaphdr *next;
+
+       curr = heap->heap_allocated;
+       while (curr) {
+               /* We don't log or warn about freeing zero refcount objects
+                * because they may happen with finalizer processing.
+                */
+
+               DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
+                                    (duk_heaphdr *) curr));
+               next = DUK_HEAPHDR_GET_NEXT(heap, curr);
+               duk_heap_free_heaphdr_raw(heap, curr);
+               curr = next;
+       }
+}
+
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_LOCAL void duk__free_refzero_list(duk_heap *heap) {
+       duk_heaphdr *curr;
+       duk_heaphdr *next;
+
+       curr = heap->refzero_list;
+       while (curr) {
+               DUK_DDD(DUK_DDDPRINT("FINALFREE (refzero_list): %!iO",
+                                    (duk_heaphdr *) curr));
+               next = DUK_HEAPHDR_GET_NEXT(heap, curr);
+               duk_heap_free_heaphdr_raw(heap, curr);
+               curr = next;
+       }
+}
+#endif
+
+#if defined(DUK_USE_MARK_AND_SWEEP)
+DUK_LOCAL void duk__free_markandsweep_finalize_list(duk_heap *heap) {
+       duk_heaphdr *curr;
+       duk_heaphdr *next;
+
+       curr = heap->finalize_list;
+       while (curr) {
+               DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
+                                    (duk_heaphdr *) curr));
+               next = DUK_HEAPHDR_GET_NEXT(heap, curr);
+               duk_heap_free_heaphdr_raw(heap, curr);
+               curr = next;
+       }
+}
+#endif
+
+DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
+       /* strings are only tracked by stringtable */
+       duk_heap_free_strtab(heap);
+}
+
+DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
+       duk_hthread *thr;
+       duk_heaphdr *curr;
+       duk_uint_t round_no;
+       duk_size_t count_all;
+       duk_size_t count_finalized;
+       duk_size_t curr_limit;
+
+       DUK_ASSERT(heap != NULL);
+       DUK_ASSERT(heap->heap_thread != NULL);
+
+#if defined(DUK_USE_REFERENCE_COUNTING)
+       DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must 
be empty */
+#endif
+#if defined(DUK_USE_MARK_AND_SWEEP)
+       DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep not running 
-> must be empty */
+#endif
+
+       /* XXX: here again finalizer thread is the heap_thread which needs
+        * to be coordinated with finalizer thread fixes.
+        */
+       thr = heap->heap_thread;
+       DUK_ASSERT(thr != NULL);
+
+       /* Prevent mark-and-sweep for the pending finalizers, also prevents
+        * refzero handling from moving objects away from the heap_allocated
+        * list.  (The flag meaning is slightly abused here.)
+        */
+       DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
+       DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
+
+       curr_limit = 0;  /* suppress warning, not used */
+       for (round_no = 0; ; round_no++) {
+               curr = heap->heap_allocated;
+               count_all = 0;
+               count_finalized = 0;
+               while (curr) {
+                       count_all++;
+                       if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
+                               /* Only objects in heap_allocated may have 
finalizers.  Check that
+                                * the object itself has a _Finalizer property 
(own or inherited)
+                                * so that we don't execute finalizers for e.g. 
Proxy objects.
+                                */
+                               DUK_ASSERT(thr != NULL);
+                               DUK_ASSERT(curr != NULL);
+
+                               if (duk_hobject_hasprop_raw(thr, (duk_hobject 
*) curr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
+                                       if 
(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
+                                               
DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd 
argument */
+                                               duk_hobject_run_finalizer(thr, 
(duk_hobject *) curr);
+                                               count_finalized++;
+                                       }
+                               }
+                       }
+                       curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
+               }
+
+               /* Each round of finalizer execution may spawn new finalizable 
objects
+                * which is normal behavior for some applications.  Allow 
multiple
+                * rounds of finalization, but use a shrinking limit based on 
the
+                * first round to detect the case where a runaway finalizer 
creates
+                * an unbounded amount of new finalizable objects.  Finalizer 
rescue
+                * is not supported: the semantics are unclear because most of 
the
+                * objects being finalized here are already reachable.  The 
finalizer
+                * is given a boolean to indicate that rescue is not possible.
+                *
+                * See discussion in: 
https://github.com/svaarala/duktape/pull/473
+                */
+
+               if (round_no == 0) {
+                       /* Cannot wrap: each object is at least 8 bytes so 
count is
+                        * at most 1/8 of that.
+                        */
+                       curr_limit = count_all * 2;
+               } else {
+                       curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% 
every round */
+               }
+               DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, 
tried to execute %ld finalizers, current limit is %ld",
+                                (long) round_no, (long) count_all, (long) 
count_finalized, (long) curr_limit));
+
+               if (count_finalized == 0) {
+                       DUK_D(DUK_DPRINT("no more finalizable objects, forced 
finalization finished"));
+                       break;
+               }
+               if (count_finalized >= curr_limit) {
+                       DUK_D(DUK_DPRINT("finalizer count above limit, 
potentially runaway finalizer; skip remaining finalizers"));
+                       break;
+               }
+       }
+
+       DUK_ASSERT(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
+       DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
+}
+
+DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
+       DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
+
+#if defined(DUK_USE_DEBUG)
+       duk_heap_dump_strtab(heap);
+#endif
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+       /* Detach a debugger if attached (can be called multiple times)
+        * safely.
+        */
+       /* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
+        * the detached callback may immediately reattach.
+        */
+       duk_debug_do_detach(heap);
+#endif
+
+       /* Execute finalizers before freeing the heap, even for reachable
+        * objects, and regardless of whether or not mark-and-sweep is
+        * enabled.  This gives finalizers the chance to free any native
+        * resources like file handles, allocations made outside Duktape,
+        * etc.  This is quite tricky to get right, so that all finalizer
+        * guarantees are honored.
+        *
+        * XXX: this perhaps requires an execution time limit.
+        */
+       DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
+#if defined(DUK_USE_MARK_AND_SWEEP)
+       /* Run mark-and-sweep a few times just in case (unreachable object
+        * finalizers run already here).  The last round must rescue objects
+        * from the previous round without running any more finalizers.  This
+        * ensures rescued objects get their FINALIZED flag cleared so that
+        * their finalizer is called once more in forced finalization to
+        * satisfy finalizer guarantees.  However, we don't want to run any
+        * more finalizer because that'd required one more loop, and so on.
+        */
+       DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
+       duk_heap_mark_and_sweep(heap, 0);
+       DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
+       duk_heap_mark_and_sweep(heap, 0);
+       DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run 
finalizers)"));
+       duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS);  /* skip 
finalizers; queue finalizable objects to heap_allocated */
+#endif
+
+       DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* rescue no longer supported */
+       duk__free_run_finalizers(heap);
+
+       /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
+        * are on the heap allocated list.
+        */
+
+       DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
+       duk__free_allocated(heap);
+
+#if defined(DUK_USE_REFERENCE_COUNTING)
+       DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
+       duk__free_refzero_list(heap);
+#endif
+
+#if defined(DUK_USE_MARK_AND_SWEEP)
+       DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", 
(void *) heap));
+       duk__free_markandsweep_finalize_list(heap);
+#endif
+
+       DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
+       duk__free_stringtable(heap);
+
+       DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
+       heap->free_func(heap->heap_udata, heap);
+}
+
+/*
+ *  Allocate a heap.
+ *
+ *  String table is initialized with built-in strings from genbuiltins.py,
+ *  either by dynamically creating the strings or by referring to ROM strings.
+ */
+
+#if defined(DUK_USE_ROM_STRINGS)
+DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
+#if defined(DUK_USE_ASSERTIONS)
+       duk_small_uint_t i;
+#endif
+
+       /* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
+        * so nothing to initialize for strs[].
+        */
+
+#if defined(DUK_USE_ASSERTIONS)
+       for (i = 0; i < sizeof(duk_rom_strings) / sizeof(const duk_hstring *); 
i++) {
+               duk_uint32_t hash;
+               const duk_hstring *h;
+               h = duk_rom_strings[i];
+               DUK_ASSERT(h != NULL);
+               hash = duk_heap_hashstring(heap, (const duk_uint8_t *) 
DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
+               DUK_DD(DUK_DDPRINT("duk_rom_strings[%d] -> hash 0x%08lx, 
computed 0x%08lx",
+                                  (int) i, (unsigned long) 
DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
+               DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
+       }
+#endif
+       return 1;
+}
+#else  /* DUK_USE_ROM_STRINGS */
+DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
+       duk_bitdecoder_ctx bd_ctx;
+       duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
+       duk_small_uint_t i, j;
+
+       DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+       bd->data = (const duk_uint8_t *) duk_strings_data;
+       bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
+
+       for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
+               duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
+               duk_hstring *h;
+               duk_small_uint_t len;
+               duk_small_uint_t mode;
+               duk_small_uint_t t;
+
+               len = duk_bd_decode(bd, 5);
+               mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
+               for (j = 0; j < len; j++) {
+                       t = duk_bd_decode(bd, 5);
+                       if (t < DUK__BITPACK_LETTER_LIMIT) {
+                               t = t + DUK_ASC_UC_A + mode;
+                       } else if (t == DUK__BITPACK_UNDERSCORE) {
+                               t = DUK_ASC_UNDERSCORE;
+                       } else if (t == DUK__BITPACK_FF) {
+                               /* Internal keys are prefixed with 0xFF in the 
stringtable
+                                * (which makes them invalid UTF-8 on purpose).
+                                */
+                               t = 0xff;
+                       } else if (t == DUK__BITPACK_SWITCH1) {
+                               t = duk_bd_decode(bd, 5);
+                               DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
+                               DUK_ASSERT(t <= 25);
+                               t = t + DUK_ASC_UC_A + (mode ^ 32);
+                       } else if (t == DUK__BITPACK_SWITCH) {
+                               mode = mode ^ 32;
+                               t = duk_bd_decode(bd, 5);
+                               DUK_ASSERT_DISABLE(t >= 0);
+                               DUK_ASSERT(t <= 25);
+                               t = t + DUK_ASC_UC_A + mode;
+                       } else if (t == DUK__BITPACK_SEVENBIT) {
+                               t = duk_bd_decode(bd, 7);
+                       }
+                       tmp[j] = (duk_uint8_t) t;
+               }
+
+               /* No need to length check string: it will never exceed even
+                * the 16-bit length maximum.
+                */
+               DUK_ASSERT(len <= 0xffffUL);
+               DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
+               h = duk_heap_string_intern(heap, tmp, len);
+               if (!h) {
+                       goto error;
+               }
+               DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
+
+               /* Special flags checks.  Since these strings are always
+                * reachable and a string cannot appear twice in the string
+                * table, there's no need to check/set these flags elsewhere.
+                * The 'internal' flag is set by string intern code.
+                */
+               if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
+                       DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
+               }
+               if (i >= DUK_STRIDX_START_RESERVED && i < 
DUK_STRIDX_END_RESERVED) {
+                       DUK_HSTRING_SET_RESERVED_WORD(h);
+                       if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
+                               DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
+                       }
+               }
+
+               DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
+
+               /* XXX: The incref macro takes a thread pointer but doesn't
+                * use it right now.
+                */
+               DUK_HSTRING_INCREF(_never_referenced_, h);
+
+#if defined(DUK_USE_HEAPPTR16)
+               heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void 
*) h);
+#else
+               heap->strs[i] = h;
+#endif
+       }
+
+       return 1;
+
+ error:
+       return 0;
+}
+#endif  /* DUK_USE_ROM_STRINGS */
+
+DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
+       duk_hthread *thr;
+
+       DUK_DD(DUK_DDPRINT("heap init: alloc heap thread"));
+       thr = duk_hthread_alloc(heap,
+                               DUK_HOBJECT_FLAG_EXTENSIBLE |
+                               DUK_HOBJECT_FLAG_THREAD |
+                               
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
+       if (!thr) {
+               DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
+               return 0;
+       }
+       thr->state = DUK_HTHREAD_STATE_INACTIVE;
+#if defined(DUK_USE_ROM_STRINGS)
+       /* No strs[] pointer. */
+#else  /* DUK_USE_ROM_STRINGS */
+#if defined(DUK_USE_HEAPPTR16)
+       thr->strs16 = heap->strs16;
+#else
+       thr->strs = heap->strs;
+#endif
+#endif  /* DUK_USE_ROM_STRINGS */
+
+       heap->heap_thread = thr;
+       DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used 
*/
+
+       /* 'thr' is now reachable */
+
+       if (!duk_hthread_init_stacks(heap, thr)) {
+               return 0;
+       }
+
+       /* XXX: this may now fail, and is not handled correctly */
+       duk_hthread_create_builtin_objects(thr);
+
+       /* default prototype (Note: 'thr' must be reachable) */
+       DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) thr, 
thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
+
+       return 1;
+}
+
+#if defined(DUK_USE_DEBUG)
+#define DUK__DUMPSZ(t)  do { \
+               DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
+       } while (0)
+
+/* These is not 100% because format would need to be non-portable "long long".
+ * Also print out as doubles to catch cases where the "long" type is not wide
+ * enough; the limits will then not be printed accurately but the magnitude
+ * will be correct.
+ */
+#define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
+               DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
+                                (long) (a), (long) (b), \
+                                (double) (a), (double) (b))); \
+       } while (0)
+#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
+               DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
+                                (unsigned long) (a), (unsigned long) (b), \
+                                (double) (a), (double) (b))); \
+       } while (0)
+#define DUK__DUMPLM_SIGNED(t)  do { \
+               DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, 
DUK_##t##_MAX); \
+       } while (0)
+#define DUK__DUMPLM_UNSIGNED(t)  do { \
+               DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, 
DUK_##t##_MAX); \
+       } while (0)
+
+DUK_LOCAL void duk__dump_type_sizes(void) {
+       DUK_D(DUK_DPRINT("sizeof()"));
+
+       /* basic platform types */
+       DUK__DUMPSZ(char);
+       DUK__DUMPSZ(short);
+       DUK__DUMPSZ(int);
+       DUK__DUMPSZ(long);
+       DUK__DUMPSZ(double);
+       DUK__DUMPSZ(void *);
+       DUK__DUMPSZ(size_t);
+
+       /* basic types from duk_features.h */
+       DUK__DUMPSZ(duk_uint8_t);
+       DUK__DUMPSZ(duk_int8_t);
+       DUK__DUMPSZ(duk_uint16_t);
+       DUK__DUMPSZ(duk_int16_t);
+       DUK__DUMPSZ(duk_uint32_t);
+       DUK__DUMPSZ(duk_int32_t);
+       DUK__DUMPSZ(duk_uint64_t);
+       DUK__DUMPSZ(duk_int64_t);
+       DUK__DUMPSZ(duk_uint_least8_t);
+       DUK__DUMPSZ(duk_int_least8_t);
+       DUK__DUMPSZ(duk_uint_least16_t);
+       DUK__DUMPSZ(duk_int_least16_t);
+       DUK__DUMPSZ(duk_uint_least32_t);
+       DUK__DUMPSZ(duk_int_least32_t);
+#if defined(DUK_USE_64BIT_OPS)
+       DUK__DUMPSZ(duk_uint_least64_t);
+       DUK__DUMPSZ(duk_int_least64_t);
+#endif
+       DUK__DUMPSZ(duk_uint_fast8_t);
+       DUK__DUMPSZ(duk_int_fast8_t);
+       DUK__DUMPSZ(duk_uint_fast16_t);
+       DUK__DUMPSZ(duk_int_fast16_t);
+       DUK__DUMPSZ(duk_uint_fast32_t);
+       DUK__DUMPSZ(duk_int_fast32_t);
+#if defined(DUK_USE_64BIT_OPS)
+       DUK__DUMPSZ(duk_uint_fast64_t);
+       DUK__DUMPSZ(duk_int_fast64_t);
+#endif
+       DUK__DUMPSZ(duk_uintptr_t);
+       DUK__DUMPSZ(duk_intptr_t);
+       DUK__DUMPSZ(duk_uintmax_t);
+       DUK__DUMPSZ(duk_intmax_t);
+       DUK__DUMPSZ(duk_double_t);
+
+       /* important chosen base types */
+       DUK__DUMPSZ(duk_int_t);
+       DUK__DUMPSZ(duk_uint_t);
+       DUK__DUMPSZ(duk_int_fast_t);
+       DUK__DUMPSZ(duk_uint_fast_t);
+       DUK__DUMPSZ(duk_small_int_t);
+       DUK__DUMPSZ(duk_small_uint_t);
+       DUK__DUMPSZ(duk_small_int_fast_t);
+       DUK__DUMPSZ(duk_small_uint_fast_t);
+
+       /* some derived types */
+       DUK__DUMPSZ(duk_codepoint_t);
+       DUK__DUMPSZ(duk_ucodepoint_t);
+       DUK__DUMPSZ(duk_idx_t);
+       DUK__DUMPSZ(duk_errcode_t);
+       DUK__DUMPSZ(duk_uarridx_t);
+
+       /* tval */
+       DUK__DUMPSZ(duk_double_union);
+       DUK__DUMPSZ(duk_tval);
+
+       /* structs from duk_forwdecl.h */
+       DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
+       DUK__DUMPSZ(duk_heaphdr);
+       DUK__DUMPSZ(duk_heaphdr_string);
+       DUK__DUMPSZ(duk_hstring);
+       DUK__DUMPSZ(duk_hstring_external);
+       DUK__DUMPSZ(duk_hobject);
+       DUK__DUMPSZ(duk_hcompiledfunction);
+       DUK__DUMPSZ(duk_hnativefunction);
+       DUK__DUMPSZ(duk_hthread);
+       DUK__DUMPSZ(duk_hbuffer);
+       DUK__DUMPSZ(duk_hbuffer_fixed);
+       DUK__DUMPSZ(duk_hbuffer_dynamic);
+       DUK__DUMPSZ(duk_hbuffer_external);
+       DUK__DUMPSZ(duk_propaccessor);
+       DUK__DUMPSZ(duk_propvalue);
+       DUK__DUMPSZ(duk_propdesc);
+       DUK__DUMPSZ(duk_heap);
+#if defined(DUK_USE_STRTAB_CHAIN)
+       DUK__DUMPSZ(duk_strtab_entry);
+#endif
+       DUK__DUMPSZ(duk_activation);
+       DUK__DUMPSZ(duk_catcher);
+       DUK__DUMPSZ(duk_strcache);
+       DUK__DUMPSZ(duk_ljstate);
+       DUK__DUMPSZ(duk_fixedbuffer);
+       DUK__DUMPSZ(duk_bitdecoder_ctx);
+       DUK__DUMPSZ(duk_bitencoder_ctx);
+       DUK__DUMPSZ(duk_token);
+       DUK__DUMPSZ(duk_re_token);
+       DUK__DUMPSZ(duk_lexer_point);
+       DUK__DUMPSZ(duk_lexer_ctx);
+       DUK__DUMPSZ(duk_compiler_instr);
+       DUK__DUMPSZ(duk_compiler_func);
+       DUK__DUMPSZ(duk_compiler_ctx);
+       DUK__DUMPSZ(duk_re_matcher_ctx);
+       DUK__DUMPSZ(duk_re_compiler_ctx);
+}
+DUK_LOCAL void duk__dump_type_limits(void) {
+       DUK_D(DUK_DPRINT("limits"));
+
+       /* basic types */
+       DUK__DUMPLM_SIGNED(INT8);
+       DUK__DUMPLM_UNSIGNED(UINT8);
+       DUK__DUMPLM_SIGNED(INT_FAST8);
+       DUK__DUMPLM_UNSIGNED(UINT_FAST8);
+       DUK__DUMPLM_SIGNED(INT_LEAST8);
+       DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
+       DUK__DUMPLM_SIGNED(INT16);
+       DUK__DUMPLM_UNSIGNED(UINT16);
+       DUK__DUMPLM_SIGNED(INT_FAST16);
+       DUK__DUMPLM_UNSIGNED(UINT_FAST16);
+       DUK__DUMPLM_SIGNED(INT_LEAST16);
+       DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
+       DUK__DUMPLM_SIGNED(INT32);
+       DUK__DUMPLM_UNSIGNED(UINT32);
+       DUK__DUMPLM_SIGNED(INT_FAST32);
+       DUK__DUMPLM_UNSIGNED(UINT_FAST32);
+       DUK__DUMPLM_SIGNED(INT_LEAST32);
+       DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
+#if defined(DUK_USE_64BIT_OPS)
+       DUK__DUMPLM_SIGNED(INT64);
+       DUK__DUMPLM_UNSIGNED(UINT64);
+       DUK__DUMPLM_SIGNED(INT_FAST64);
+       DUK__DUMPLM_UNSIGNED(UINT_FAST64);
+       DUK__DUMPLM_SIGNED(INT_LEAST64);
+       DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
+#endif
+       DUK__DUMPLM_SIGNED(INTPTR);
+       DUK__DUMPLM_UNSIGNED(UINTPTR);
+       DUK__DUMPLM_SIGNED(INTMAX);
+       DUK__DUMPLM_UNSIGNED(UINTMAX);
+
+       /* derived types */
+       DUK__DUMPLM_SIGNED(INT);
+       DUK__DUMPLM_UNSIGNED(UINT);
+       DUK__DUMPLM_SIGNED(INT_FAST);
+       DUK__DUMPLM_UNSIGNED(UINT_FAST);
+       DUK__DUMPLM_SIGNED(SMALL_INT);
+       DUK__DUMPLM_UNSIGNED(SMALL_UINT);
+       DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
+       DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
+}
+#undef DUK__DUMPSZ
+#undef DUK__DUMPLM_SIGNED_RAW
+#undef DUK__DUMPLM_UNSIGNED_RAW
+#undef DUK__DUMPLM_SIGNED
+#undef DUK__DUMPLM_UNSIGNED
+
+DUK_LOCAL void duk__dump_misc_options(void) {
+       DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
+       DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
+       DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
+       DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
+       DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
+#if defined(DUK_USE_PACKED_TVAL)
+       DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
+#else
+       DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
+#endif
+#if defined(DUK_USE_VARIADIC_MACROS)
+       DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
+#else
+       DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
+#endif
+#if defined(DUK_USE_INTEGER_LE)
+       DUK_D(DUK_DPRINT("integer endianness: little"));
+#elif defined(DUK_USE_INTEGER_ME)
+       DUK_D(DUK_DPRINT("integer endianness: mixed"));
+#elif defined(DUK_USE_INTEGER_BE)
+       DUK_D(DUK_DPRINT("integer endianness: big"));
+#else
+       DUK_D(DUK_DPRINT("integer endianness: ???"));
+#endif
+#if defined(DUK_USE_DOUBLE_LE)
+       DUK_D(DUK_DPRINT("IEEE double endianness: little"));
+#elif defined(DUK_USE_DOUBLE_ME)
+       DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
+#elif defined(DUK_USE_DOUBLE_BE)
+       DUK_D(DUK_DPRINT("IEEE double endianness: big"));
+#else
+       DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
+#endif
+}
+#endif  /* DUK_USE_DEBUG */
+
+DUK_INTERNAL
+duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
+                         duk_realloc_function realloc_func,
+                         duk_free_function free_func,
+                         void *heap_udata,
+                         duk_fatal_function fatal_func) {
+       duk_heap *res = NULL;
+
+       /* Silence a few global unused warnings here. */
+       DUK_UNREF(duk_str_unsupported);
+
+       DUK_D(DUK_DPRINT("allocate heap"));
+
+       /*
+        *  Debug dump type sizes
+        */
+
+#if defined(DUK_USE_DEBUG)
+       duk__dump_misc_options();
+       duk__dump_type_sizes();
+       duk__dump_type_limits();
+#endif
+
+       /*
+        *  If selftests enabled, run them as early as possible
+        */
+#if defined(DUK_USE_SELF_TESTS)
+       DUK_D(DUK_DPRINT("running self tests"));
+       duk_selftest_run_tests();
+       DUK_D(DUK_DPRINT("self tests passed"));
+#endif
+
+       /*
+        *  Computed values (e.g. INFINITY)
+        */
+
+#if defined(DUK_USE_COMPUTED_NAN)
+       do {
+               /* Workaround for some exotic platforms where NAN is missing
+                * and the expression (0.0 / 0.0) does NOT result in a NaN.
+                * Such platforms use the global 'duk_computed_nan' which must
+                * be initialized at runtime.  Use 'volatile' to ensure that
+                * the compiler will actually do the computation and not try
+                * to do constant folding which might result in the original
+                * problem.
+                */
+               volatile double dbl1 = 0.0;
+               volatile double dbl2 = 0.0;
+               duk_computed_nan = dbl1 / dbl2;
+       } while (0);
+#endif
+
+#if defined(DUK_USE_COMPUTED_INFINITY)
+       do {
+               /* Similar workaround for INFINITY. */
+               volatile double dbl1 = 1.0;
+               volatile double dbl2 = 0.0;
+               duk_computed_infinity = dbl1 / dbl2;
+       } while (0);
+#endif
+
+       /*
+        *  Allocate heap struct
+        *
+        *  Use a raw call, all macros expect the heap to be initialized
+        */
+
+       res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
+       if (!res) {
+               goto error;
+       }
+
+       /*
+        *  Zero the struct, and start initializing roughly in order
+        */
+
+       DUK_MEMZERO(res, sizeof(*res));
+
+       /* explicit NULL inits */
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+       res->heap_udata = NULL;
+       res->heap_allocated = NULL;
+#if defined(DUK_USE_REFERENCE_COUNTING)
+       res->refzero_list = NULL;
+       res->refzero_list_tail = NULL;
+#endif
+#if defined(DUK_USE_MARK_AND_SWEEP)
+       res->finalize_list = NULL;
+#endif
+       res->heap_thread = NULL;
+       res->curr_thread = NULL;
+       res->heap_object = NULL;
+#if defined(DUK_USE_STRTAB_CHAIN)
+       /* nothing to NULL */
+#elif defined(DUK_USE_STRTAB_PROBE)
+#if defined(DUK_USE_HEAPPTR16)
+       res->strtable16 = (duk_uint16_t *) NULL;
+#else
+       res->strtable = (duk_hstring **) NULL;
+#endif
+#endif
+#if defined(DUK_USE_ROM_STRINGS)
+       /* no res->strs[] */
+#else  /* DUK_USE_ROM_STRINGS */
+#if defined(DUK_USE_HEAPPTR16)
+       /* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. 
*/
+#else
+       {
+               duk_small_uint_t i;
+               for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
+                       res->strs[i] = NULL;
+               }
+       }
+#endif
+#endif  /* DUK_USE_ROM_STRINGS */
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+       res->dbg_read_cb = NULL;
+       res->dbg_write_cb = NULL;
+       res->dbg_peek_cb = NULL;
+       res->dbg_read_flush_cb = NULL;
+       res->dbg_write_flush_cb = NULL;
+       res->dbg_request_cb = NULL;
+       res->dbg_udata = NULL;
+       res->dbg_step_thread = NULL;
+#endif
+#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
+
+       res->alloc_func = alloc_func;
+       res->realloc_func = realloc_func;
+       res->free_func = free_func;
+       res->heap_udata = heap_udata;
+       res->fatal_func = fatal_func;
+
+#if defined(DUK_USE_HEAPPTR16)
+       /* XXX: zero assumption */
+       res->heapptr_null16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) 
NULL);
+       res->heapptr_deleted16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void 
*) DUK_STRTAB_DELETED_MARKER(res));
+#endif
+
+       /* res->mark_and_sweep_trigger_counter == 0 -> now causes immediate GC; 
which is OK */
+
+       res->call_recursion_depth = 0;
+       res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
+
+       /* XXX: use the pointer as a seed for now: mix in time at least */
+
+       /* The casts through duk_intr_pt is to avoid the following GCC warning:
+        *
+        *   warning: cast from pointer to integer of different size 
[-Wpointer-to-int-cast]
+        *
+        * This still generates a /Wp64 warning on VS2010 when compiling for 
x86.
+        */
+#if defined(DUK_USE_ROM_STRINGS)
+       /* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
+       DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed 
value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
+       res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
+#else  /* DUK_USE_ROM_STRINGS */
+       res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
+       res->rnd_state = (duk_uint32_t) (duk_intptr_t) res;
+#if !defined(DUK_USE_STRHASH_DENSE)
+       res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; 
XOR it in in case pointer low bits are 0 */
+#endif
+#endif  /* DUK_USE_ROM_STRINGS */
+
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+       res->lj.jmpbuf_ptr = NULL;
+#endif
+       DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
+
+       DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
+       DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
+
+#if (DUK_STRTAB_INITIAL_SIZE < DUK_UTIL_MIN_HASH_PRIME)
+#error initial heap stringtable size is defined incorrectly
+#endif
+
+       /*
+        *  Init stringtable: fixed variant
+        */
+
+#if defined(DUK_USE_STRTAB_CHAIN)
+       DUK_MEMZERO(res->strtable, sizeof(duk_strtab_entry) * 
DUK_STRTAB_CHAIN_SIZE);
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+       {
+               duk_small_uint_t i;
+               for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+                       res->strtable[i].u.str16 = res->heapptr_null16;
+#else
+                       res->strtable[i].u.str = NULL;
+#endif
+               }
+       }
+#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
+#endif  /* DUK_USE_STRTAB_CHAIN */
+
+       /*
+        *  Init stringtable: probe variant
+        */
+
+#if defined(DUK_USE_STRTAB_PROBE)
+#if defined(DUK_USE_HEAPPTR16)
+       res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, 
sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
+       if (!res->strtable16) {
+               goto error;
+       }
+#else  /* DUK_USE_HEAPPTR16 */
+       res->strtable = (duk_hstring **) alloc_func(heap_udata, 
sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
+       if (!res->strtable) {
+               goto error;
+       }
+#endif  /* DUK_USE_HEAPPTR16 */
+       res->st_size = DUK_STRTAB_INITIAL_SIZE;
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+       {
+               duk_small_uint_t i;
+               DUK_ASSERT(res->st_size == DUK_STRTAB_INITIAL_SIZE);
+               for (i = 0; i < DUK_STRTAB_INITIAL_SIZE; i++) {
+#if defined(DUK_USE_HEAPPTR16)
+                       res->strtable16[i] = res->heapptr_null16;
+#else
+                       res->strtable[i] = NULL;
+#endif
+               }
+       }
+#else  /* DUK_USE_EXPLICIT_NULL_INIT */
+#if defined(DUK_USE_HEAPPTR16)
+       DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * 
DUK_STRTAB_INITIAL_SIZE);
+#else
+       DUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * 
DUK_STRTAB_INITIAL_SIZE);
+#endif
+#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
+#endif  /* DUK_USE_STRTAB_PROBE */
+
+       /*
+        *  Init stringcache
+        */
+
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+       {
+               duk_small_uint_t i;
+               for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
+                       res->strcache[i].h = NULL;
+               }
+       }
+#endif
+
+       /* XXX: error handling is incomplete.  It would be cleanest if
+        * there was a setjmp catchpoint, so that all init code could
+        * freely throw errors.  If that were the case, the return code
+        * passing here could be removed.
+        */
+
+       /*
+        *  Init built-in strings
+        */
+
+       DUK_DD(DUK_DDPRINT("HEAP: INIT STRINGS"));
+       if (!duk__init_heap_strings(res)) {
+               goto error;
+       }
+
+       /*
+        *  Init the heap thread
+        */
+
+       DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP THREAD"));
+       if (!duk__init_heap_thread(res)) {
+               goto error;
+       }
+
+       /*
+        *  Init the heap object
+        */
+
+       DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP OBJECT"));
+       DUK_ASSERT(res->heap_thread != NULL);
+       res->heap_object = duk_hobject_alloc(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
+                                                 
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
+       if (!res->heap_object) {
+               goto error;
+       }
+       DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
+
+       /*
+        *  All done
+        */
+
+       DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
+       return res;
+
+ error:
+       DUK_D(DUK_DPRINT("heap allocation failed"));
+
+       if (res) {
+               /* assumes that allocated pointers and alloc funcs are valid
+                * if res exists
+                */
+               DUK_ASSERT(res->alloc_func != NULL);
+               DUK_ASSERT(res->realloc_func != NULL);
+               DUK_ASSERT(res->free_func != NULL);
+               duk_heap_free(res);
+       }
+       return NULL;
+}
+
+#undef DUK__BITPACK_LETTER_LIMIT
+#undef DUK__BITPACK_UNDERSCORE
+#undef DUK__BITPACK_FF
+#undef DUK__BITPACK_SWITCH1
+#undef DUK__BITPACK_SWITCH
+#undef DUK__BITPACK_SEVENBIT
+#undef DUK__FIXED_HASH_SEED

Reply via email to