1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2000-2018. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #ifndef __ERL_TERM_H
22 #define __ERL_TERM_H
23
24 #include "erl_mmap.h"
25
26 void erts_term_init(void);
27
28 typedef UWord Wterm; /* Full word terms */
29
30 struct erl_node_; /* Declared in erl_node_tables.h */
31
32 /*
33 * Defining ET_DEBUG to 1 causes all type-specific data access
34 * macros to perform runtime type checking. This is very useful
35 * during development but reduces performance, so ET_DEBUG should
36 * be disabled during benchmarking or release.
37 */
38 /* #define ET_DEBUG 1 */
39 #ifndef ET_DEBUG
40 # ifdef DEBUG
41 # define ET_DEBUG 1
42 # else
43 # define ET_DEBUG 0
44 # endif
45 #endif
46
47 #if ET_DEBUG
48 #define _ET_DECLARE_CHECKED(TF,F,TX) extern TF checked_##F(TX,const char*,unsigned);
49 #define _ET_APPLY(F,X) checked_##F(X,__FILE__,__LINE__)
50 #else
51 #define _ET_DECLARE_CHECKED(TF,F,TX)
52 #define _ET_APPLY(F,X) _unchecked_##F(X)
53 #endif
54
55 #if defined(ARCH_64)
56 # define TAG_PTR_MASK__ 0x7
57 # if !defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION) || defined(DEBUG)
58 # define TAG_LITERAL_PTR 0x4
59 # else
60 # undef TAG_LITERAL_PTR
61 # endif
62 #elif defined(ARCH_32)
63 # define TAG_PTR_MASK__ 0x3
64 # undef TAG_LITERAL_PTR
65 #else
66 # error Not supported arch
67 #endif
68
69
70 #define _TAG_PRIMARY_SIZE 2
71 #define _TAG_PRIMARY_MASK 0x3
72 #define TAG_PRIMARY_HEADER 0x0
73 #define TAG_PRIMARY_LIST 0x1
74 #define TAG_PRIMARY_BOXED 0x2
75 #define TAG_PRIMARY_IMMED1 0x3
76
77 #define primary_tag(x) ((x) & _TAG_PRIMARY_MASK)
78
79 #define _TAG_IMMED1_SIZE 4
80 #define _TAG_IMMED1_MASK 0xF
81 #define _TAG_IMMED1_PID ((0x0 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
82 #define _TAG_IMMED1_PORT ((0x1 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
83 #define _TAG_IMMED1_IMMED2 ((0x2 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
84 #define _TAG_IMMED1_SMALL ((0x3 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
85
86 #define _TAG_IMMED2_SIZE 6
87 #define _TAG_IMMED2_MASK 0x3F
88 #define _TAG_IMMED2_ATOM ((0x0 << _TAG_IMMED1_SIZE) | _TAG_IMMED1_IMMED2)
89 #define _TAG_IMMED2_CATCH ((0x1 << _TAG_IMMED1_SIZE) | _TAG_IMMED1_IMMED2)
90 #define _TAG_IMMED2_NIL ((0x3 << _TAG_IMMED1_SIZE) | _TAG_IMMED1_IMMED2)
91
92 /*
93 * HEADER representation:
94 *
95 * aaaaaaaaaaaaaaaaaaaaaaaaaatttt00 arity:26, tag:4
96 *
97 * HEADER tags:
98 *
99 * 0000 ARITYVAL
100 * 0001 BINARY_AGGREGATE |
101 * 001x BIGNUM with sign bit |
102 * 0100 REF |
103 * 0101 FUN | THINGS
104 * 0110 FLONUM |
105 * 0111 EXPORT |
106 * 1000 REFC_BINARY | |
107 * 1001 HEAP_BINARY | BINARIES |
108 * 1010 SUB_BINARY | |
109 * 1011 Not used; see comment below
110 * 1100 EXTERNAL_PID | |
111 * 1101 EXTERNAL_PORT | EXTERNAL THINGS |
112 * 1110 EXTERNAL_REF | |
113 * 1111 MAP
114 *
115 * COMMENTS:
116 *
117 * - The tag is zero for arityval and non-zero for thing headers.
118 * - A single bit differentiates between positive and negative bignums.
119 * - If more tags are needed, the REF and and EXTERNAL_REF tags could probably
120 * be combined to one tag.
121 *
122 * XXX: globally replace XXX_SUBTAG with TAG_HEADER_XXX
123 */
124 #define ARITYVAL_SUBTAG (0x0 << _TAG_PRIMARY_SIZE) /* TUPLE */
125 #define BIN_MATCHSTATE_SUBTAG (0x1 << _TAG_PRIMARY_SIZE)
126 #define POS_BIG_SUBTAG (0x2 << _TAG_PRIMARY_SIZE) /* BIG: tags 2&3 */
127 #define NEG_BIG_SUBTAG (0x3 << _TAG_PRIMARY_SIZE) /* BIG: tags 2&3 */
128 #define _BIG_SIGN_BIT (0x1 << _TAG_PRIMARY_SIZE)
129 #define REF_SUBTAG (0x4 << _TAG_PRIMARY_SIZE) /* REF */
130 #define FUN_SUBTAG (0x5 << _TAG_PRIMARY_SIZE) /* FUN */
131 #define FLOAT_SUBTAG (0x6 << _TAG_PRIMARY_SIZE) /* FLOAT */
132 #define EXPORT_SUBTAG (0x7 << _TAG_PRIMARY_SIZE) /* FLOAT */
133 #define _BINARY_XXX_MASK (0x3 << _TAG_PRIMARY_SIZE)
134 #define REFC_BINARY_SUBTAG (0x8 << _TAG_PRIMARY_SIZE) /* BINARY */
135 #define HEAP_BINARY_SUBTAG (0x9 << _TAG_PRIMARY_SIZE) /* BINARY */
136 #define SUB_BINARY_SUBTAG (0xA << _TAG_PRIMARY_SIZE) /* BINARY */
137 /* _BINARY_XXX_MASK depends on 0xB being unused */
138 #define EXTERNAL_PID_SUBTAG (0xC << _TAG_PRIMARY_SIZE) /* EXTERNAL_PID */
139 #define EXTERNAL_PORT_SUBTAG (0xD << _TAG_PRIMARY_SIZE) /* EXTERNAL_PORT */
140 #define EXTERNAL_REF_SUBTAG (0xE << _TAG_PRIMARY_SIZE) /* EXTERNAL_REF */
141 #define MAP_SUBTAG (0xF << _TAG_PRIMARY_SIZE) /* MAP */
142
143
144 #define _TAG_HEADER_ARITYVAL (TAG_PRIMARY_HEADER|ARITYVAL_SUBTAG)
145 #define _TAG_HEADER_FUN (TAG_PRIMARY_HEADER|FUN_SUBTAG)
146 #define _TAG_HEADER_POS_BIG (TAG_PRIMARY_HEADER|POS_BIG_SUBTAG)
147 #define _TAG_HEADER_NEG_BIG (TAG_PRIMARY_HEADER|NEG_BIG_SUBTAG)
148 #define _TAG_HEADER_FLOAT (TAG_PRIMARY_HEADER|FLOAT_SUBTAG)
149 #define _TAG_HEADER_EXPORT (TAG_PRIMARY_HEADER|EXPORT_SUBTAG)
150 #define _TAG_HEADER_REF (TAG_PRIMARY_HEADER|REF_SUBTAG)
151 #define _TAG_HEADER_REFC_BIN (TAG_PRIMARY_HEADER|REFC_BINARY_SUBTAG)
152 #define _TAG_HEADER_HEAP_BIN (TAG_PRIMARY_HEADER|HEAP_BINARY_SUBTAG)
153 #define _TAG_HEADER_SUB_BIN (TAG_PRIMARY_HEADER|SUB_BINARY_SUBTAG)
154 #define _TAG_HEADER_EXTERNAL_PID (TAG_PRIMARY_HEADER|EXTERNAL_PID_SUBTAG)
155 #define _TAG_HEADER_EXTERNAL_PORT (TAG_PRIMARY_HEADER|EXTERNAL_PORT_SUBTAG)
156 #define _TAG_HEADER_EXTERNAL_REF (TAG_PRIMARY_HEADER|EXTERNAL_REF_SUBTAG)
157 #define _TAG_HEADER_BIN_MATCHSTATE (TAG_PRIMARY_HEADER|BIN_MATCHSTATE_SUBTAG)
158 #define _TAG_HEADER_MAP (TAG_PRIMARY_HEADER|MAP_SUBTAG)
159
160
161 #define _TAG_HEADER_MASK 0x3F
162 #define _HEADER_SUBTAG_MASK 0x3C /* 4 bits for subtag */
163 #define _HEADER_ARITY_OFFS 6
164
165 #define header_is_transparent(x) \
166 (((x) & (_HEADER_SUBTAG_MASK)) == ARITYVAL_SUBTAG)
167 #define header_is_arityval(x) (((x) & _HEADER_SUBTAG_MASK) == ARITYVAL_SUBTAG)
168 #define header_is_thing(x) (!header_is_transparent((x)))
169 #define header_is_bin_matchstate(x) ((((x) & (_HEADER_SUBTAG_MASK)) == BIN_MATCHSTATE_SUBTAG))
170
171 #define _CPMASK 0x3
172
173 /* immediate object access methods */
174 #define is_immed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_IMMED1)
175 #define is_not_immed(x) (!is_immed((x)))
176 #define IS_CONST(x) is_immed((x))
177 #if TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK
178 #define is_both_immed(x,y) is_immed(((x)&(y)))
179 #else
180 #define is_both_immed(x,y) (is_immed((x)) && is_immed((y)))
181 #endif
182 #define is_not_both_immed(x,y) (!is_both_immed((x),(y)))
183
184
185 /* boxed object access methods */
186
187 #define _is_taggable_pointer(x) (((Uint)(x) & TAG_PTR_MASK__) == 0)
188
189 #define _boxed_precond(x) (is_boxed(x))
190
191 #define _is_aligned(x) (((Uint)(x) & TAG_PTR_MASK__) == 0)
192 #define _unchecked_make_boxed(x) ((Uint)(x) + TAG_PRIMARY_BOXED)
193 _ET_DECLARE_CHECKED(Eterm,make_boxed,const Eterm*)
194 #define make_boxed(x) _ET_APPLY(make_boxed,(x))
195 #if 1
196 #define _is_not_boxed(x) ((x) & (_TAG_PRIMARY_MASK-TAG_PRIMARY_BOXED))
197 #define _unchecked_is_boxed(x) (!_is_not_boxed((x)))
198 _ET_DECLARE_CHECKED(int,is_boxed,Eterm)
199 #define is_boxed(x) _ET_APPLY(is_boxed,(x))
200 #else
201 #define is_boxed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_BOXED)
202 #endif
203 #ifdef TAG_LITERAL_PTR
204 #define _unchecked_boxed_val(x) _unchecked_ptr_val(x)
205 #else
206 #define _unchecked_boxed_val(x) ((Eterm*) ((x) - TAG_PRIMARY_BOXED))
207 #endif
208 _ET_DECLARE_CHECKED(Eterm*,boxed_val,Wterm)
209 #define boxed_val(x) _ET_APPLY(boxed_val,(x))
210
211 /* cons cell ("list") access methods */
212 #define _unchecked_make_list(x) ((Uint)(x) + TAG_PRIMARY_LIST)
213 _ET_DECLARE_CHECKED(Eterm,make_list,const Eterm*)
214 #define make_list(x) _ET_APPLY(make_list,(x))
215 #if 1
216 #define _unchecked_is_not_list(x) ((x) & (_TAG_PRIMARY_MASK-TAG_PRIMARY_LIST))
217 _ET_DECLARE_CHECKED(int,is_not_list,Eterm)
218 #define is_not_list(x) _ET_APPLY(is_not_list,(x))
219 #define is_list(x) (!is_not_list((x)))
220 #else
221 #define is_list(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_LIST)
222 #define is_not_list(x) (!is_list((x)))
223 #endif
224 #define _list_precond(x) (is_list(x))
225 #ifdef TAG_LITERAL_PTR
226 #define _unchecked_list_val(x) _unchecked_ptr_val(x)
227 #else
228 #define _unchecked_list_val(x) ((Eterm*) ((x) - TAG_PRIMARY_LIST))
229 #endif
230 _ET_DECLARE_CHECKED(Eterm*,list_val,Wterm)
231 #define list_val(x) _ET_APPLY(list_val,(x))
232
233 #define CONS(hp, car, cdr) \
234 (CAR(hp)=(car), CDR(hp)=(cdr), make_list(hp))
235
236 #define CAR(x) ((x)[0])
237 #define CDR(x) ((x)[1])
238
239 /* generic tagged pointer (boxed or list) access methods */
240 #define _unchecked_ptr_val(x) ((Eterm*) ((x) & ~((Uint) TAG_PTR_MASK__)))
241 #define ptr_val(x) _unchecked_ptr_val((x)) /*XXX*/
242 #define _unchecked_offset_ptr(x,offs) ((x)+((offs)*sizeof(Eterm)))
243 #define offset_ptr(x,offs) _unchecked_offset_ptr(x,offs) /*XXX*/
244 #define _unchecked_byte_offset_ptr(x,byte_offs) ((x)+(offs))
245 #define byte_offset_ptr(x,offs) _unchecked_byte_offset_ptr(x,offs) /*XXX*/
246
247 #ifdef TAG_LITERAL_PTR
248 #define _unchecked_is_not_literal_ptr(x) (!((x) & TAG_LITERAL_PTR))
249 #define is_not_literal_ptr(x) _unchecked_is_not_literal_ptr((x)) /*XXX*/
250 #define is_literal_ptr(x) (!is_not_literal_ptr((x))) /*XXX*/
251 #endif
252
253
254 /* fixnum ("small") access methods */
255 #if defined(ARCH_64)
256 #define SMALL_BITS (64-4)
257 #define SMALL_DIGITS (17)
258 #else
259 #define SMALL_BITS (28)
260 #define SMALL_DIGITS (8)
261 #endif
262 #define MAX_SMALL ((SWORD_CONSTANT(1) << (SMALL_BITS-1))-1)
263 #define MIN_SMALL (-(SWORD_CONSTANT(1) << (SMALL_BITS-1)))
264 #define make_small(x) (((Uint)(x) << _TAG_IMMED1_SIZE) + _TAG_IMMED1_SMALL)
265 #define is_small(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
266 #define is_not_small(x) (!is_small((x)))
267 #define is_byte(x) (((x) & ((~(Uint)0 << (_TAG_IMMED1_SIZE+8)) + _TAG_IMMED1_MASK)) == _TAG_IMMED1_SMALL)
268 #define is_valid_bit_size(x) (((Sint)(x)) >= 0 && ((x) & 0x7F) == _TAG_IMMED1_SMALL)
269 #define is_not_valid_bit_size(x) (!is_valid_bit_size((x)))
270 #define _unchecked_unsigned_val(x) ((x) >> _TAG_IMMED1_SIZE)
271 _ET_DECLARE_CHECKED(Uint,unsigned_val,Eterm)
272 #define unsigned_val(x) _ET_APPLY(unsigned_val,(x))
273 #define _unchecked_signed_val(x) ((Sint)(x) >> _TAG_IMMED1_SIZE)
274 _ET_DECLARE_CHECKED(Sint,signed_val,Eterm)
275 #define signed_val(x) _ET_APPLY(signed_val,(x))
276
277 #if _TAG_IMMED1_SMALL == 0x0F
278 #define is_both_small(x,y) (((x) & (y) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
279 #elif _TAG_IMMED1_SMALL == 0x00
280 #define is_both_small(x,y) ((((x)|(y)) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
281 #else
282 #define is_both_small(x,y) (is_small(x) && is_small(y))
283 #endif
284
285 /* NIL access methods */
286 #define NIL ((Eterm)(_TAG_IMMED2_NIL))
287 #define is_nil(x) ((x) == NIL)
288 #define is_not_nil(x) ((x) != NIL)
289
290 #define MAX_ATOM_INDEX (~(~((Uint) 0) << (sizeof(Uint)*8 - _TAG_IMMED2_SIZE)))
291
292 /* atom access methods */
293 #define make_atom(x) ((Eterm)(((x) << _TAG_IMMED2_SIZE) + _TAG_IMMED2_ATOM))
294 #define is_atom(x) (((x) & _TAG_IMMED2_MASK) == _TAG_IMMED2_ATOM)
295 #define is_not_atom(x) (!is_atom(x))
296 #define _unchecked_atom_val(x) ((x) >> _TAG_IMMED2_SIZE)
297 _ET_DECLARE_CHECKED(Uint,atom_val,Eterm)
298 #define atom_val(x) _ET_APPLY(atom_val,(x))
299
300 /* header (arityval or thing) access methods */
301 #define _make_header(sz,tag) ((Uint)(((Uint)(sz) << _HEADER_ARITY_OFFS) + (tag)))
302 #define is_header(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_HEADER)
303 #define _unchecked_header_arity(x) \
304 (is_map_header(x) ? MAP_HEADER_ARITY(x) : ((x) >> _HEADER_ARITY_OFFS))
305 _ET_DECLARE_CHECKED(Uint,header_arity,Eterm)
306 #define header_arity(x) _ET_APPLY(header_arity,(x))
307
308 /* arityval access methods */
309 /* Erlang Spec. 4.7.3 defines max arity to 65535
310 * we will however enforce max arity of 16777215 (24 bits)
311 * (checked in bifs and asserted in debug)
312 */
313 #define MAX_ARITYVAL ((((Uint)1) << 24) - 1)
314 #define ERTS_MAX_TUPLE_SIZE MAX_ARITYVAL
315
316 #define make_arityval(sz) (ASSERT((sz) <= MAX_ARITYVAL), \
317 _make_header((sz),_TAG_HEADER_ARITYVAL))
318 #define is_arity_value(x) (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_ARITYVAL)
319 #define is_sane_arity_value(x) ((((x) & _TAG_HEADER_MASK) == _TAG_HEADER_ARITYVAL) && \
320 (((x) >> _HEADER_ARITY_OFFS) <= MAX_ARITYVAL))
321 #define is_not_arity_value(x) (!is_arity_value((x)))
322 #define _unchecked_arityval(x) _unchecked_header_arity((x))
323 _ET_DECLARE_CHECKED(Uint,arityval,Eterm)
324 #define arityval(x) _ET_APPLY(arityval,(x))
325
326 /* thing access methods */
327 #define is_thing(x) (is_header((x)) && header_is_thing((x)))
328 #define is_thing_ptr(t) (is_thing((t)->header))
329 #define _unchecked_thing_arityval(x) _unchecked_header_arity((x))
330 _ET_DECLARE_CHECKED(Uint,thing_arityval,Eterm)
331 #define thing_arityval(x) _ET_APPLY(thing_arityval,(x))
332 #define _unchecked_thing_subtag(x) ((x) & _HEADER_SUBTAG_MASK)
333 _ET_DECLARE_CHECKED(Uint,thing_subtag,Eterm)
334 #define thing_subtag(x) _ET_APPLY(thing_subtag,(x))
335
336 /*
337 * Magic non-value object.
338 * Used as function return error and "absent value" indicator
339 * in the original runtime system. The new runtime system also
340 * uses it as forwarding marker for CONS cells.
341 *
342 * This value is 0 in the original runtime system, which unfortunately
343 * promotes sloppy programming practices. It also prevents some useful
344 * tag assignment schemes, e.g. using a 2-bit tag 00 for FIXNUM.
345 *
346 * To help find code which makes unwarranted assumptions about zero,
347 * we now use a non-zero bit-pattern in debug mode.
348 *
349 * In order to be able to differentiata against values, the non-value
350 * needs to be tagged as a header of some sort.
351 */
352 #if ET_DEBUG
353 #define THE_NON_VALUE _make_header(0,_TAG_HEADER_FLOAT)
354 #else
355 #define THE_NON_VALUE (TAG_PRIMARY_HEADER)
356 #endif
357
358 #define is_non_value(x) ((x) == THE_NON_VALUE)
359 #define is_value(x) ((x) != THE_NON_VALUE)
360
361 /* binary object access methods */
362 #define is_binary_header(x) \
363 ((((x) & (_TAG_HEADER_MASK)) == _TAG_HEADER_REFC_BIN) || \
364 (((x) & (_TAG_HEADER_MASK)) == _TAG_HEADER_HEAP_BIN) || \
365 (((x) & (_TAG_HEADER_MASK)) == _TAG_HEADER_SUB_BIN))
366
367 #define make_binary(x) make_boxed((Eterm*)(x))
368 #define is_binary(x) (is_boxed((x)) && is_binary_header(*boxed_val((x))))
369 #define is_not_binary(x) (!is_binary((x)))
370 #define _unchecked_binary_val(x) _unchecked_boxed_val((x))
371 _ET_DECLARE_CHECKED(Eterm*,binary_val,Wterm)
372 #define binary_val(x) _ET_APPLY(binary_val,(x))
373
374 /* process binaries stuff (special case of binaries) */
375 #define HEADER_PROC_BIN _make_header(PROC_BIN_SIZE-1,_TAG_HEADER_REFC_BIN)
376
377 /* fun & export objects */
378 #define is_any_fun(x) (is_fun((x)) || is_export((x)))
379 #define is_not_any_fun(x) (!is_any_fun((x)))
380
381 /* fun objects */
382 #define HEADER_FUN _make_header(ERL_FUN_SIZE-2,_TAG_HEADER_FUN)
383 #define is_fun_header(x) ((x) == HEADER_FUN)
384 #define make_fun(x) make_boxed((Eterm*)(x))
385 #define is_fun(x) (is_boxed((x)) && is_fun_header(*boxed_val((x))))
386 #define is_not_fun(x) (!is_fun((x)))
387 #define _unchecked_fun_val(x) _unchecked_boxed_val((x))
388 _ET_DECLARE_CHECKED(Eterm*,fun_val,Wterm)
389 #define fun_val(x) _ET_APPLY(fun_val,(x))
390
391 /* export access methods */
392 #define make_export(x) make_boxed((x))
393 #define is_export(x) (is_boxed((x)) && is_export_header(*boxed_val((x))))
394 #define is_not_export(x) (!is_export((x)))
395 #define _unchecked_export_val(x) _unchecked_boxed_val(x)
396 _ET_DECLARE_CHECKED(Eterm*,export_val,Wterm)
397 #define export_val(x) _ET_APPLY(export_val,(x))
398 #define is_export_header(x) ((x) == HEADER_EXPORT)
399 #define HEADER_EXPORT _make_header(1,_TAG_HEADER_EXPORT)
400
401 /* bignum access methods */
402 #define make_pos_bignum_header(sz) _make_header((sz),_TAG_HEADER_POS_BIG)
403 #define make_neg_bignum_header(sz) _make_header((sz),_TAG_HEADER_NEG_BIG)
404 #define _is_bignum_header(x) (((x) & (_TAG_HEADER_MASK-_BIG_SIGN_BIT)) == _TAG_HEADER_POS_BIG)
405 #define _unchecked_bignum_header_is_neg(x) ((x) & _BIG_SIGN_BIT)
406 _ET_DECLARE_CHECKED(int,bignum_header_is_neg,Eterm)
407 #define bignum_header_is_neg(x) _ET_APPLY(bignum_header_is_neg,(x))
408 #define _unchecked_bignum_header_neg(x) ((x) | _BIG_SIGN_BIT)
409 _ET_DECLARE_CHECKED(Eterm,bignum_header_neg,Eterm)
410 #define bignum_header_neg(x) _ET_APPLY(bignum_header_neg,(x))
411 #define _unchecked_bignum_header_arity(x) _unchecked_header_arity((x))
412 _ET_DECLARE_CHECKED(Uint,bignum_header_arity,Eterm)
413 #define bignum_header_arity(x) _ET_APPLY(bignum_header_arity,(x))
414 #define BIG_ARITY_MAX ((1 << 19)-1)
415 #define make_big(x) make_boxed((x))
416 #define is_big(x) (is_boxed((x)) && _is_bignum_header(*boxed_val((x))))
417 #define is_not_big(x) (!is_big((x)))
418 #define _unchecked_big_val(x) _unchecked_boxed_val((x))
419 _ET_DECLARE_CHECKED(Eterm*,big_val,Wterm)
420 #define big_val(x) _ET_APPLY(big_val,(x))
421
422 /* flonum ("float") access methods */
423 #if defined(ARCH_64)
424 #define HEADER_FLONUM _make_header(1,_TAG_HEADER_FLOAT)
425 #else
426 #define HEADER_FLONUM _make_header(2,_TAG_HEADER_FLOAT)
427 #endif
428 #define make_float(x) make_boxed((x))
429 #define is_float(x) (is_boxed((x)) && *boxed_val((x)) == HEADER_FLONUM)
430 #define is_not_float(x) (!is_float(x))
431 #define _unchecked_float_val(x) _unchecked_boxed_val((x))
432 _ET_DECLARE_CHECKED(Eterm*,float_val,Wterm)
433 #define float_val(x) _ET_APPLY(float_val,(x))
434
435 /* Float definition for byte and word access */
436 typedef double ieee754_8;
437
438 typedef union float_def
439 {
440 ieee754_8 fd;
441 byte fb[sizeof(ieee754_8)];
442 Uint16 fs[sizeof(ieee754_8) / sizeof(Uint16)];
443 Uint32 fw[sizeof(ieee754_8) / sizeof(Uint32)];
444 #if defined(ARCH_64)
445 Uint fdw;
446 #endif
447 } FloatDef;
448
449 #if defined(ARCH_64)
450
451 #define FLOAT_VAL_GET_DOUBLE(fval, f) (f).fdw = *((fval)+1)
452
453 #define PUT_DOUBLE(f, x) *(x) = HEADER_FLONUM, \
454 *((x)+1) = (f).fdw
455 #define GET_DOUBLE_DATA(p, f) (f).fdw = *((Uint *) (p))
456 #define PUT_DOUBLE_DATA(f,p) *((Uint *) (p)) = (f).fdw
457 #else
458 #define FLOAT_VAL_GET_DOUBLE(fval, f) (f).fw[0] = *((fval)+1), \
459 (f).fw[1] = *((fval)+2)
460
461 #define PUT_DOUBLE(f, x) *(x) = HEADER_FLONUM, \
462 *((x)+1) = (f).fw[0], \
463 *((x)+2) = (f).fw[1]
464 #define GET_DOUBLE_DATA(p, f) (f).fw[0] = *((Uint *) (p)),\
465 (f).fw[1] = *(((Uint *) (p))+1)
466 #define PUT_DOUBLE_DATA(f,p) *((Uint *) (p)) = (f).fw[0],\
467 *(((Uint *) (p))+1) = (f).fw[1]
468 #endif
469
470 #define GET_DOUBLE(x, f) FLOAT_VAL_GET_DOUBLE(float_val(x), f)
471
472 #define DOUBLE_DATA_WORDS (sizeof(ieee754_8)/sizeof(Eterm))
473 #define FLOAT_SIZE_OBJECT (DOUBLE_DATA_WORDS+1)
474
475 /* tuple access methods */
476 #define make_tuple(x) make_boxed((x))
477 #define is_tuple(x) (is_boxed((x)) && is_arity_value(*boxed_val((x))))
478 #define is_not_tuple(x) (!is_tuple((x)))
479 #define is_tuple_arity(x, a) \
480 (is_boxed((x)) && *boxed_val((x)) == make_arityval((a)))
481 #define is_not_tuple_arity(x, a) (!is_tuple_arity((x),(a)))
482 #define _unchecked_tuple_val(x) _unchecked_boxed_val(x)
483 _ET_DECLARE_CHECKED(Eterm*,tuple_val,Wterm)
484 #define tuple_val(x) _ET_APPLY(tuple_val,(x))
485
486 #define TUPLE0(t) \
487 ((t)[0] = make_arityval(0), \
488 make_tuple(t))
489 #define TUPLE1(t,e1) \
490 ((t)[0] = make_arityval(1), \
491 (t)[1] = (e1), \
492 make_tuple(t))
493 #define TUPLE2(t,e1,e2) \
494 ((t)[0] = make_arityval(2), \
495 (t)[1] = (e1), \
496 (t)[2] = (e2), \
497 make_tuple(t))
498 #define TUPLE3(t,e1,e2,e3) \
499 ((t)[0] = make_arityval(3), \
500 (t)[1] = (e1), \
501 (t)[2] = (e2), \
502 (t)[3] = (e3), \
503 make_tuple(t))
504 #define TUPLE4(t,e1,e2,e3,e4) \
505 ((t)[0] = make_arityval(4), \
506 (t)[1] = (e1), \
507 (t)[2] = (e2), \
508 (t)[3] = (e3), \
509 (t)[4] = (e4), \
510 make_tuple(t))
511 #define TUPLE5(t,e1,e2,e3,e4,e5) \
512 ((t)[0] = make_arityval(5), \
513 (t)[1] = (e1), \
514 (t)[2] = (e2), \
515 (t)[3] = (e3), \
516 (t)[4] = (e4), \
517 (t)[5] = (e5), \
518 make_tuple(t))
519 #define TUPLE6(t,e1,e2,e3,e4,e5,e6) \
520 ((t)[0] = make_arityval(6), \
521 (t)[1] = (e1), \
522 (t)[2] = (e2), \
523 (t)[3] = (e3), \
524 (t)[4] = (e4), \
525 (t)[5] = (e5), \
526 (t)[6] = (e6), \
527 make_tuple(t))
528
529 #define TUPLE7(t,e1,e2,e3,e4,e5,e6,e7) \
530 ((t)[0] = make_arityval(7), \
531 (t)[1] = (e1), \
532 (t)[2] = (e2), \
533 (t)[3] = (e3), \
534 (t)[4] = (e4), \
535 (t)[5] = (e5), \
536 (t)[6] = (e6), \
537 (t)[7] = (e7), \
538 make_tuple(t))
539
540 #define TUPLE8(t,e1,e2,e3,e4,e5,e6,e7,e8) \
541 ((t)[0] = make_arityval(8), \
542 (t)[1] = (e1), \
543 (t)[2] = (e2), \
544 (t)[3] = (e3), \
545 (t)[4] = (e4), \
546 (t)[5] = (e5), \
547 (t)[6] = (e6), \
548 (t)[7] = (e7), \
549 (t)[8] = (e8), \
550 make_tuple(t))
551
552 /* This macro get Size bits starting at low order position Pos
553 and adjusts the bits to the right
554 bits are numbered from 0 - (sizeof(Uint)*8-1) */
555
556 #define _GETBITS(X,Pos,Size) (((X) >> (Pos)) & ~(~((Uint) 0) << (Size)))
557
558
559 /*
560 * PID layout (internal pids):
561 *
562 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
563 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
564 * | | | | |
565 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
566 * |n n n n n n n n n n n n n n n n n n n n n n n n n n n n|0 0|1 1|
567 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
568 *
569 * n : number
570 *
571 * Very old pid layout:
572 *
573 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
574 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
575 * | | | | |
576 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
577 * |s s s|n n n n n n n n n n n n n n n|N N N N N N N N|c c|0 0|1 1|
578 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
579 *
580 * s : serial
581 * n : number
582 * c : creation
583 * N : node number
584 *
585 */
586
587 #define _PID_SER_SIZE (_PID_DATA_SIZE - _PID_NUM_SIZE)
588 #define _PID_NUM_SIZE 15
589
590 #define _PID_DATA_SIZE 28
591 #define _PID_DATA_SHIFT (_TAG_IMMED1_SIZE)
592
593 #define _GET_PID_DATA(X) _GETBITS((X),_PID_DATA_SHIFT,_PID_DATA_SIZE)
594 #define _GET_PID_NUM(X) _GETBITS((X),0,_PID_NUM_SIZE)
595 #define _GET_PID_SER(X) _GETBITS((X),_PID_NUM_SIZE,_PID_SER_SIZE)
596
597 #define make_pid_data(Ser, Num) \
598 ((Uint) ((Ser) << _PID_NUM_SIZE | (Num)))
599
600 #define is_internal_pid(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_PID)
601 #define is_not_internal_pid(x) (!is_internal_pid((x)))
602
603 #define _unchecked_internal_pid_node(x) erts_this_node
604 _ET_DECLARE_CHECKED(struct erl_node_*,internal_pid_node,Eterm)
605 #define internal_pid_node(x) _ET_APPLY(internal_pid_node,(x))
606
607 #define internal_pid_data_words(x) (1)
608
609 /*
610 * PORT layout (internal ports):
611 *
612 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
613 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
614 * | | | | |
615 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616 * |n n n n n n n n n n n n n n n n n n n n n n n n n n n n|0 1|1 1|
617 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
618 *
619 * n : number
620 *
621 * Old port layout:
622 *
623 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
624 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
625 * | | | | |
626 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
627 * |N N N N N N N N|n n n n n n n n n n n n n n n n n n|c c|0 1|1 1|
628 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
629 *
630 * s : serial
631 * n : number
632 * c : creation
633 * N : node number
634 *
635 */
636 #define _PORT_NUM_SIZE _PORT_DATA_SIZE
637
638 #define _PORT_DATA_SIZE 28
639 #define _PORT_DATA_SHIFT (_TAG_IMMED1_SIZE)
640
641 #define _GET_PORT_DATA(X) _GETBITS((X),_PORT_DATA_SHIFT,_PORT_DATA_SIZE)
642 #define _GET_PORT_NUM(X) _GETBITS((X), 0, _PORT_NUM_SIZE)
643
644
645 #define is_internal_port(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_PORT)
646 #define is_not_internal_port(x) (!is_internal_port(x))
647
648 #define _unchecked_internal_port_node(x) erts_this_node
649 _ET_DECLARE_CHECKED(struct erl_node_*,internal_port_node,Eterm)
650 #define internal_port_node(x) _ET_APPLY(internal_port_node,(x))
651
652 #define internal_port_data_words(x) (1)
653 /*
654 * Ref layout (internal references):
655 *
656 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
657 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
658 * | | | | |
659 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
660 * |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1|0 1 0 0|0 0| Thing
661 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
662 * |0 0 0 0 0 0 0 0 0 0 0 0 0 0|r r r r r r r r r r r r r r r r r r| Data 0
663 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
664 * |r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r| Data 1
665 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
666 * |r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r| Data 2
667 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
668 *
669 *
670 * r : reference number
671 * c : creation
672 *
673 *
674 * Old "heap ref" layout:
675 *
676 *
677 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
678 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
679 * | | | | |
680 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681 * |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1|0 1 0 0|0 0| Thing
682 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
683 * |N N N N N N N N|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|c c|0 1 1 1| Head
684 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
685 * |0 0 0 0 0 0 0 0 0 0 0 0 0 0|r r r r r r r r r r r r r r r r r r| Word 0
686 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
687 * |r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r| Word 1
688 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
689 * |r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r| Word 2
690 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
691 *
692 * r : reference number
693 * c : creation
694 * N : node index
695 *
696 * Old "one-word ref" layout:
697 *
698 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
699 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
700 * | | | | |
701 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
702 * |N N N N N N N N|r r r r r r r r r r r r r r r r r r|c c|T T T T|
703 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
704 *
705 * r : reference number
706 * c : creation
707 * N : node index
708 *
709 */
710 #define _REF_NUM_SIZE 18
711
712 /* Old maximum number of references in the system */
713 #define MAX_REFERENCE (1 << _REF_NUM_SIZE)
714 #define REF_MASK (~(~((Uint)0) << _REF_NUM_SIZE))
715 #define ERTS_REF_NUMBERS 3
716 #if defined(ARCH_64)
717 #define ERTS_PID_REF_NUMBERS (ERTS_REF_NUMBERS + 2)
718 #else
719 #define ERTS_PID_REF_NUMBERS (ERTS_REF_NUMBERS + 1)
720 #endif
721 #define ERTS_MAX_INTERNAL_REF_NUMBERS ERTS_PID_REF_NUMBERS
722 #define ERTS_MAX_REF_NUMBERS 5
723
724 #ifndef ERTS_ENDIANNESS
725 # error ERTS_ENDIANNESS not defined...
726 #endif
727
728 #if ERTS_REF_NUMBERS != 3
729 # error "A new reference layout for 64-bit needs to be implemented..."
730 #endif
731
732 struct magic_binary;
733
734 #if defined(ARCH_64)
735
736 # define ERTS_ORDINARY_REF_MARKER (~((Uint32) 0))
737
738 typedef struct {
739 Eterm header;
740 #if ERTS_ENDIANNESS <= 0
741 Uint32 marker;
742 #endif
743 Uint32 num[ERTS_REF_NUMBERS];
744 #if ERTS_ENDIANNESS > 0
745 Uint32 marker;
746 #endif
747 } ErtsORefThing;
748
749 typedef struct {
750 Eterm header;
751 #if ERTS_ENDIANNESS <= 0
752 Uint32 marker;
753 #endif
754 Uint32 num[ERTS_PID_REF_NUMBERS];
755 #if ERTS_ENDIANNESS > 0
756 Uint32 marker;
757 #endif
758 } ErtsPRefThing;
759
760 typedef struct {
761 Eterm header;
762 struct magic_binary *mb;
763 struct erl_off_heap_header* next;
764 #if !ERTS_ENDIANNESS
765 Uint32 num[ERTS_REF_NUMBERS];
766 Uint32 marker;
767 #endif
768 } ErtsMRefThing;
769
770 /*
771 * Ordinary ref layout on a 64-bit little endian machine:
772 *
773 * 63 31 0
774 * +--------------+--------------+
775 * | Thing word |
776 * +--------------+--------------+
777 * | Data 0 | 0xffffffff |
778 * +--------------+--------------+
779 * | Data 2 | Data 1 |
780 * +--------------+--------------+
781 *
782 * Ordinary ref layout on a 64-bit big endian machine:
783 *
784 * 63 31 0
785 * +--------------+--------------+
786 * | Thing word |
787 * +--------------+--------------+
788 * | Data 0 | Data 1 |
789 * +--------------+--------------+
790 * | Data 2 | 0xffffffff |
791 * +--------------+--------------+
792 *
793 * Magic Ref layout on a 64-bit machine:
794 *
795 * 63 31 0
796 * +--------------+--------------+
797 * | Thing word |
798 * +--------------+--------------+
799 * | Magic Binary Pointer |
800 * +--------------+--------------+
801 * | Next Off Heap Pointer |
802 * +--------------+--------------+
803 *
804 * Both pointers in the magic ref are 64-bit aligned. That is,
805 * least significant bits are zero. The marker 32-bit word of
806 * an ordinary ref is placed over the least significant bits
807 * of one of the pointers. That is, we can distinguish between
808 * magic and ordinary ref by looking at the marker field.
809 * Pid refs are larger than ordinary and magic refs, so we
810 * can distinguish pid refs from the other by the header word.
811 */
812
813 #define write_ref_thing(Hp, R0, R1, R2) \
814 do { \
815 ((ErtsORefThing *) (Hp))->header = ERTS_REF_THING_HEADER; \
816 ((ErtsORefThing *) (Hp))->marker = ERTS_ORDINARY_REF_MARKER; \
817 ((ErtsORefThing *) (Hp))->num[0] = (R0); \
818 ((ErtsORefThing *) (Hp))->num[1] = (R1); \
819 ((ErtsORefThing *) (Hp))->num[2] = (R2); \
820 } while (0)
821
822 #if ERTS_ENDIANNESS
823 /* Known big or little endian */
824
825 #define write_magic_ref_thing(Hp, Ohp, Binp) \
826 do { \
827 ((ErtsMRefThing *) (Hp))->header = ERTS_REF_THING_HEADER; \
828 ((ErtsMRefThing *) (Hp))->mb = (Binp); \
829 ((ErtsMRefThing *) (Hp))->next = (Ohp)->first; \
830 (Ohp)->first = (struct erl_off_heap_header*) (Hp); \
831 ASSERT(erts_is_ref_numbers_magic((Binp)->refn)); \
832 } while (0)
833
834 #else /* !ERTS_ENDIANNESS */
835
836 #define write_magic_ref_thing(Hp, Ohp, Binp) \
837 do { \
838 ((ErtsMRefThing *) (Hp))->header = ERTS_MAGIC_REF_THING_HEADER; \
839 ((ErtsMRefThing *) (Hp))->mb = (Binp); \
840 ((ErtsMRefThing *) (Hp))->next = (Ohp)->first; \
841 (Ohp)->first = (struct erl_off_heap_header*) (Hp); \
842 ((ErtsMRefThing *) (Hp))->marker = 0; \
843 ((ErtsMRefThing *) (Hp))->num[0] = (Binp)->refn[0]; \
844 ((ErtsMRefThing *) (Hp))->num[1] = (Binp)->refn[1]; \
845 ((ErtsMRefThing *) (Hp))->num[2] = (Binp)->refn[2]; \
846 ASSERT(erts_is_ref_numbers_magic((Binp)->refn)); \
847 } while (0)
848
849 #endif /* !ERTS_ENDIANNESS */
850
851 #define write_pid_ref_thing(Hp, R0, R1, R2, PID) \
852 do { \
853 ((ErtsPRefThing *) (Hp))->header = ERTS_PID_REF_THING_HEADER; \
854 ((ErtsPRefThing *) (Hp))->marker = ERTS_ORDINARY_REF_MARKER; \
855 ((ErtsPRefThing *) (Hp))->num[0] = (R0); \
856 ((ErtsPRefThing *) (Hp))->num[1] = (R1); \
857 ((ErtsPRefThing *) (Hp))->num[2] = (R2); \
858 ((ErtsPRefThing *) (Hp))->num[3] = (Uint32) ((PID) & 0xffffffff); \
859 ((ErtsPRefThing *) (Hp))->num[4] = (Uint32) (((PID) >> 32) \
860 & 0xffffffff); \
861 } while (0)
862
863 #define pid_ref_thing_get_pid(Hp) \
864 (ASSERT(is_pid_ref_thing((Hp))), \
865 (((Eterm) ((ErtsPRefThing *) (Hp))->num[3]) \
866 | ((((Eterm) ((ErtsPRefThing *) (Hp))->num[4]) << 32))))
867
868 #else /* ARCH_32 */
869
870 typedef struct {
871 Eterm header;
872 Uint32 num[ERTS_REF_NUMBERS];
873 } ErtsORefThing;
874
875 typedef struct {
876 Eterm header;
877 Uint32 num[ERTS_PID_REF_NUMBERS];
878 } ErtsPRefThing;
879
880 typedef struct {
881 Eterm header;
882 struct magic_binary *mb;
883 struct erl_off_heap_header* next;
884 } ErtsMRefThing;
885
886
887 #define write_ref_thing(Hp, R0, R1, R2) \
888 do { \
889 ((ErtsORefThing *) (Hp))->header = ERTS_REF_THING_HEADER; \
890 ((ErtsORefThing *) (Hp))->num[0] = (R0); \
891 ((ErtsORefThing *) (Hp))->num[1] = (R1); \
892 ((ErtsORefThing *) (Hp))->num[2] = (R2); \
893 } while (0)
894
895 #define write_magic_ref_thing(Hp, Ohp, Binp) \
896 do { \
897 ((ErtsMRefThing *) (Hp))->header = ERTS_MAGIC_REF_THING_HEADER; \
898 ((ErtsMRefThing *) (Hp))->mb = (Binp); \
899 ((ErtsMRefThing *) (Hp))->next = (Ohp)->first; \
900 (Ohp)->first = (struct erl_off_heap_header*) (Hp); \
901 ASSERT(erts_is_ref_numbers_magic((Binp)->refn)); \
902 } while (0)
903
904 #define write_pid_ref_thing(Hp, R0, R1, R2, PID) \
905 do { \
906 ((ErtsPRefThing *) (Hp))->header = ERTS_PID_REF_THING_HEADER; \
907 ((ErtsPRefThing *) (Hp))->num[0] = (R0); \
908 ((ErtsPRefThing *) (Hp))->num[1] = (R1); \
909 ((ErtsPRefThing *) (Hp))->num[2] = (R2); \
910 ((ErtsPRefThing *) (Hp))->num[3] = (Uint32) (PID); \
911 } while (0)
912
913 #define pid_ref_thing_get_pid(Hp) \
914 (ASSERT(is_pid_ref_thing((Hp))), \
915 ((Eterm) ((ErtsPRefThing *) (Hp))->num[3]))
916
917
918 #endif /* ARCH_32 */
919
920 typedef union {
921 ErtsMRefThing m;
922 ErtsORefThing o;
923 ErtsPRefThing p;
924 } ErtsRefThing;
925
926 /* for copy sharing */
927 #define BOXED_VISITED_MASK ((Eterm) 3)
928 #define BOXED_VISITED ((Eterm) 1)
929 #define BOXED_SHARED_UNPROCESSED ((Eterm) 2)
930 #define BOXED_SHARED_PROCESSED ((Eterm) 3)
931
932 #define ERTS_REF_THING_SIZE (sizeof(ErtsORefThing)/sizeof(Uint))
933 #define ERTS_PID_REF_THING_SIZE (sizeof(ErtsPRefThing)/sizeof(Uint))
934 #define ERTS_MAGIC_REF_THING_SIZE (sizeof(ErtsMRefThing)/sizeof(Uint))
935 #define ERTS_MAX_INTERNAL_REF_SIZE (sizeof(ErtsRefThing)/sizeof(Uint))
936
937 #define make_ref_thing_header(Words) \
938 _make_header((Words)-1,_TAG_HEADER_REF)
939
940 #define ERTS_REF_THING_HEADER _make_header(ERTS_REF_THING_SIZE-1,_TAG_HEADER_REF)
941 #define ERTS_PID_REF_THING_HEADER _make_header(ERTS_PID_REF_THING_SIZE-1,_TAG_HEADER_REF)
942
943 # define is_ref_thing_header(x) \
944 (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_REF)
945
946 #if defined(ARCH_64) && ERTS_ENDIANNESS
947 /* Ordinary and magic refs of same size, but pid ref larger */
948
949 # undef ERTS_MAGIC_REF_THING_HEADER
950
951 #define is_pid_ref_thing(x) \
952 (*((Eterm *)(x)) == ERTS_PID_REF_THING_HEADER)
953
954 #define is_ordinary_ref_thing(x) \
955 ((*((Eterm *)(x)) == ERTS_REF_THING_HEADER) \
956 & (((ErtsRefThing *) (x))->o.marker == ERTS_ORDINARY_REF_MARKER))
957
958 /* the _with_hdr variant usable when header word may be broken (copy_shared) */
959 #define is_magic_ref_thing_with_hdr(PTR,HDR) \
960 (((HDR) == ERTS_REF_THING_HEADER) \
961 & (((ErtsRefThing *) (PTR))->o.marker != ERTS_ORDINARY_REF_MARKER))
962
963 #else /* Ordinary and magic references of different sizes... */
964
965 # define ERTS_MAGIC_REF_THING_HEADER \
966 _make_header(ERTS_MAGIC_REF_THING_SIZE-1,_TAG_HEADER_REF)
967
968 #define is_ordinary_ref_thing(x) \
969 (*((Eterm *)(x)) == ERTS_REF_THING_HEADER)
970
971 #define is_pid_ref_thing(x) \
972 (*((Eterm *)(x)) == ERTS_PID_REF_THING_HEADER)
973
974 #define is_magic_ref_thing_with_hdr(PTR,HDR) \
975 ((HDR) == ERTS_MAGIC_REF_THING_HEADER)
976
977 #endif
978
979 #define is_magic_ref_thing(PTR) \
980 is_magic_ref_thing_with_hdr(PTR, *(Eterm *)(PTR))
981
982 #define is_internal_magic_ref(x) \
983 (_unchecked_is_boxed((x)) && is_magic_ref_thing(boxed_val((x))))
984
985 #define is_internal_non_magic_ref(x) \
986 (is_internal_ordinary_ref((x)) || is_internal_pid_ref((x)))
987
988 #define is_internal_ordinary_ref(x) \
989 (_unchecked_is_boxed((x)) && is_ordinary_ref_thing(boxed_val((x))))
990
991 #define is_internal_pid_ref(x) \
992 (_unchecked_is_boxed((x)) && is_pid_ref_thing(boxed_val((x))))
993
994 #define make_internal_ref(x) make_boxed((Eterm*)(x))
995
996 #define _unchecked_ordinary_ref_thing_ptr(x) \
997 ((ErtsORefThing*) _unchecked_internal_ref_val(x))
998 #define ordinary_ref_thing_ptr(x) \
999 ((ErtsORefThing*) internal_ref_val(x))
1000
1001 #define _unchecked_magic_ref_thing_ptr(x) \
1002 ((ErtsMRefThing*) _unchecked_internal_ref_val(x))
1003 #define magic_ref_thing_ptr(x) \
1004 ((ErtsMRefThing*) internal_ref_val(x))
1005
1006 #define is_internal_ref(x) \
1007 (_unchecked_is_boxed((x)) && is_ref_thing_header(*boxed_val((x))))
1008
1009 #define is_not_internal_ref(x) \
1010 (!is_internal_ref((x)))
1011
1012 #define _unchecked_internal_ref_val(x) _unchecked_boxed_val((x))
1013 _ET_DECLARE_CHECKED(Eterm*,internal_ref_val,Wterm)
1014 #define internal_ref_val(x) _ET_APPLY(internal_ref_val,(x))
1015
1016 #define internal_non_magic_ref_thing_numbers(rt) (((ErtsORefThing *)(rt))->num)
1017 #define _unchecked_internal_non_magic_ref_numbers(x) (internal_non_magic_ref_thing_numbers(_unchecked_ordinary_ref_thing_ptr(x)))
1018 _ET_DECLARE_CHECKED(Uint32*,internal_non_magic_ref_numbers,Wterm)
1019 #define internal_non_magic_ref_numbers(x) _ET_APPLY(internal_non_magic_ref_numbers,(x))
1020
1021 #define internal_ordinary_ref_numbers(x) internal_non_magic_ref_numbers((x))
1022 #define internal_pid_ref_numbers(x) internal_non_magic_ref_numbers((x))
1023
1024 #if defined(ARCH_64) && !ERTS_ENDIANNESS
1025 #define internal_magic_thing_ref_numbers(mrt) (((ErtsMRefThing *)(mrt))->num)
1026 #else
1027 #define internal_magic_thing_ref_numbers(mrt) (((ErtsMRefThing *)(mrt))->mb->refn)
1028 #endif
1029
1030 #define _unchecked_internal_magic_ref_numbers(x) (internal_magic_thing_ref_numbers(_unchecked_magic_ref_thing_ptr(x)))
1031 _ET_DECLARE_CHECKED(Uint32*,internal_magic_ref_numbers,Wterm)
1032 #define internal_magic_ref_numbers(x) _ET_APPLY(internal_magic_ref_numbers,(x))
1033
1034
1035 #define _unchecked_internal_ref_node(x) erts_this_node
1036 _ET_DECLARE_CHECKED(struct erl_node_*,internal_ref_node,Eterm)
1037 #define internal_ref_node(x) _ET_APPLY(internal_ref_node,(x))
1038
1039 /*
1040 *
1041 * External thing layout (external pids, ports, and refs):
1042 *
1043 * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
1044 * |1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
1045 * | | | | |
1046 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1047 * |A A A A A A A A A A A A A A A A A A A A A A A A A A|t t t t|0 0| Thing
1048 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1049 * |E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E| ErlNode
1050 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1051 * |N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N| Next
1052 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1053 * |X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X| Data 0
1054 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1055 * . . .
1056 * . . .
1057 * . . .
1058 *
1059 * A : Arity
1060 * t : External pid thing tag (1100)
1061 * t : External port thing tag (1101)
1062 * t : External ref thing tag (1110)
1063 * N : Next (off_heap) pointer
1064 * E : ErlNode pointer
1065 * X : Type specific data
1066 *
1067 * External pid layout (OTP 24):
1068 * External pids always have two 32-bit words (num and seq).
1069 *
1070 * External port layout (OTP 24):
1071 * External ports always have two 32-bit words.
1072 *
1073 * External refs layout:
1074 * External refs has the same layout for the data words as in the internal
1075 * ref.
1076 *
1077 */
1078
1079 typedef struct external_thing_ {
1080 /* ----+ */
1081 Eterm header; /* | */
1082 struct erl_node_* node; /* > External thing head */
1083 struct erl_off_heap_header* next; /* | */
1084 /* ----+ */
1085 union {
1086 struct {
1087 Uint32 num;
1088 Uint32 ser;
1089 } pid;
1090 struct {
1091 #ifdef ARCH_64
1092 Uint64 id;
1093 #else
1094 Uint32 low;
1095 Uint32 high;
1096 #endif
1097 } port;
1098 Uint32 ui32[1];
1099 Uint ui[1];
1100 } data;
1101 } ExternalThing;
1102
1103 #define EXTERNAL_THING_HEAD_SIZE (offsetof(ExternalThing,data) / sizeof(Uint))
1104
1105 /* external pid data is always 64 bits */
1106 #define EXTERNAL_PID_DATA_WORDS (8 / sizeof(Uint))
1107
1108 #define EXTERNAL_PID_HEAP_SIZE \
1109 (EXTERNAL_THING_HEAD_SIZE + EXTERNAL_PID_DATA_WORDS)
1110
1111 #define make_external_pid_header() \
1112 _make_header(EXTERNAL_PID_HEAP_SIZE-1,_TAG_HEADER_EXTERNAL_PID)
1113 #define is_external_pid_header(x) \
1114 (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_PID)
1115
1116 /* external port data is always 64 bits */
1117 #define EXTERNAL_PORT_DATA_WORDS (8 / sizeof(Uint))
1118
1119 #define EXTERNAL_PORT_HEAP_SIZE \
1120 (EXTERNAL_THING_HEAD_SIZE + EXTERNAL_PID_DATA_WORDS)
1121
1122 #define make_external_port_header() \
1123 _make_header(EXTERNAL_PORT_HEAP_SIZE-1,_TAG_HEADER_EXTERNAL_PORT)
1124 #define is_external_port_header(x) \
1125 (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_PORT)
1126
1127 #define make_external_ref_header(DW) \
1128 _make_header((DW)+EXTERNAL_THING_HEAD_SIZE-1,_TAG_HEADER_EXTERNAL_REF)
1129 #define is_external_ref_header(x) \
1130 (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_REF)
1131
1132 #define is_external_header(x) \
1133 (((x) & (_TAG_HEADER_MASK-_BINARY_XXX_MASK)) == _TAG_HEADER_EXTERNAL_PID \
1134 && ((x) & _TAG_HEADER_MASK) != _TAG_HEADER_MAP)
1135
1136 #define is_external(x) (is_boxed((x)) && is_external_header(*boxed_val((x))))
1137
1138 #define is_external_pid(x) \
1139 (is_boxed((x)) && is_external_pid_header(*boxed_val((x))))
1140 #define is_external_port(x) \
1141 (is_boxed((x)) && is_external_port_header(*boxed_val((x))))
1142
1143 #define is_external_ref(x) (_unchecked_is_boxed((x)) && is_external_ref_header(*boxed_val((x))))
1144
1145 #define _unchecked_is_external(x) \
1146 (_unchecked_is_boxed((x)) && is_external_header(*_unchecked_boxed_val((x))))
1147
1148 #define is_not_external(x) (!is_external((x)))
1149 #define is_not_external_pid(x) (!is_external_pid((x)))
1150 #define is_not_external_port(x) (!is_external_port((x)))
1151 #define is_not_external_ref(x) (!is_external_ref((x)))
1152
1153
1154 #define make_external(x) make_boxed((Eterm *) (x))
1155
1156 #define make_external_pid make_external
1157 #define make_external_port make_external
1158 #define make_external_ref make_external
1159
1160 #define _unchecked_external_val(x) _unchecked_boxed_val((x))
1161 _ET_DECLARE_CHECKED(Eterm*,external_val,Wterm)
1162 #define external_val(x) _ET_APPLY(external_val,(x))
1163
1164 #define external_thing_ptr(x) ((ExternalThing *) external_val((x)))
1165 #define _unchecked_external_thing_ptr(x) \
1166 ((ExternalThing *) _unchecked_external_val((x)))
1167
1168 #define _unchecked_external_thing_data_words(thing) \
1169 (_unchecked_thing_arityval((thing)->header) + (1 - EXTERNAL_THING_HEAD_SIZE))
1170 _ET_DECLARE_CHECKED(Uint,external_thing_data_words,ExternalThing*)
1171 #define external_thing_data_words(thing) _ET_APPLY(external_thing_data_words,(thing))
1172
1173 #define _unchecked_external_data_words(x) \
1174 _unchecked_external_thing_data_words(_unchecked_external_thing_ptr((x)))
1175 _ET_DECLARE_CHECKED(Uint,external_data_words,Wterm)
1176 #define external_data_words(x) _ET_APPLY(external_data_words,(x))
1177
1178 #define _unchecked_external_data(x) (_unchecked_external_thing_ptr((x))->data.ui)
1179 #define _unchecked_external_node(x) (_unchecked_external_thing_ptr((x))->node)
1180
1181 #define external_data(x) (external_thing_ptr((x))->data.ui)
1182 #define external_node(x) (external_thing_ptr((x))->node)
1183
1184 #define _unchecked_external_pid_data_words(x) \
1185 _unchecked_external_data_words((x))
1186 _ET_DECLARE_CHECKED(Uint,external_pid_data_words,Wterm)
1187 #define external_pid_data_words(x) _ET_APPLY(external_pid_data_words,(x))
1188
1189 #define _unchecked_external_pid_node(x) _unchecked_external_node((x))
1190 _ET_DECLARE_CHECKED(struct erl_node_*,external_pid_node,Wterm)
1191 #define external_pid_node(x) _ET_APPLY(external_pid_node,(x))
1192
1193 #define external_pid_number(x) (external_thing_ptr(x)->data.pid.num)
1194 #define external_pid_serial(x) (external_thing_ptr(x)->data.pid.ser)
1195
1196 #define _unchecked_external_port_data_words(x) \
1197 _unchecked_external_data_words((x))
1198 _ET_DECLARE_CHECKED(Uint,external_port_data_words,Wterm)
1199 #define external_port_data_words(x) _ET_APPLY(external_port_data_words,(x))
1200
1201 #define _unchecked_external_port_data(x) _unchecked_external_data((x))
1202 _ET_DECLARE_CHECKED(Uint*,external_port_data,Wterm)
1203 #define external_port_data(x) _ET_APPLY(external_port_data,(x))
1204
1205 #define _unchecked_external_port_node(x) _unchecked_external_node((x))
1206 _ET_DECLARE_CHECKED(struct erl_node_*,external_port_node,Wterm)
1207 #define external_port_node(x) _ET_APPLY(external_port_node,(x))
1208
1209 #ifdef ARCH_64
1210 #define external_port_number(x) ((Uint64) external_thing_ptr((x))->data.port.id)
1211 #else
1212 #define external_port_number(x) \
1213 ((((Uint64) external_thing_ptr((x))->data.port.high) << 32) \
1214 | ((Uint64) external_thing_ptr((x))->data.port.low))
1215 #endif
1216
1217 #define _unchecked_external_ref_data_words(x) \
1218 _unchecked_external_data_words((x))
1219 _ET_DECLARE_CHECKED(Uint,external_ref_data_words,Wterm)
1220 #define external_ref_data_words(x) _ET_APPLY(external_ref_data_words,(x))
1221 #define external_thing_ref_data_words(thing) external_thing_data_words(thing)
1222
1223 #define _unchecked_external_ref_data(x) (_unchecked_external_thing_ptr((x))->data.ui32)
1224 _ET_DECLARE_CHECKED(Uint32*,external_ref_data,Wterm)
1225 #define external_ref_data(x) _ET_APPLY(external_ref_data,(x))
1226 #define external_thing_ref_data(thing) ((thing)->data.ui32)
1227
1228 #define _unchecked_external_ref_node(x) _unchecked_external_node((x))
1229 _ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm)
1230 #define external_ref_node(x) _ET_APPLY(external_ref_node,(x))
1231
1232 /* maps */
1233
1234 #define MAP_HEADER_TAG_SZ (2)
1235 #define MAP_HEADER_ARITY_SZ (8)
1236 #define MAP_HEADER_VAL_SZ (16)
1237
1238 #define MAP_HEADER_TAG_FLATMAP_HEAD (0x0)
1239 #define MAP_HEADER_TAG_HAMT_NODE_BITMAP (0x1)
1240 #define MAP_HEADER_TAG_HAMT_HEAD_ARRAY (0x2)
1241 #define MAP_HEADER_TAG_HAMT_HEAD_BITMAP (0x3)
1242
1243 #define MAP_HEADER_TYPE(Hdr) (((Hdr) >> (_HEADER_ARITY_OFFS)) & (0x3))
1244 #define MAP_HEADER_ARITY(Hdr) (((Hdr) >> (_HEADER_ARITY_OFFS + MAP_HEADER_TAG_SZ)) & (0xff))
1245 #define MAP_HEADER_VAL(Hdr) (((Hdr) >> (_HEADER_ARITY_OFFS + MAP_HEADER_TAG_SZ + MAP_HEADER_ARITY_SZ)) & (0xffff))
1246
1247 #define make_hashmap(x) make_boxed((Eterm*)(x))
1248 #define is_hashmap(x) (is_boxed((x)) && is_hashmap_header(*boxed_val((x))))
1249 #define is_not_hashmap(x) (!is_hashmap(x))
1250 #define is_hashmap_header(x) (((x) & (_HEADER_MAP_HASHMAP_HEAD_MASK)) == HAMT_SUBTAG_HEAD_ARRAY)
1251 #define hashmap_val(x) _unchecked_boxed_val((x))
1252
1253 #define make_flatmap(x) make_boxed((Eterm*)(x))
1254 #define is_flatmap(x) (is_boxed((x)) && is_flatmap_header(*boxed_val((x))))
1255 #define is_not_flatmap(x) (!is_flatmap((x)))
1256 #define is_flatmap_header(x) (((x) & (_HEADER_MAP_SUBTAG_MASK)) == HAMT_SUBTAG_HEAD_FLATMAP)
1257 #define flatmap_val(x) (_unchecked_boxed_val((x)))
1258
1259 #define is_map_header(x) (((x) & (_TAG_HEADER_MASK)) == _TAG_HEADER_MAP)
1260 #define is_map(x) (is_boxed((x)) && is_map_header(*boxed_val(x)))
1261 #define is_not_map(x) (!is_map(x))
1262
1263 #define MAP_HEADER(hp, sz, keys) \
1264 ((hp)[0] = MAP_HEADER_FLATMAP, \
1265 (hp)[1] = sz, \
1266 (hp)[2] = keys)
1267
1268 #define MAP_SZ(sz) (MAP_HEADER_FLATMAP_SZ + 2*sz + 1)
1269
1270 #define MAP0_SZ MAP_SZ(0)
1271 #define MAP1_SZ MAP_SZ(1)
1272 #define MAP2_SZ MAP_SZ(2)
1273 #define MAP3_SZ MAP_SZ(3)
1274 #define MAP4_SZ MAP_SZ(4)
1275 #define MAP5_SZ MAP_SZ(5)
1276 #define MAP0(hp) \
1277 (MAP_HEADER(hp, 0, TUPLE0(hp+MAP_HEADER_FLATMAP_SZ)), \
1278 make_flatmap(hp))
1279 #define MAP1(hp, k1, v1) \
1280 (MAP_HEADER(hp, 1, TUPLE1(hp+1+MAP_HEADER_FLATMAP_SZ, k1)), \
1281 (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
1282 make_flatmap(hp))
1283 #define MAP2(hp, k1, v1, k2, v2) \
1284 (MAP_HEADER(hp, 2, TUPLE2(hp+2+MAP_HEADER_FLATMAP_SZ, k1, k2)), \
1285 (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
1286 (hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
1287 make_flatmap(hp))
1288 #define MAP3(hp, k1, v1, k2, v2, k3, v3) \
1289 (MAP_HEADER(hp, 3, TUPLE3(hp+3+MAP_HEADER_FLATMAP_SZ, k1, k2, k3)), \
1290 (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
1291 (hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
1292 (hp)[MAP_HEADER_FLATMAP_SZ+2] = v3, \
1293 make_flatmap(hp))
1294 #define MAP4(hp, k1, v1, k2, v2, k3, v3, k4, v4) \
1295 (MAP_HEADER(hp, 4, TUPLE4(hp+4+MAP_HEADER_FLATMAP_SZ, k1, k2, k3, k4)), \
1296 (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
1297 (hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
1298 (hp)[MAP_HEADER_FLATMAP_SZ+2] = v3, \
1299 (hp)[MAP_HEADER_FLATMAP_SZ+3] = v4, \
1300 make_flatmap(hp))
1301 #define MAP5(hp, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5) \
1302 (MAP_HEADER(hp, 5, TUPLE5(hp+5+MAP_HEADER_FLATMAP_SZ, k1, k2, k3, k4, k5)), \
1303 (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
1304 (hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
1305 (hp)[MAP_HEADER_FLATMAP_SZ+2] = v3, \
1306 (hp)[MAP_HEADER_FLATMAP_SZ+3] = v4, \
1307 (hp)[MAP_HEADER_FLATMAP_SZ+4] = v5, \
1308 make_flatmap(hp))
1309
1310
1311 /* number tests */
1312
1313 #define is_integer(x) (is_small(x) || is_big(x))
1314 #define is_not_integer(x) (!is_integer(x))
1315 #define is_number(x) (is_integer(x) || is_float(x))
1316
1317 #define SMALL_MINUS_ONE make_small(-1)
1318 #define SMALL_ZERO make_small(0)
1319 #define SMALL_ONE make_small(1)
1320
1321 #define ENULL 0
1322
1323 /* on some architectures CP contains labels which are not aligned */
1324 #ifdef NOT_ALIGNED
1325 #error "fix yer arch, like"
1326 #endif
1327
1328 #define _is_legal_cp(x) (((Uint)(x) & _CPMASK) == 0)
1329 #define _unchecked_make_cp(x) ((Eterm)(x))
1330 _ET_DECLARE_CHECKED(Eterm,make_cp,ErtsCodePtr)
1331 #define make_cp(x) _ET_APPLY(make_cp,(x))
1332
1333 #define is_not_CP(x) ((x) & _CPMASK)
1334 #define is_CP(x) (!is_not_CP(x))
1335
1336 #define _unchecked_cp_val(x) ((ErtsCodePtr) (x))
1337 _ET_DECLARE_CHECKED(ErtsCodePtr,cp_val,Eterm)
1338 #define cp_val(x) _ET_APPLY(cp_val,(x))
1339
1340 #define make_catch(x) (((x) << _TAG_IMMED2_SIZE) | _TAG_IMMED2_CATCH)
1341 #define is_catch(x) (((x) & _TAG_IMMED2_MASK) == _TAG_IMMED2_CATCH)
1342 #define is_not_catch(x) (!is_catch(x))
1343 #define _unchecked_catch_val(x) ((x) >> _TAG_IMMED2_SIZE)
1344 _ET_DECLARE_CHECKED(Uint,catch_val,Eterm)
1345 #define catch_val(x) _ET_APPLY(catch_val,(x))
1346
1347 #define make_blank(X) ((X) = NIL)
1348
1349 /*
1350 * Overloaded tags.
1351 *
1352 * In the loader, we want to tag a term in a way so that it can
1353 * be any literal (atom/integer/float/tuple/list/binary) or a
1354 * register.
1355 *
1356 * We can achive that by overloading the PID and PORT tags to
1357 * mean X and Y registers. That works because there are no
1358 * pid or port literals.
1359 */
1360
1361 #define _LOADER_TAG_XREG _TAG_IMMED1_PID
1362 #define _LOADER_TAG_YREG _TAG_IMMED1_PORT
1363 #define _LOADER_TAG_SIZE _TAG_IMMED1_SIZE
1364 #define _LOADER_MASK _TAG_IMMED1_MASK
1365
1366 #define LOADER_X_REG _LOADER_TAG_XREG
1367 #define LOADER_Y_REG _LOADER_TAG_YREG
1368
1369 #define make_loader_x_reg(R) (((R) << _LOADER_TAG_SIZE) | _LOADER_TAG_XREG)
1370 #define make_loader_y_reg(R) (((R) << _LOADER_TAG_SIZE) | _LOADER_TAG_YREG)
1371
1372 #define loader_reg_index(R) ((R) >> _LOADER_TAG_SIZE)
1373
1374 #define loader_tag(T) ((T) & _LOADER_MASK)
1375
1376 #define _is_loader_x_reg(x) (loader_tag(x) == _LOADER_TAG_XREG)
1377 #define _is_loader_y_reg(x) (loader_tag(x) == _LOADER_TAG_YREG)
1378
1379 #define _unchecked_loader_x_reg_index(R) ((R) >> _LOADER_TAG_SIZE)
1380 _ET_DECLARE_CHECKED(Uint,loader_x_reg_index,Uint)
1381 #define loader_x_reg_index(R) _ET_APPLY(loader_x_reg_index,(R))
1382
1383 #define _unchecked_loader_y_reg_index(R) ((R) >> _LOADER_TAG_SIZE)
1384 _ET_DECLARE_CHECKED(Uint,loader_y_reg_index,Uint)
1385 #define loader_y_reg_index(R) _ET_APPLY(loader_y_reg_index,(R))
1386
1387 /*
1388 * Backwards compatibility definitions:
1389 * - #define virtual *_DEF constants with values that fit term order:
1390 * number < atom < ref < fun < port < pid < tuple < map < nil < cons < binary
1391 * - tag_val_def() function generates virtual _DEF tag
1392 * - not_eq_tags() and NUMBER_CODE() defined in terms
1393 * of the tag_val_def() function
1394 */
1395
1396 #define BINARY_DEF 0x0
1397 #define LIST_DEF 0x1
1398 #define NIL_DEF 0x2
1399 #define MAP_DEF 0x3
1400 #define TUPLE_DEF 0x4
1401 #define PID_DEF 0x5
1402 #define EXTERNAL_PID_DEF 0x6
1403 #define PORT_DEF 0x7
1404 #define EXTERNAL_PORT_DEF 0x8
1405 #define EXPORT_DEF 0x9
1406 #define FUN_DEF 0xa
1407 #define REF_DEF 0xb
1408 #define EXTERNAL_REF_DEF 0xc
1409 #define ATOM_DEF 0xd
1410 #define FLOAT_DEF 0xe
1411 #define BIG_DEF 0xf
1412 #define SMALL_DEF 0x10
1413 #define MATCHSTATE_DEF 0x11 /* not a "real" term */
1414
1415 #define FIRST_VACANT_TAG_DEF 0x12
1416
1417 #if ET_DEBUG
1418 ERTS_GLB_INLINE unsigned tag_val_def(Wterm, const char*, unsigned);
1419 #else
1420 ERTS_GLB_INLINE unsigned tag_val_def(Wterm);
1421 #endif
1422
1423 #define not_eq_tags(X,Y) (tag_val_def((X)) ^ tag_val_def((Y)))
1424
1425 #define NUMBER_CODE(x,y) ((tag_val_def(x) << 5) | tag_val_def(y))
1426 #define _NUMBER_CODE(TX,TY) ((TX << 5) | TY)
1427 #define SMALL_SMALL _NUMBER_CODE(SMALL_DEF,SMALL_DEF)
1428 #define SMALL_BIG _NUMBER_CODE(SMALL_DEF,BIG_DEF)
1429 #define SMALL_FLOAT _NUMBER_CODE(SMALL_DEF,FLOAT_DEF)
1430 #define BIG_SMALL _NUMBER_CODE(BIG_DEF,SMALL_DEF)
1431 #define BIG_BIG _NUMBER_CODE(BIG_DEF,BIG_DEF)
1432 #define BIG_FLOAT _NUMBER_CODE(BIG_DEF,FLOAT_DEF)
1433 #define FLOAT_SMALL _NUMBER_CODE(FLOAT_DEF,SMALL_DEF)
1434 #define FLOAT_BIG _NUMBER_CODE(FLOAT_DEF,BIG_DEF)
1435 #define FLOAT_FLOAT _NUMBER_CODE(FLOAT_DEF,FLOAT_DEF)
1436
1437 #define is_same(A,B) ((A)==(B))
1438
1439 void erts_set_literal_tag(Eterm *term, Eterm *hp_start, Eterm hsz);
1440
1441 #if ET_DEBUG
1442 #define ET_ASSERT(expr,file,line) \
1443 do { \
1444 if (!(expr)) \
1445 erl_assert_error("TYPE ASSERTION: " #expr, __FUNCTION__, file, line); \
1446 } while(0)
1447 #else
1448 #define ET_ASSERT(expr,file,line) do { } while(0)
1449 #endif
1450
1451 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
1452
1453 #if ET_DEBUG
tag_val_def(Wterm x,const char * file,unsigned line)1454 ERTS_GLB_INLINE unsigned tag_val_def(Wterm x, const char *file, unsigned line)
1455 #else
1456 ERTS_GLB_INLINE unsigned tag_val_def(Wterm x)
1457 #define file __FILE__
1458 #define line __LINE__
1459 #endif
1460 {
1461
1462 switch (x & _TAG_PRIMARY_MASK) {
1463 case TAG_PRIMARY_LIST:
1464 ET_ASSERT(_list_precond(x),file,line);
1465 return LIST_DEF;
1466 case TAG_PRIMARY_BOXED: {
1467 Eterm hdr = *boxed_val(x);
1468 ET_ASSERT(is_header(hdr),file,line);
1469 switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {
1470 case (_TAG_HEADER_ARITYVAL >> _TAG_PRIMARY_SIZE): return TUPLE_DEF;
1471 case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE): return BIG_DEF;
1472 case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): return BIG_DEF;
1473 case (_TAG_HEADER_REF >> _TAG_PRIMARY_SIZE): return REF_DEF;
1474 case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): return FLOAT_DEF;
1475 case (_TAG_HEADER_EXPORT >> _TAG_PRIMARY_SIZE): return EXPORT_DEF;
1476 case (_TAG_HEADER_FUN >> _TAG_PRIMARY_SIZE): return FUN_DEF;
1477 case (_TAG_HEADER_EXTERNAL_PID >> _TAG_PRIMARY_SIZE): return EXTERNAL_PID_DEF;
1478 case (_TAG_HEADER_EXTERNAL_PORT >> _TAG_PRIMARY_SIZE): return EXTERNAL_PORT_DEF;
1479 case (_TAG_HEADER_EXTERNAL_REF >> _TAG_PRIMARY_SIZE): return EXTERNAL_REF_DEF;
1480 case (_TAG_HEADER_MAP >> _TAG_PRIMARY_SIZE): return MAP_DEF;
1481 case (_TAG_HEADER_REFC_BIN >> _TAG_PRIMARY_SIZE): return BINARY_DEF;
1482 case (_TAG_HEADER_HEAP_BIN >> _TAG_PRIMARY_SIZE): return BINARY_DEF;
1483 case (_TAG_HEADER_SUB_BIN >> _TAG_PRIMARY_SIZE): return BINARY_DEF;
1484 case (_TAG_HEADER_BIN_MATCHSTATE >> _TAG_PRIMARY_SIZE): return MATCHSTATE_DEF;
1485 }
1486
1487 break;
1488 }
1489 case TAG_PRIMARY_IMMED1: {
1490 switch ((x & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {
1491 case (_TAG_IMMED1_PID >> _TAG_PRIMARY_SIZE): return PID_DEF;
1492 case (_TAG_IMMED1_PORT >> _TAG_PRIMARY_SIZE): return PORT_DEF;
1493 case (_TAG_IMMED1_IMMED2 >> _TAG_PRIMARY_SIZE): {
1494 switch ((x & _TAG_IMMED2_MASK) >> _TAG_IMMED1_SIZE) {
1495 case (_TAG_IMMED2_ATOM >> _TAG_IMMED1_SIZE): return ATOM_DEF;
1496 case (_TAG_IMMED2_NIL >> _TAG_IMMED1_SIZE): return NIL_DEF;
1497 }
1498 break;
1499 }
1500 case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): return SMALL_DEF;
1501 }
1502 break;
1503 }
1504 }
1505 erl_assert_error("tag_val_def error", __FUNCTION__, file, line);
1506 #undef file
1507 #undef line
1508 }
1509 #endif
1510
1511 #if ET_DEBUG
1512 #define tag_val_def(X) tag_val_def(X, __FILE__, __LINE__)
1513 #endif
1514
1515 #endif /* __ERL_TERM_H */
1516
1517