]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* |
2 | * Heap header definition and assorted macros, including ref counting. | |
3 | * Access all fields through the accessor macros. | |
4 | */ | |
5 | ||
6 | #ifndef DUK_HEAPHDR_H_INCLUDED | |
7 | #define DUK_HEAPHDR_H_INCLUDED | |
8 | ||
9 | /* | |
10 | * Common heap header | |
11 | * | |
12 | * All heap objects share the same flags and refcount fields. Objects other | |
13 | * than strings also need to have a single or double linked list pointers | |
14 | * for insertion into the "heap allocated" list. Strings are held in the | |
15 | * heap-wide string table so they don't need link pointers. | |
16 | * | |
17 | * Technically, 'h_refcount' must be wide enough to guarantee that it cannot | |
18 | * wrap (otherwise objects might be freed incorrectly after wrapping). This | |
19 | * means essentially that the refcount field must be as wide as data pointers. | |
20 | * On 64-bit platforms this means that the refcount needs to be 64 bits even | |
21 | * if an 'int' is 32 bits. This is a bit unfortunate, and compromising on | |
22 | * this might be reasonable in the future. | |
23 | * | |
24 | * Heap header size on 32-bit platforms: 8 bytes without reference counting, | |
25 | * 16 bytes with reference counting. | |
26 | */ | |
27 | ||
28 | struct duk_heaphdr { | |
29 | duk_uint32_t h_flags; | |
30 | ||
31 | #if defined(DUK_USE_REFERENCE_COUNTING) | |
32 | #if defined(DUK_USE_REFCOUNT16) | |
33 | duk_uint16_t h_refcount16; | |
34 | #else | |
35 | duk_size_t h_refcount; | |
36 | #endif | |
37 | #endif | |
38 | ||
39 | #if defined(DUK_USE_HEAPPTR16) | |
40 | duk_uint16_t h_next16; | |
41 | #else | |
42 | duk_heaphdr *h_next; | |
43 | #endif | |
44 | ||
45 | #if defined(DUK_USE_DOUBLE_LINKED_HEAP) | |
46 | /* refcounting requires direct heap frees, which in turn requires a dual linked heap */ | |
47 | #if defined(DUK_USE_HEAPPTR16) | |
48 | duk_uint16_t h_prev16; | |
49 | #else | |
50 | duk_heaphdr *h_prev; | |
51 | #endif | |
52 | #endif | |
53 | ||
54 | /* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the | |
55 | * struct won't align nicely to 4 bytes. This 16-bit extra field | |
56 | * is added to make the alignment clean; the field can be used by | |
57 | * heap objects when 16-bit packing is used. This field is now | |
58 | * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be | |
59 | * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP; | |
60 | * this only matter to low memory environments anyway. | |
61 | */ | |
62 | #if defined(DUK_USE_HEAPPTR16) | |
63 | duk_uint16_t h_extra16; | |
64 | #endif | |
65 | }; | |
66 | ||
67 | struct duk_heaphdr_string { | |
68 | /* 16 bits would be enough for shared heaphdr flags and duk_hstring | |
69 | * flags. The initial parts of duk_heaphdr_string and duk_heaphdr | |
70 | * must match so changing the flags field size here would be quite | |
71 | * awkward. However, to minimize struct size, we can pack at least | |
72 | * 16 bits of duk_hstring data into the flags field. | |
73 | */ | |
74 | duk_uint32_t h_flags; | |
75 | ||
76 | #if defined(DUK_USE_REFERENCE_COUNTING) | |
77 | #if defined(DUK_USE_REFCOUNT16) | |
78 | duk_uint16_t h_refcount16; | |
79 | duk_uint16_t h_strextra16; /* round out to 8 bytes */ | |
80 | #else | |
81 | duk_size_t h_refcount; | |
82 | #endif | |
83 | #else | |
84 | duk_uint16_t h_strextra16; | |
85 | #endif | |
86 | }; | |
87 | ||
88 | #define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL | |
89 | #define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK) | |
90 | ||
91 | /* 2 bits for heap type */ | |
92 | #define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */ | |
93 | #define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */ | |
94 | ||
95 | #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n)) | |
96 | #define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n)) | |
97 | #define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n))) | |
98 | #define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n))) | |
99 | ||
100 | #define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */ | |
101 | #define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */ | |
102 | #define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */ | |
103 | #define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */ | |
104 | #define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */ | |
105 | ||
106 | #define DUK_HTYPE_MIN 1 | |
107 | #define DUK_HTYPE_STRING 1 | |
108 | #define DUK_HTYPE_OBJECT 2 | |
109 | #define DUK_HTYPE_BUFFER 3 | |
110 | #define DUK_HTYPE_MAX 3 | |
111 | ||
112 | #if defined(DUK_USE_HEAPPTR16) | |
113 | #define DUK_HEAPHDR_GET_NEXT(heap,h) \ | |
114 | ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16)) | |
115 | #define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \ | |
116 | (h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \ | |
117 | } while (0) | |
118 | #else | |
119 | #define DUK_HEAPHDR_GET_NEXT(heap,h) ((h)->h_next) | |
120 | #define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \ | |
121 | (h)->h_next = (val); \ | |
122 | } while (0) | |
123 | #endif | |
124 | ||
125 | #if defined(DUK_USE_DOUBLE_LINKED_HEAP) | |
126 | #if defined(DUK_USE_HEAPPTR16) | |
127 | #define DUK_HEAPHDR_GET_PREV(heap,h) \ | |
128 | ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16)) | |
129 | #define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \ | |
130 | (h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \ | |
131 | } while (0) | |
132 | #else | |
133 | #define DUK_HEAPHDR_GET_PREV(heap,h) ((h)->h_prev) | |
134 | #define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \ | |
135 | (h)->h_prev = (val); \ | |
136 | } while (0) | |
137 | #endif | |
138 | #endif | |
139 | ||
140 | #if defined(DUK_USE_REFERENCE_COUNTING) | |
141 | #if defined(DUK_USE_REFCOUNT16) | |
142 | #define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount16) | |
143 | #define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \ | |
144 | (h)->h_refcount16 = (val); \ | |
145 | } while (0) | |
146 | #define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount16) /* result: updated refcount */ | |
147 | #define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount16) /* result: updated refcount */ | |
148 | #else | |
149 | #define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount) | |
150 | #define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \ | |
151 | (h)->h_refcount = (val); \ | |
152 | } while (0) | |
153 | #define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */ | |
154 | #define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */ | |
155 | #endif | |
156 | #else | |
157 | /* refcount macros not defined without refcounting, caller must #ifdef now */ | |
158 | #endif /* DUK_USE_REFERENCE_COUNTING */ | |
159 | ||
160 | /* | |
161 | * Note: type is treated as a field separate from flags, so some masking is | |
162 | * involved in the macros below. | |
163 | */ | |
164 | ||
165 | #define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags) | |
166 | ||
167 | #define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK) | |
168 | #define DUK_HEAPHDR_SET_FLAGS(h,val) do { \ | |
169 | (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \ | |
170 | } while (0) | |
171 | ||
172 | #define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK) | |
173 | #define DUK_HEAPHDR_SET_TYPE(h,val) do { \ | |
174 | (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \ | |
175 | } while (0) | |
176 | ||
177 | #define DUK_HEAPHDR_HTYPE_VALID(h) ( \ | |
178 | DUK_HEAPHDR_GET_TYPE((h)) >= DUK_HTYPE_MIN && \ | |
179 | DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \ | |
180 | ) | |
181 | ||
182 | #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval) do { \ | |
183 | (h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \ | |
184 | ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \ | |
185 | } while (0) | |
186 | ||
187 | #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits) do { \ | |
188 | DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \ | |
189 | (h)->h_flags |= (bits); \ | |
190 | } while (0) | |
191 | ||
192 | #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits) do { \ | |
193 | DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \ | |
194 | (h)->h_flags &= ~((bits)); \ | |
195 | } while (0) | |
196 | ||
197 | #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits) (((h)->h_flags & (bits)) != 0) | |
198 | ||
199 | #define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE) | |
200 | #define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE) | |
201 | #define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE) | |
202 | ||
203 | #define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT) | |
204 | #define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT) | |
205 | #define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT) | |
206 | ||
207 | #define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE) | |
208 | #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE) | |
209 | #define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE) | |
210 | ||
211 | #define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED) | |
212 | #define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED) | |
213 | #define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED) | |
214 | ||
215 | #define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY) | |
216 | #define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY) | |
217 | #define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY) | |
218 | ||
219 | /* get or set a range of flags; m=first bit number, n=number of bits */ | |
220 | #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL)) | |
221 | ||
222 | #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v) do { \ | |
223 | (h)->h_flags = \ | |
224 | ((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \ | |
225 | | ((v) << (m)); \ | |
226 | } while (0) | |
227 | ||
228 | /* init pointer fields to null */ | |
229 | #if defined(DUK_USE_DOUBLE_LINKED_HEAP) | |
230 | #define DUK_HEAPHDR_INIT_NULLS(h) do { \ | |
231 | DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \ | |
232 | DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \ | |
233 | } while (0) | |
234 | #else | |
235 | #define DUK_HEAPHDR_INIT_NULLS(h) do { \ | |
236 | DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \ | |
237 | } while (0) | |
238 | #endif | |
239 | ||
240 | #define DUK_HEAPHDR_STRING_INIT_NULLS(h) /* currently nop */ | |
241 | ||
242 | /* | |
243 | * Assert helpers | |
244 | */ | |
245 | ||
246 | /* Check that prev/next links are consistent: if e.g. h->prev is != NULL, | |
247 | * h->prev->next should point back to h. | |
248 | */ | |
249 | #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS) | |
250 | #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \ | |
251 | if ((h) != NULL) { \ | |
252 | duk_heaphdr *h__prev, *h__next; \ | |
253 | h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \ | |
254 | h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \ | |
255 | DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \ | |
256 | DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \ | |
257 | } \ | |
258 | } while (0) | |
259 | #else | |
260 | #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0) | |
261 | #endif | |
262 | ||
263 | /* | |
264 | * Reference counting helper macros. The macros take a thread argument | |
265 | * and must thus always be executed in a specific thread context. The | |
266 | * thread argument is needed for features like finalization. Currently | |
267 | * it is not required for INCREF, but it is included just in case. | |
268 | * | |
269 | * Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not | |
270 | * defined without DUK_USE_REFERENCE_COUNTING, so caller must #ifdef | |
271 | * around them. | |
272 | */ | |
273 | ||
274 | #if defined(DUK_USE_REFERENCE_COUNTING) | |
275 | ||
276 | #if defined(DUK_USE_ROM_OBJECTS) | |
277 | /* With ROM objects "needs refcount update" is true when the value is | |
278 | * heap allocated and is not a ROM object. | |
279 | */ | |
280 | /* XXX: double evaluation for 'tv' argument. */ | |
281 | #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \ | |
282 | (DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv)))) | |
283 | #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h))) | |
284 | #else /* DUK_USE_ROM_OBJECTS */ | |
285 | /* Without ROM objects "needs refcount update" == is heap allocated. */ | |
286 | #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv)) | |
287 | #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1 | |
288 | #endif /* DUK_USE_ROM_OBJECTS */ | |
289 | ||
290 | /* Fast variants, inline refcount operations except for refzero handling. | |
291 | * Can be used explicitly when speed is always more important than size. | |
292 | * For a good compiler and a single file build, these are basically the | |
293 | * same as a forced inline. | |
294 | */ | |
295 | #define DUK_TVAL_INCREF_FAST(thr,tv) do { \ | |
296 | duk_tval *duk__tv = (tv); \ | |
297 | DUK_ASSERT(duk__tv != NULL); \ | |
298 | if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \ | |
299 | duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \ | |
300 | DUK_ASSERT(duk__h != NULL); \ | |
301 | DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ | |
302 | DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \ | |
303 | } \ | |
304 | } while (0) | |
305 | #define DUK_TVAL_DECREF_FAST(thr,tv) do { \ | |
306 | duk_tval *duk__tv = (tv); \ | |
307 | DUK_ASSERT(duk__tv != NULL); \ | |
308 | if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \ | |
309 | duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \ | |
310 | DUK_ASSERT(duk__h != NULL); \ | |
311 | DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ | |
312 | DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \ | |
313 | if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \ | |
314 | duk_heaphdr_refzero((thr), duk__h); \ | |
315 | } \ | |
316 | } \ | |
317 | } while (0) | |
318 | #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \ | |
319 | duk_heaphdr *duk__h = (duk_heaphdr *) (h); \ | |
320 | DUK_ASSERT(duk__h != NULL); \ | |
321 | DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ | |
322 | if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \ | |
323 | DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \ | |
324 | } \ | |
325 | } while (0) | |
326 | #define DUK_HEAPHDR_DECREF_FAST(thr,h) do { \ | |
327 | duk_heaphdr *duk__h = (duk_heaphdr *) (h); \ | |
328 | DUK_ASSERT(duk__h != NULL); \ | |
329 | DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \ | |
330 | DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \ | |
331 | if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \ | |
332 | if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \ | |
333 | duk_heaphdr_refzero((thr), duk__h); \ | |
334 | } \ | |
335 | } \ | |
336 | } while (0) | |
337 | ||
338 | /* Slow variants, call to a helper to reduce code size. | |
339 | * Can be used explicitly when size is always more important than speed. | |
340 | */ | |
341 | #define DUK_TVAL_INCREF_SLOW(thr,tv) do { \ | |
342 | duk_tval_incref((tv)); \ | |
343 | } while (0) | |
344 | #define DUK_TVAL_DECREF_SLOW(thr,tv) do { \ | |
345 | duk_tval_decref((thr), (tv)); \ | |
346 | } while (0) | |
347 | #define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { \ | |
348 | duk_heaphdr_incref((duk_heaphdr *) (h)); \ | |
349 | } while (0) | |
350 | #define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { \ | |
351 | duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \ | |
352 | } while (0) | |
353 | ||
354 | /* Default variants. Selection depends on speed/size preference. | |
355 | * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary | |
356 | * is about +1kB for _FAST variants. | |
357 | */ | |
358 | #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT) | |
359 | #define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_FAST((thr),(tv)) | |
360 | #define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_FAST((thr),(tv)) | |
361 | #define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_FAST((thr),(h)) | |
362 | #define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST((thr),(h)) | |
363 | #else | |
364 | #define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_SLOW((thr),(tv)) | |
365 | #define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_SLOW((thr),(tv)) | |
366 | #define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_SLOW((thr),(h)) | |
367 | #define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_SLOW((thr),(h)) | |
368 | #endif | |
369 | ||
370 | /* Casting convenience. */ | |
371 | #define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) | |
372 | #define DUK_HSTRING_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h)) | |
373 | #define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) | |
374 | #define DUK_HOBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h)) | |
375 | #define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h)) | |
376 | #define DUK_HBUFFER_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h)) | |
377 | #define DUK_HCOMPILEDFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) | |
378 | #define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) | |
379 | #define DUK_HNATIVEFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) | |
380 | #define DUK_HNATIVEFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) | |
381 | #define DUK_HBUFFEROBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) | |
382 | #define DUK_HBUFFEROBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) | |
383 | #define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) | |
384 | #define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) | |
385 | ||
386 | /* Convenience for some situations; the above macros don't allow NULLs | |
387 | * for performance reasons. | |
388 | */ | |
389 | #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \ | |
390 | if ((h) != NULL) { \ | |
391 | DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \ | |
392 | } \ | |
393 | } while (0) | |
394 | #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \ | |
395 | if ((h) != NULL) { \ | |
396 | DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \ | |
397 | } \ | |
398 | } while (0) | |
399 | ||
400 | /* | |
401 | * Macros to set a duk_tval and update refcount of the target (decref the | |
402 | * old value and incref the new value if necessary). This is both performance | |
403 | * and footprint critical; any changes made should be measured for size/speed. | |
404 | */ | |
405 | ||
406 | #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
407 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
408 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
409 | DUK_TVAL_SET_UNDEFINED(tv__dst); \ | |
410 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
411 | } while (0) | |
412 | ||
413 | #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
414 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
415 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
416 | DUK_TVAL_SET_UNUSED(tv__dst); \ | |
417 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
418 | } while (0) | |
419 | ||
420 | #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
421 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
422 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
423 | DUK_TVAL_SET_NULL(tv__dst); \ | |
424 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
425 | } while (0) | |
426 | ||
427 | #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
428 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
429 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
430 | DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \ | |
431 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
432 | } while (0) | |
433 | ||
434 | #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
435 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
436 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
437 | DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \ | |
438 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
439 | } while (0) | |
440 | #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
441 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
442 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
443 | DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \ | |
444 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
445 | } while (0) | |
446 | #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
447 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
448 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
449 | DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \ | |
450 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
451 | } while (0) | |
452 | #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
453 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
454 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
455 | DUK_TVAL_SET_NAN(tv__dst); \ | |
456 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
457 | } while (0) | |
458 | #if defined(DUK_USE_FASTINT) | |
459 | #define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
460 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
461 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
462 | DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \ | |
463 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
464 | } while (0) | |
465 | #define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
466 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
467 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
468 | DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \ | |
469 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
470 | } while (0) | |
471 | #define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
472 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
473 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
474 | DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \ | |
475 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
476 | } while (0) | |
477 | #else | |
478 | #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \ | |
479 | DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval)) | |
480 | #endif /* DUK_USE_FASTINT */ | |
481 | ||
482 | #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \ | |
483 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
484 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
485 | DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \ | |
486 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
487 | } while (0) | |
488 | ||
489 | #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
490 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
491 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
492 | DUK_TVAL_SET_STRING(tv__dst, (newval)); \ | |
493 | DUK_HSTRING_INCREF((thr), (newval)); \ | |
494 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
495 | } while (0) | |
496 | ||
497 | #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
498 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
499 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
500 | DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \ | |
501 | DUK_HOBJECT_INCREF((thr), (newval)); \ | |
502 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
503 | } while (0) | |
504 | ||
505 | #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
506 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
507 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
508 | DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \ | |
509 | DUK_HBUFFER_INCREF((thr), (newval)); \ | |
510 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
511 | } while (0) | |
512 | ||
513 | #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
514 | duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \ | |
515 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
516 | DUK_TVAL_SET_POINTER(tv__dst, (newval)); \ | |
517 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
518 | } while (0) | |
519 | ||
520 | /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups, | |
521 | * etc, so it's very important for performance. Measure when changing. | |
522 | * | |
523 | * NOTE: the source and destination duk_tval pointers may be the same, and | |
524 | * the macros MUST deal with that correctly. | |
525 | */ | |
526 | ||
527 | /* Original idiom used, minimal code size. */ | |
528 | #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \ | |
529 | duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \ | |
530 | tv__dst = (tvptr_dst); tv__src = (tvptr_src); \ | |
531 | DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \ | |
532 | DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ | |
533 | DUK_TVAL_INCREF((thr), tv__src); \ | |
534 | DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \ | |
535 | } while (0) | |
536 | ||
537 | /* Faster alternative: avoid making a temporary copy of tvptr_dst and use | |
538 | * fast incref/decref macros. | |
539 | */ | |
540 | #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \ | |
541 | duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \ | |
542 | tv__dst = (tvptr_dst); tv__src = (tvptr_src); \ | |
543 | DUK_TVAL_INCREF_FAST((thr), tv__src); \ | |
544 | if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \ | |
545 | h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \ | |
546 | DUK_ASSERT(h__obj != NULL); \ | |
547 | DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ | |
548 | DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \ | |
549 | } else { \ | |
550 | DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ | |
551 | } \ | |
552 | } while (0) | |
553 | ||
554 | /* XXX: no optimized variants yet */ | |
555 | #define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0 | |
556 | #define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0 | |
557 | #define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0 | |
558 | #define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0 | |
559 | #define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0 | |
560 | #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0 | |
561 | #define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0 | |
562 | #define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0 | |
563 | #if defined(DUK_USE_FASTINT) | |
564 | #define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_FASTINT_UPDREF_ALT0 | |
565 | #define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0 | |
566 | #define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0 | |
567 | #else | |
568 | #define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */ | |
569 | #define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF | |
570 | #define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF | |
571 | #endif /* DUK_USE_FASTINT */ | |
572 | #define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0 | |
573 | #define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0 | |
574 | #define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0 | |
575 | #define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0 | |
576 | #define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0 | |
577 | ||
578 | #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT) | |
579 | /* Optimized for speed. */ | |
580 | #define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1 | |
581 | #define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1 | |
582 | #define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
583 | #else | |
584 | /* Optimized for size. */ | |
585 | #define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
586 | #define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
587 | #define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
588 | #endif | |
589 | ||
590 | #else /* DUK_USE_REFERENCE_COUNTING */ | |
591 | ||
592 | #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) 0 | |
593 | #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 0 | |
594 | ||
595 | #define DUK_TVAL_INCREF_FAST(thr,v) do {} while (0) /* nop */ | |
596 | #define DUK_TVAL_DECREF_FAST(thr,v) do {} while (0) /* nop */ | |
597 | #define DUK_TVAL_INCREF_SLOW(thr,v) do {} while (0) /* nop */ | |
598 | #define DUK_TVAL_DECREF_SLOW(thr,v) do {} while (0) /* nop */ | |
599 | #define DUK_TVAL_INCREF(thr,v) do {} while (0) /* nop */ | |
600 | #define DUK_TVAL_DECREF(thr,v) do {} while (0) /* nop */ | |
601 | #define DUK_HEAPHDR_INCREF_FAST(thr,h) do {} while (0) /* nop */ | |
602 | #define DUK_HEAPHDR_DECREF_FAST(thr,h) do {} while (0) /* nop */ | |
603 | #define DUK_HEAPHDR_INCREF_SLOW(thr,h) do {} while (0) /* nop */ | |
604 | #define DUK_HEAPHDR_DECREF_SLOW(thr,h) do {} while (0) /* nop */ | |
605 | #define DUK_HEAPHDR_INCREF(thr,h) do {} while (0) /* nop */ | |
606 | #define DUK_HEAPHDR_DECREF(thr,h) do {} while (0) /* nop */ | |
607 | #define DUK_HSTRING_INCREF(thr,h) do {} while (0) /* nop */ | |
608 | #define DUK_HSTRING_DECREF(thr,h) do {} while (0) /* nop */ | |
609 | #define DUK_HOBJECT_INCREF(thr,h) do {} while (0) /* nop */ | |
610 | #define DUK_HOBJECT_DECREF(thr,h) do {} while (0) /* nop */ | |
611 | #define DUK_HBUFFER_INCREF(thr,h) do {} while (0) /* nop */ | |
612 | #define DUK_HBUFFER_DECREF(thr,h) do {} while (0) /* nop */ | |
613 | #define DUK_HCOMPILEDFUNCTION_INCREF(thr,h) do {} while (0) /* nop */ | |
614 | #define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) do {} while (0) /* nop */ | |
615 | #define DUK_HNATIVEFUNCTION_INCREF(thr,h) do {} while (0) /* nop */ | |
616 | #define DUK_HNATIVEFUNCTION_DECREF(thr,h) do {} while (0) /* nop */ | |
617 | #define DUK_HBUFFEROBJECT_INCREF(thr,h) do {} while (0) /* nop */ | |
618 | #define DUK_HBUFFEROBJECT_DECREF(thr,h) do {} while (0) /* nop */ | |
619 | #define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */ | |
620 | #define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */ | |
621 | #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ | |
622 | #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ | |
623 | ||
624 | #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
625 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
626 | DUK_TVAL_SET_UNDEFINED(tv__dst); \ | |
627 | DUK_UNREF((thr)); \ | |
628 | } while (0) | |
629 | ||
630 | #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
631 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
632 | DUK_TVAL_SET_UNUSED(tv__dst); \ | |
633 | DUK_UNREF((thr)); \ | |
634 | } while (0) | |
635 | ||
636 | #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
637 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
638 | DUK_TVAL_SET_NULL(tv__dst); \ | |
639 | DUK_UNREF((thr)); \ | |
640 | } while (0) | |
641 | ||
642 | #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
643 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
644 | DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \ | |
645 | DUK_UNREF((thr)); \ | |
646 | } while (0) | |
647 | ||
648 | #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
649 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
650 | DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \ | |
651 | DUK_UNREF((thr)); \ | |
652 | } while (0) | |
653 | #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
654 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
655 | DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \ | |
656 | DUK_UNREF((thr)); \ | |
657 | } while (0) | |
658 | #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
659 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
660 | DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \ | |
661 | DUK_UNREF((thr)); \ | |
662 | } while (0) | |
663 | #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \ | |
664 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
665 | DUK_TVAL_SET_NAN(tv__dst); \ | |
666 | DUK_UNREF((thr)); \ | |
667 | } while (0) | |
668 | #if defined(DUK_USE_FASTINT) | |
669 | #define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
670 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
671 | DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \ | |
672 | DUK_UNREF((thr)); \ | |
673 | } while (0) | |
674 | #define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
675 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
676 | DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \ | |
677 | DUK_UNREF((thr)); \ | |
678 | } while (0) | |
679 | #define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
680 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
681 | DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \ | |
682 | DUK_UNREF((thr)); \ | |
683 | } while (0) | |
684 | #else | |
685 | #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \ | |
686 | DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval)) | |
687 | #endif /* DUK_USE_FASTINT */ | |
688 | ||
689 | #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \ | |
690 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
691 | DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \ | |
692 | DUK_UNREF((thr)); \ | |
693 | } while (0) | |
694 | ||
695 | #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
696 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
697 | DUK_TVAL_SET_STRING(tv__dst, (newval)); \ | |
698 | DUK_UNREF((thr)); \ | |
699 | } while (0) | |
700 | ||
701 | #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
702 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
703 | DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \ | |
704 | DUK_UNREF((thr)); \ | |
705 | } while (0) | |
706 | ||
707 | #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
708 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
709 | DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \ | |
710 | DUK_UNREF((thr)); \ | |
711 | } while (0) | |
712 | ||
713 | #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \ | |
714 | duk_tval *tv__dst; tv__dst = (tvptr_dst); \ | |
715 | DUK_TVAL_SET_POINTER(tv__dst, (newval)); \ | |
716 | DUK_UNREF((thr)); \ | |
717 | } while (0) | |
718 | ||
719 | #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \ | |
720 | duk_tval *tv__dst, *tv__src; \ | |
721 | tv__dst = (tvptr_dst); tv__src = (tvptr_src); \ | |
722 | DUK_TVAL_SET_TVAL(tv__dst, tv__src); \ | |
723 | DUK_UNREF((thr)); \ | |
724 | } while (0) | |
725 | ||
726 | #define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0 | |
727 | #define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0 | |
728 | #define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0 | |
729 | #define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0 | |
730 | #define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0 | |
731 | #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0 | |
732 | #define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0 | |
733 | #define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0 | |
734 | #if defined(DUK_USE_FASTINT) | |
735 | #define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_FASTINT_UPDREF_ALT0 | |
736 | #define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0 | |
737 | #define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0 | |
738 | #else | |
739 | #define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */ | |
740 | #define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF | |
741 | #define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF | |
742 | #endif /* DUK_USE_FASTINT */ | |
743 | #define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0 | |
744 | #define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0 | |
745 | #define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0 | |
746 | #define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0 | |
747 | #define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0 | |
748 | ||
749 | #define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
750 | #define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
751 | #define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0 | |
752 | ||
753 | #endif /* DUK_USE_REFERENCE_COUNTING */ | |
754 | ||
755 | #endif /* DUK_HEAPHDR_H_INCLUDED */ |