]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Hobject allocation. | |
3 | * | |
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. | |
7 | */ | |
8 | ||
9 | #include "duk_internal.h" | |
10 | ||
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); | |
14 | #endif | |
15 | ||
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 */ | |
19 | ||
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); | |
25 | #endif | |
26 | #endif | |
11fdf7f2 TL |
27 | DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr); |
28 | DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr); | |
7c673cae FG |
29 | |
30 | /* | |
31 | * obj->props is intentionally left as NULL, and duk_hobject_props.c must deal | |
32 | * with this properly. This is intentional: empty objects consume a minimum | |
33 | * amount of memory. Further, an initial allocation might fail and cause | |
34 | * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet. | |
35 | */ | |
36 | } | |
37 | ||
38 | /* | |
39 | * Allocate an duk_hobject. | |
40 | * | |
41 | * The allocated object has no allocation for properties; the caller may | |
42 | * want to force a resize if a desired size is known. | |
43 | * | |
44 | * The allocated object has zero reference count and is not reachable. | |
45 | * The caller MUST make the object reachable and increase its reference | |
46 | * count before invoking any operation that might require memory allocation. | |
47 | */ | |
48 | ||
49 | DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) { | |
50 | duk_hobject *res; | |
51 | ||
52 | DUK_ASSERT(heap != NULL); | |
53 | ||
54 | /* different memory layout, alloc size, and init */ | |
55 | DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPILEDFUNCTION) == 0); | |
56 | DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATIVEFUNCTION) == 0); | |
57 | DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_THREAD) == 0); | |
58 | ||
59 | res = (duk_hobject *) DUK_ALLOC(heap, sizeof(duk_hobject)); | |
60 | if (!res) { | |
61 | return NULL; | |
62 | } | |
63 | DUK_MEMZERO(res, sizeof(duk_hobject)); | |
64 | ||
65 | duk__init_object_parts(heap, res, hobject_flags); | |
66 | ||
67 | return res; | |
68 | } | |
69 | ||
70 | DUK_INTERNAL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) { | |
71 | duk_hcompiledfunction *res; | |
72 | ||
73 | res = (duk_hcompiledfunction *) DUK_ALLOC(heap, sizeof(duk_hcompiledfunction)); | |
74 | if (!res) { | |
75 | return NULL; | |
76 | } | |
77 | DUK_MEMZERO(res, sizeof(duk_hcompiledfunction)); | |
78 | ||
79 | duk__init_object_parts(heap, &res->obj, hobject_flags); | |
80 | ||
81 | #ifdef DUK_USE_EXPLICIT_NULL_INIT | |
82 | #ifdef DUK_USE_HEAPPTR16 | |
83 | /* NULL pointer is required to encode to zero, so memset is enough. */ | |
84 | #else | |
85 | res->data = NULL; | |
86 | res->funcs = NULL; | |
87 | res->bytecode = NULL; | |
88 | #endif | |
89 | #endif | |
90 | ||
91 | return res; | |
92 | } | |
93 | ||
94 | DUK_INTERNAL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) { | |
95 | duk_hnativefunction *res; | |
96 | ||
97 | res = (duk_hnativefunction *) DUK_ALLOC(heap, sizeof(duk_hnativefunction)); | |
98 | if (!res) { | |
99 | return NULL; | |
100 | } | |
101 | DUK_MEMZERO(res, sizeof(duk_hnativefunction)); | |
102 | ||
103 | duk__init_object_parts(heap, &res->obj, hobject_flags); | |
104 | ||
105 | #ifdef DUK_USE_EXPLICIT_NULL_INIT | |
106 | res->func = NULL; | |
107 | #endif | |
108 | ||
109 | return res; | |
110 | } | |
111 | ||
112 | DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) { | |
113 | duk_hbufferobject *res; | |
114 | ||
115 | res = (duk_hbufferobject *) DUK_ALLOC(heap, sizeof(duk_hbufferobject)); | |
116 | if (!res) { | |
117 | return NULL; | |
118 | } | |
119 | DUK_MEMZERO(res, sizeof(duk_hbufferobject)); | |
120 | ||
121 | duk__init_object_parts(heap, &res->obj, hobject_flags); | |
122 | ||
123 | #ifdef DUK_USE_EXPLICIT_NULL_INIT | |
124 | res->buf = NULL; | |
125 | #endif | |
126 | ||
127 | DUK_ASSERT_HBUFFEROBJECT_VALID(res); | |
128 | return res; | |
129 | } | |
130 | ||
131 | /* | |
132 | * Allocate a new thread. | |
133 | * | |
134 | * Leaves the built-ins array uninitialized. The caller must either | |
135 | * initialize a new global context or share existing built-ins from | |
136 | * another thread. | |
137 | */ | |
138 | ||
139 | DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) { | |
140 | duk_hthread *res; | |
141 | ||
142 | res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread)); | |
143 | if (!res) { | |
144 | return NULL; | |
145 | } | |
146 | DUK_MEMZERO(res, sizeof(duk_hthread)); | |
147 | ||
148 | duk__init_object_parts(heap, &res->obj, hobject_flags); | |
149 | ||
150 | #ifdef DUK_USE_EXPLICIT_NULL_INIT | |
151 | res->ptr_curr_pc = NULL; | |
152 | res->heap = NULL; | |
153 | res->valstack = NULL; | |
154 | res->valstack_end = NULL; | |
155 | res->valstack_bottom = NULL; | |
156 | res->valstack_top = NULL; | |
157 | res->callstack = NULL; | |
158 | res->catchstack = NULL; | |
159 | res->resumer = NULL; | |
160 | res->compile_ctx = NULL, | |
161 | #ifdef DUK_USE_HEAPPTR16 | |
162 | res->strs16 = NULL; | |
163 | #else | |
164 | res->strs = NULL; | |
165 | #endif | |
166 | { | |
167 | int i; | |
168 | for (i = 0; i < DUK_NUM_BUILTINS; i++) { | |
169 | res->builtins[i] = NULL; | |
170 | } | |
171 | } | |
172 | #endif | |
173 | /* when nothing is running, API calls are in non-strict mode */ | |
174 | DUK_ASSERT(res->strict == 0); | |
175 | ||
176 | res->heap = heap; | |
177 | res->valstack_max = DUK_VALSTACK_DEFAULT_MAX; | |
178 | res->callstack_max = DUK_CALLSTACK_DEFAULT_MAX; | |
179 | res->catchstack_max = DUK_CATCHSTACK_DEFAULT_MAX; | |
180 | ||
181 | return res; | |
182 | } | |
183 | ||
184 | #if 0 /* unused now */ | |
185 | DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) { | |
186 | duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags); | |
187 | if (!res) { | |
11fdf7f2 | 188 | DUK_ERROR_ALLOC_DEFMSG(thr); |
7c673cae FG |
189 | } |
190 | return res; | |
191 | } | |
192 | #endif |