/* * Hobject allocation. * * Provides primitive allocation functions for all object types (plain object, * compiled function, native function, thread). The object return is not yet * in "heap allocated" list and has a refcount of zero, so caller must careful. */ #include "duk_internal.h" DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) { #ifdef DUK_USE_EXPLICIT_NULL_INIT obj->p = NULL; #endif /* XXX: macro? sets both heaphdr and object flags */ obj->hdr.h_flags = hobject_flags; DUK_HEAPHDR_SET_TYPE(&obj->hdr, DUK_HTYPE_OBJECT); /* also goes into flags */ DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr); /* * obj->p is intentionally left as NULL, and duk_hobject_props.c must deal * with this properly. This is intentional: empty objects consume a minimum * amount of memory. Further, an initial allocation might fail and cause * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet. */ } /* * Allocate an duk_hobject. * * The allocated object has no allocation for properties; the caller may * want to force a resize if a desired size is known. * * The allocated object has zero reference count and is not reachable. * The caller MUST make the object reachable and increase its reference * count before invoking any operation that might require memory allocation. */ DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) { duk_hobject *res; DUK_ASSERT(heap != NULL); /* different memory layout, alloc size, and init */ DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPILEDFUNCTION) == 0); DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATIVEFUNCTION) == 0); DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_THREAD) == 0); res = (duk_hobject *) DUK_ALLOC(heap, sizeof(duk_hobject)); if (!res) { return NULL; } DUK_MEMZERO(res, sizeof(duk_hobject)); duk__init_object_parts(heap, res, hobject_flags); return res; } DUK_INTERNAL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) { duk_hcompiledfunction *res; res = (duk_hcompiledfunction *) DUK_ALLOC(heap, sizeof(duk_hcompiledfunction)); if (!res) { return NULL; } DUK_MEMZERO(res, sizeof(duk_hcompiledfunction)); duk__init_object_parts(heap, &res->obj, hobject_flags); #ifdef DUK_USE_EXPLICIT_NULL_INIT res->data = NULL; res->funcs = NULL; res->bytecode = NULL; #endif return res; } DUK_INTERNAL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) { duk_hnativefunction *res; res = (duk_hnativefunction *) DUK_ALLOC(heap, sizeof(duk_hnativefunction)); if (!res) { return NULL; } DUK_MEMZERO(res, sizeof(duk_hnativefunction)); duk__init_object_parts(heap, &res->obj, hobject_flags); #ifdef DUK_USE_EXPLICIT_NULL_INIT res->func = NULL; #endif return res; } /* * Allocate a new thread. * * Leaves the built-ins array uninitialized. The caller must either * initialize a new global context or share existing built-ins from * another thread. */ DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) { duk_hthread *res; res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread)); if (!res) { return NULL; } DUK_MEMZERO(res, sizeof(duk_hthread)); duk__init_object_parts(heap, &res->obj, hobject_flags); #ifdef DUK_USE_EXPLICIT_NULL_INIT res->heap = NULL; res->valstack = NULL; res->valstack_end = NULL; res->valstack_bottom = NULL; res->valstack_top = NULL; res->callstack = NULL; res->catchstack = NULL; res->resumer = NULL; res->strs = NULL; { int i; for (i = 0; i < DUK_NUM_BUILTINS; i++) { res->builtins[i] = NULL; } } #endif /* when nothing is running, API calls are in non-strict mode */ DUK_ASSERT(res->strict == 0); res->heap = heap; res->valstack_max = DUK_VALSTACK_DEFAULT_MAX; res->callstack_max = DUK_CALLSTACK_DEFAULT_MAX; res->catchstack_max = DUK_CATCHSTACK_DEFAULT_MAX; return res; } #if 0 /* unused now */ DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) { duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags); if (!res) { DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "failed to allocate an object"); } return res; } #endif