]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_tval.h
import 12.2.13 release
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.5.2 / src-separate / duk_tval.h
1 /*
2 * Tagged type definition (duk_tval) and accessor macros.
3 *
4 * Access all fields through the accessor macros, as the representation
5 * is quite tricky.
6 *
7 * There are two packed type alternatives: an 8-byte representation
8 * based on an IEEE double (preferred for compactness), and a 12-byte
9 * representation (portability). The latter is needed also in e.g.
10 * 64-bit environments (it usually pads to 16 bytes per value).
11 *
12 * Selecting the tagged type format involves many trade-offs (memory
13 * use, size and performance of generated code, portability, etc),
14 * see doc/types.rst for a detailed discussion (especially of how the
15 * IEEE double format is used to pack tagged values).
16 *
17 * NB: because macro arguments are often expressions, macros should
18 * avoid evaluating their argument more than once.
19 */
20
21 #ifndef DUK_TVAL_H_INCLUDED
22 #define DUK_TVAL_H_INCLUDED
23
24 /* sanity */
25 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
26 #error unsupported: cannot determine byte order variant
27 #endif
28
29 #if defined(DUK_USE_PACKED_TVAL)
30 /* ======================================================================== */
31
32 /*
33 * Packed 8-byte representation
34 */
35
36 /* use duk_double_union as duk_tval directly */
37 typedef union duk_double_union duk_tval;
38
39 /* tags */
40 #define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
41 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
42 #if defined(DUK_USE_FASTINT)
43 #define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
44 #endif
45 #define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
46 #define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
47 #define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
48 #define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
49 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
50 #define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
51 #define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
52 #define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
53 #define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
54 #define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
55
56 /* for convenience */
57 #define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
58 #define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
59
60 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
61 #if defined(DUK_USE_64BIT_OPS)
62 #if defined(DUK_USE_DOUBLE_ME)
63 #define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
64 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
65 } while (0)
66 #else
67 #define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
68 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
69 } while (0)
70 #endif
71 #else /* DUK_USE_64BIT_OPS */
72 #define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
73 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
74 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
75 } while (0)
76 #endif /* DUK_USE_64BIT_OPS */
77
78 #if defined(DUK_USE_64BIT_OPS)
79 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
80 #if defined(DUK_USE_DOUBLE_ME)
81 #define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
82 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
83 ((duk_uint64_t) (flags)) | \
84 (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
85 } while (0)
86 #else
87 #define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
88 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
89 (((duk_uint64_t) (flags)) << 32) | \
90 ((duk_uint64_t) (duk_uint32_t) (fp)); \
91 } while (0)
92 #endif
93 #else /* DUK_USE_64BIT_OPS */
94 #define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
95 (v)->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
96 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
97 } while (0)
98 #endif /* DUK_USE_64BIT_OPS */
99
100 #if defined(DUK_USE_FASTINT)
101 /* Note: masking is done for 'i' to deal with negative numbers correctly */
102 #if defined(DUK_USE_DOUBLE_ME)
103 #define DUK__TVAL_SET_FASTINT(v,i) do { \
104 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
105 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
106 } while (0)
107 #define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
108 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
109 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
110 } while (0)
111 #else
112 #define DUK__TVAL_SET_FASTINT(v,i) do { \
113 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
114 } while (0)
115 #define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
116 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
117 } while (0)
118 #endif
119
120 #define DUK__TVAL_SET_FASTINT_I32(v,i) do { \
121 duk_int64_t duk__tmp = (duk_int64_t) (i); \
122 DUK_TVAL_SET_FASTINT((v), duk__tmp); \
123 } while (0)
124
125 /* XXX: clumsy sign extend and masking of 16 topmost bits */
126 #if defined(DUK_USE_DOUBLE_ME)
127 #define DUK__TVAL_GET_FASTINT(v) (((duk_int64_t) ((((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
128 #else
129 #define DUK__TVAL_GET_FASTINT(v) ((((duk_int64_t) (v)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
130 #endif
131 #define DUK__TVAL_GET_FASTINT_U32(v) ((v)->ui[DUK_DBL_IDX_UI1])
132 #define DUK__TVAL_GET_FASTINT_I32(v) ((duk_int32_t) (v)->ui[DUK_DBL_IDX_UI1])
133 #endif /* DUK_USE_FASTINT */
134
135 #define DUK_TVAL_SET_UNDEFINED(v) do { \
136 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
137 } while (0)
138 #define DUK_TVAL_SET_UNUSED(v) do { \
139 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
140 } while (0)
141 #define DUK_TVAL_SET_NULL(v) do { \
142 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
143 } while (0)
144
145 #define DUK_TVAL_SET_BOOLEAN(v,val) DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
146
147 #define DUK_TVAL_SET_NAN(v) DUK_DBLUNION_SET_NAN_FULL((v))
148
149 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
150 #if defined(DUK_USE_FASTINT)
151 #define DUK_TVAL_SET_DOUBLE(v,d) do { \
152 duk_double_t duk__dblval; \
153 duk__dblval = (d); \
154 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
155 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
156 } while (0)
157 #define DUK_TVAL_SET_FASTINT(v,i) DUK__TVAL_SET_FASTINT((v), (i))
158 #define DUK_TVAL_SET_FASTINT_I32(v,i) DUK__TVAL_SET_FASTINT_I32((v), (i))
159 #define DUK_TVAL_SET_FASTINT_U32(v,i) DUK__TVAL_SET_FASTINT_U32((v), (i))
160 #define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) duk_tval_set_number_chkfast((v), (d))
161 #define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
162 #define DUK_TVAL_CHKFAST_INPLACE(v) do { \
163 duk_tval *duk__tv; \
164 duk_double_t duk__d; \
165 duk__tv = (v); \
166 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
167 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
168 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
169 } \
170 } while (0)
171 #else
172 #define DUK_TVAL_SET_DOUBLE(v,d) do { \
173 duk_double_t duk__dblval; \
174 duk__dblval = (d); \
175 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
176 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
177 } while (0)
178 #define DUK_TVAL_SET_FASTINT(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i)) /* XXX: fast int-to-double */
179 #define DUK_TVAL_SET_FASTINT_I32(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
180 #define DUK_TVAL_SET_FASTINT_U32(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
181 #define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
182 #define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
183 #define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
184 #endif
185
186 #define DUK_TVAL_SET_LIGHTFUNC(v,fp,flags) DUK__TVAL_SET_LIGHTFUNC((v), (fp), (flags))
187 #define DUK_TVAL_SET_STRING(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_STRING)
188 #define DUK_TVAL_SET_OBJECT(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_OBJECT)
189 #define DUK_TVAL_SET_BUFFER(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_BUFFER)
190 #define DUK_TVAL_SET_POINTER(v,p) DUK__TVAL_SET_TAGGEDPOINTER((v), (p), DUK_TAG_POINTER)
191
192 #define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
193
194 /* getters */
195 #define DUK_TVAL_GET_BOOLEAN(v) ((int) (v)->us[DUK_DBL_IDX_US1])
196 #if defined(DUK_USE_FASTINT)
197 #define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
198 #define DUK_TVAL_GET_FASTINT(v) DUK__TVAL_GET_FASTINT((v))
199 #define DUK_TVAL_GET_FASTINT_U32(v) DUK__TVAL_GET_FASTINT_U32((v))
200 #define DUK_TVAL_GET_FASTINT_I32(v) DUK__TVAL_GET_FASTINT_I32((v))
201 #define DUK_TVAL_GET_NUMBER(v) duk_tval_get_number_packed((v))
202 #else
203 #define DUK_TVAL_GET_NUMBER(v) ((v)->d)
204 #define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
205 #endif
206 #define DUK_TVAL_GET_LIGHTFUNC(v,out_fp,out_flags) do { \
207 (out_flags) = (v)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
208 (out_fp) = (duk_c_function) (v)->ui[DUK_DBL_IDX_UI1]; \
209 } while (0)
210 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(v) ((duk_c_function) ((v)->ui[DUK_DBL_IDX_UI1]))
211 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(v) (((int) (v)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
212 #define DUK_TVAL_GET_STRING(v) ((duk_hstring *) (v)->vp[DUK_DBL_IDX_VP1])
213 #define DUK_TVAL_GET_OBJECT(v) ((duk_hobject *) (v)->vp[DUK_DBL_IDX_VP1])
214 #define DUK_TVAL_GET_BUFFER(v) ((duk_hbuffer *) (v)->vp[DUK_DBL_IDX_VP1])
215 #define DUK_TVAL_GET_POINTER(v) ((void *) (v)->vp[DUK_DBL_IDX_VP1])
216 #define DUK_TVAL_GET_HEAPHDR(v) ((duk_heaphdr *) (v)->vp[DUK_DBL_IDX_VP1])
217
218 /* decoding */
219 #define DUK_TVAL_GET_TAG(v) ((duk_small_uint_t) (v)->us[DUK_DBL_IDX_US0])
220
221 #define DUK_TVAL_IS_UNDEFINED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNDEFINED)
222 #define DUK_TVAL_IS_UNUSED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNUSED)
223 #define DUK_TVAL_IS_NULL(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_NULL)
224 #define DUK_TVAL_IS_BOOLEAN(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BOOLEAN)
225 #define DUK_TVAL_IS_BOOLEAN_TRUE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
226 #define DUK_TVAL_IS_BOOLEAN_FALSE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
227 #define DUK_TVAL_IS_LIGHTFUNC(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_LIGHTFUNC)
228 #define DUK_TVAL_IS_STRING(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_STRING)
229 #define DUK_TVAL_IS_OBJECT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_OBJECT)
230 #define DUK_TVAL_IS_BUFFER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BUFFER)
231 #define DUK_TVAL_IS_POINTER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_POINTER)
232 #if defined(DUK_USE_FASTINT)
233 /* 0xfff0 is -Infinity */
234 #define DUK_TVAL_IS_DOUBLE(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
235 #define DUK_TVAL_IS_FASTINT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_FASTINT)
236 #define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff1UL)
237 #else
238 #define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
239 #define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
240 #endif
241
242 /* This is performance critical because it appears in every DECREF. */
243 #define DUK_TVAL_IS_HEAP_ALLOCATED(v) (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING)
244
245 #if defined(DUK_USE_FASTINT)
246 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
247 #endif
248
249 #else /* DUK_USE_PACKED_TVAL */
250 /* ======================================================================== */
251
252 /*
253 * Portable 12-byte representation
254 */
255
256 /* Note: not initializing all bytes is normally not an issue: Duktape won't
257 * read or use the uninitialized bytes so valgrind won't issue warnings.
258 * In some special cases a harmless valgrind warning may be issued though.
259 * For example, the DumpHeap debugger command writes out a compiled function's
260 * 'data' area as is, including any uninitialized bytes, which causes a
261 * valgrind warning.
262 */
263
264 typedef struct duk_tval_struct duk_tval;
265
266 struct duk_tval_struct {
267 duk_small_uint_t t;
268 duk_small_uint_t v_extra;
269 union {
270 duk_double_t d;
271 duk_small_int_t i;
272 #if defined(DUK_USE_FASTINT)
273 duk_int64_t fi; /* if present, forces 16-byte duk_tval */
274 #endif
275 void *voidptr;
276 duk_hstring *hstring;
277 duk_hobject *hobject;
278 duk_hcompiledfunction *hcompiledfunction;
279 duk_hnativefunction *hnativefunction;
280 duk_hthread *hthread;
281 duk_hbuffer *hbuffer;
282 duk_heaphdr *heaphdr;
283 duk_c_function lightfunc;
284 } v;
285 };
286
287 #define DUK__TAG_NUMBER 0 /* not exposed */
288 #if defined(DUK_USE_FASTINT)
289 #define DUK_TAG_FASTINT 1
290 #endif
291 #define DUK_TAG_UNDEFINED 2
292 #define DUK_TAG_NULL 3
293 #define DUK_TAG_BOOLEAN 4
294 #define DUK_TAG_POINTER 5
295 #define DUK_TAG_LIGHTFUNC 6
296 #define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
297 #define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
298 #define DUK_TAG_OBJECT 9
299 #define DUK_TAG_BUFFER 10
300
301 /* DUK__TAG_NUMBER is intentionally first, as it is the default clause in code
302 * to support the 8-byte representation. Further, it is a non-heap-allocated
303 * type so it should come before DUK_TAG_STRING. Finally, it should not break
304 * the tag value ranges covered by case-clauses in a switch-case.
305 */
306
307 /* setters */
308 #define DUK_TVAL_SET_UNDEFINED(tv) do { \
309 (tv)->t = DUK_TAG_UNDEFINED; \
310 } while (0)
311
312 #define DUK_TVAL_SET_UNUSED(tv) do { \
313 (tv)->t = DUK_TAG_UNUSED; \
314 } while (0)
315
316 #define DUK_TVAL_SET_NULL(tv) do { \
317 (tv)->t = DUK_TAG_NULL; \
318 } while (0)
319
320 #define DUK_TVAL_SET_BOOLEAN(tv,val) do { \
321 (tv)->t = DUK_TAG_BOOLEAN; \
322 (tv)->v.i = (val); \
323 } while (0)
324
325 #if defined(DUK_USE_FASTINT)
326 #define DUK_TVAL_SET_DOUBLE(tv,val) do { \
327 (tv)->t = DUK__TAG_NUMBER; \
328 (tv)->v.d = (val); \
329 } while (0)
330 #define DUK_TVAL_SET_FASTINT(tv,val) do { \
331 (tv)->t = DUK_TAG_FASTINT; \
332 (tv)->v.fi = (val); \
333 } while (0)
334 #define DUK_TVAL_SET_FASTINT_U32(tv,val) do { \
335 (tv)->t = DUK_TAG_FASTINT; \
336 (tv)->v.fi = (duk_int64_t) (val); \
337 } while (0)
338 #define DUK_TVAL_SET_FASTINT_I32(tv,val) do { \
339 (tv)->t = DUK_TAG_FASTINT; \
340 (tv)->v.fi = (duk_int64_t) (val); \
341 } while (0)
342 #define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
343 duk_tval_set_number_chkfast((tv), (d))
344 #define DUK_TVAL_SET_NUMBER(tv,val) \
345 DUK_TVAL_SET_DOUBLE((tv), (val))
346 #define DUK_TVAL_CHKFAST_INPLACE(v) do { \
347 duk_tval *duk__tv; \
348 duk_double_t duk__d; \
349 duk__tv = (v); \
350 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
351 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
352 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
353 } \
354 } while (0)
355 #else
356 #define DUK_TVAL_SET_DOUBLE(tv,d) \
357 DUK_TVAL_SET_NUMBER((tv), (d))
358 #define DUK_TVAL_SET_FASTINT(tv,val) \
359 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
360 #define DUK_TVAL_SET_FASTINT_U32(tv,val) \
361 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
362 #define DUK_TVAL_SET_FASTINT_I32(tv,val) \
363 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
364 #define DUK_TVAL_SET_NUMBER(tv,val) do { \
365 (tv)->t = DUK__TAG_NUMBER; \
366 (tv)->v.d = (val); \
367 } while (0)
368 #define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
369 DUK_TVAL_SET_NUMBER((tv), (d))
370 #define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
371 #endif /* DUK_USE_FASTINT */
372
373 #define DUK_TVAL_SET_POINTER(tv,hptr) do { \
374 (tv)->t = DUK_TAG_POINTER; \
375 (tv)->v.voidptr = (hptr); \
376 } while (0)
377
378 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
379 (tv)->t = DUK_TAG_LIGHTFUNC; \
380 (tv)->v_extra = (flags); \
381 (tv)->v.lightfunc = (duk_c_function) (fp); \
382 } while (0)
383
384 #define DUK_TVAL_SET_STRING(tv,hptr) do { \
385 (tv)->t = DUK_TAG_STRING; \
386 (tv)->v.hstring = (hptr); \
387 } while (0)
388
389 #define DUK_TVAL_SET_OBJECT(tv,hptr) do { \
390 (tv)->t = DUK_TAG_OBJECT; \
391 (tv)->v.hobject = (hptr); \
392 } while (0)
393
394 #define DUK_TVAL_SET_BUFFER(tv,hptr) do { \
395 (tv)->t = DUK_TAG_BUFFER; \
396 (tv)->v.hbuffer = (hptr); \
397 } while (0)
398
399 #define DUK_TVAL_SET_NAN(tv) do { \
400 /* in non-packed representation we don't care about which NaN is used */ \
401 (tv)->t = DUK__TAG_NUMBER; \
402 (tv)->v.d = DUK_DOUBLE_NAN; \
403 } while (0)
404
405 #define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
406
407 /* getters */
408 #define DUK_TVAL_GET_BOOLEAN(tv) ((tv)->v.i)
409 #if defined(DUK_USE_FASTINT)
410 #define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
411 #define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
412 #define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
413 #define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
414 #if 0
415 #define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
416 (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
417 DUK_TVAL_GET_DOUBLE((tv)))
418 #define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
419 #else
420 /* This seems reasonable overall. */
421 #define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
422 duk_tval_get_number_unpacked_fastint((tv)) : \
423 DUK_TVAL_GET_DOUBLE((tv)))
424 #endif
425 #else
426 #define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
427 #define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
428 #endif /* DUK_USE_FASTINT */
429 #define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
430 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
431 (out_flags) = (duk_uint32_t) (tv)->v_extra; \
432 (out_fp) = (tv)->v.lightfunc; \
433 } while (0)
434 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
435 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_uint32_t) ((tv)->v_extra))
436 #define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring)
437 #define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject)
438 #define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer)
439 #define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr)
440
441 /* decoding */
442 #define DUK_TVAL_GET_TAG(tv) ((tv)->t)
443 #define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED)
444 #define DUK_TVAL_IS_UNUSED(tv) ((tv)->t == DUK_TAG_UNUSED)
445 #define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL)
446 #define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN)
447 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
448 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
449 #if defined(DUK_USE_FASTINT)
450 #define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK__TAG_NUMBER)
451 #define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
452 #define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER || \
453 (tv)->t == DUK_TAG_FASTINT)
454 #else
455 #define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER)
456 #define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
457 #endif /* DUK_USE_FASTINT */
458 #define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
459 #define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
460 #define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
461 #define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
462 #define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
463
464 /* This is performance critical because it's needed for every DECREF.
465 * Take advantage of the fact that the first heap allocated tag is 8,
466 * so that bit 3 is set for all heap allocated tags (and never set for
467 * non-heap-allocated tags).
468 */
469 #if 0
470 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
471 #endif
472 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
473
474 #if defined(DUK_USE_FASTINT)
475 #if 0
476 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
477 #endif
478 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
479 #endif
480
481 #endif /* DUK_USE_PACKED_TVAL */
482
483 /*
484 * Convenience (independent of representation)
485 */
486
487 #define DUK_TVAL_SET_BOOLEAN_TRUE(v) DUK_TVAL_SET_BOOLEAN(v, 1)
488 #define DUK_TVAL_SET_BOOLEAN_FALSE(v) DUK_TVAL_SET_BOOLEAN(v, 0)
489
490 /* Lightfunc flags packing and unpacking. */
491 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss## */
492 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
493 ((((duk_int32_t) (lf_flags)) << 16) >> 24)
494 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
495 (((lf_flags) >> 4) & 0x0f)
496 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
497 ((lf_flags) & 0x0f)
498 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
499 (((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
500
501 #define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
502 #define DUK_LFUNC_NARGS_MIN 0x00
503 #define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
504 #define DUK_LFUNC_LENGTH_MIN 0x00
505 #define DUK_LFUNC_LENGTH_MAX 0x0f
506 #define DUK_LFUNC_MAGIC_MIN (-0x80)
507 #define DUK_LFUNC_MAGIC_MAX 0x7f
508
509 /* fastint constants etc */
510 #if defined(DUK_USE_FASTINT)
511 #define DUK_FASTINT_MIN (-0x800000000000LL)
512 #define DUK_FASTINT_MAX 0x7fffffffffffLL
513 #define DUK_FASTINT_BITS 48
514
515 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
516 #endif
517
518 #endif /* DUK_TVAL_H_INCLUDED */