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 */ 756