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