4 * Provides primitive allocation functions for all object types (plain object,
5 * compiled function, native function, thread). The object return is not yet
6 * in "heap allocated" list and has a refcount of zero, so caller must careful.
9 #include "duk_internal.h"
11 DUK_LOCAL
void duk__init_object_parts(duk_heap
*heap
, duk_hobject
*obj
, duk_uint_t hobject_flags
) {
12 #ifdef DUK_USE_EXPLICIT_NULL_INIT
13 DUK_HOBJECT_SET_PROPS(heap
, obj
, NULL
);
16 /* XXX: macro? sets both heaphdr and object flags */
17 obj
->hdr
.h_flags
= hobject_flags
;
18 DUK_HEAPHDR_SET_TYPE(&obj
->hdr
, DUK_HTYPE_OBJECT
); /* also goes into flags */
20 #if defined(DUK_USE_HEAPPTR16)
21 /* Zero encoded pointer is required to match NULL */
22 DUK_HEAPHDR_SET_NEXT(heap
, &obj
->hdr
, NULL
);
23 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
24 DUK_HEAPHDR_SET_PREV(heap
, &obj
->hdr
, NULL
);
27 DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap
, &obj
->hdr
);
30 * obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
31 * with this properly. This is intentional: empty objects consume a minimum
32 * amount of memory. Further, an initial allocation might fail and cause
33 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
38 * Allocate an duk_hobject.
40 * The allocated object has no allocation for properties; the caller may
41 * want to force a resize if a desired size is known.
43 * The allocated object has zero reference count and is not reachable.
44 * The caller MUST make the object reachable and increase its reference
45 * count before invoking any operation that might require memory allocation.
48 DUK_INTERNAL duk_hobject
*duk_hobject_alloc(duk_heap
*heap
, duk_uint_t hobject_flags
) {
51 DUK_ASSERT(heap
!= NULL
);
53 /* different memory layout, alloc size, and init */
54 DUK_ASSERT((hobject_flags
& DUK_HOBJECT_FLAG_COMPILEDFUNCTION
) == 0);
55 DUK_ASSERT((hobject_flags
& DUK_HOBJECT_FLAG_NATIVEFUNCTION
) == 0);
56 DUK_ASSERT((hobject_flags
& DUK_HOBJECT_FLAG_THREAD
) == 0);
58 res
= (duk_hobject
*) DUK_ALLOC(heap
, sizeof(duk_hobject
));
62 DUK_MEMZERO(res
, sizeof(duk_hobject
));
64 duk__init_object_parts(heap
, res
, hobject_flags
);
69 DUK_INTERNAL duk_hcompiledfunction
*duk_hcompiledfunction_alloc(duk_heap
*heap
, duk_uint_t hobject_flags
) {
70 duk_hcompiledfunction
*res
;
72 res
= (duk_hcompiledfunction
*) DUK_ALLOC(heap
, sizeof(duk_hcompiledfunction
));
76 DUK_MEMZERO(res
, sizeof(duk_hcompiledfunction
));
78 duk__init_object_parts(heap
, &res
->obj
, hobject_flags
);
80 #ifdef DUK_USE_EXPLICIT_NULL_INIT
81 #ifdef DUK_USE_HEAPPTR16
82 /* NULL pointer is required to encode to zero, so memset is enough. */
93 DUK_INTERNAL duk_hnativefunction
*duk_hnativefunction_alloc(duk_heap
*heap
, duk_uint_t hobject_flags
) {
94 duk_hnativefunction
*res
;
96 res
= (duk_hnativefunction
*) DUK_ALLOC(heap
, sizeof(duk_hnativefunction
));
100 DUK_MEMZERO(res
, sizeof(duk_hnativefunction
));
102 duk__init_object_parts(heap
, &res
->obj
, hobject_flags
);
104 #ifdef DUK_USE_EXPLICIT_NULL_INIT
111 DUK_INTERNAL duk_hbufferobject
*duk_hbufferobject_alloc(duk_heap
*heap
, duk_uint_t hobject_flags
) {
112 duk_hbufferobject
*res
;
114 res
= (duk_hbufferobject
*) DUK_ALLOC(heap
, sizeof(duk_hbufferobject
));
118 DUK_MEMZERO(res
, sizeof(duk_hbufferobject
));
120 duk__init_object_parts(heap
, &res
->obj
, hobject_flags
);
122 #ifdef DUK_USE_EXPLICIT_NULL_INIT
126 DUK_ASSERT_HBUFFEROBJECT_VALID(res
);
131 * Allocate a new thread.
133 * Leaves the built-ins array uninitialized. The caller must either
134 * initialize a new global context or share existing built-ins from
138 DUK_INTERNAL duk_hthread
*duk_hthread_alloc(duk_heap
*heap
, duk_uint_t hobject_flags
) {
141 res
= (duk_hthread
*) DUK_ALLOC(heap
, sizeof(duk_hthread
));
145 DUK_MEMZERO(res
, sizeof(duk_hthread
));
147 duk__init_object_parts(heap
, &res
->obj
, hobject_flags
);
149 #ifdef DUK_USE_EXPLICIT_NULL_INIT
150 res
->ptr_curr_pc
= NULL
;
152 res
->valstack
= NULL
;
153 res
->valstack_end
= NULL
;
154 res
->valstack_bottom
= NULL
;
155 res
->valstack_top
= NULL
;
156 res
->callstack
= NULL
;
157 res
->catchstack
= NULL
;
159 res
->compile_ctx
= NULL
,
160 #ifdef DUK_USE_HEAPPTR16
167 for (i
= 0; i
< DUK_NUM_BUILTINS
; i
++) {
168 res
->builtins
[i
] = NULL
;
172 /* when nothing is running, API calls are in non-strict mode */
173 DUK_ASSERT(res
->strict
== 0);
176 res
->valstack_max
= DUK_VALSTACK_DEFAULT_MAX
;
177 res
->callstack_max
= DUK_CALLSTACK_DEFAULT_MAX
;
178 res
->catchstack_max
= DUK_CATCHSTACK_DEFAULT_MAX
;
183 #if 0 /* unused now */
184 DUK_INTERNAL duk_hobject
*duk_hobject_alloc_checked(duk_hthread
*thr
, duk_uint_t hobject_flags
) {
185 duk_hobject
*res
= duk_hobject_alloc(thr
->heap
, hobject_flags
);
187 DUK_ERROR(thr
, DUK_ERR_ALLOC_ERROR
, "failed to allocate an object");