aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_term.h
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /erts/emulator/beam/erl_term.h
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'erts/emulator/beam/erl_term.h')
-rw-r--r--erts/emulator/beam/erl_term.h1056
1 files changed, 1056 insertions, 0 deletions
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
new file mode 100644
index 0000000000..b0a57a3ebe
--- /dev/null
+++ b/erts/emulator/beam/erl_term.h
@@ -0,0 +1,1056 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2000-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef __ERL_TERM_H
+#define __ERL_TERM_H
+
+struct erl_node_; /* Declared in erl_node_tables.h */
+
+/*
+ * Defining ET_DEBUG to 1 causes all type-specific data access
+ * macros to perform runtime type checking. This is very useful
+ * during development but reduces performance, so ET_DEBUG should
+ * be disabled during benchmarking or release.
+ */
+/* #define ET_DEBUG 1 */
+#ifndef ET_DEBUG
+# ifdef DEBUG
+# define ET_DEBUG 1
+# else
+# define ET_DEBUG 0
+# endif
+#endif
+
+#if ET_DEBUG
+#define _ET_DECLARE_CHECKED(TF,F,TX) extern TF checked_##F(TX,const char*,unsigned)
+#define _ET_APPLY(F,X) checked_##F(X,__FILE__,__LINE__)
+#else
+#define _ET_DECLARE_CHECKED(TF,F,TX)
+#define _ET_APPLY(F,X) _unchecked_##F(X)
+#endif
+
+#define _TAG_PRIMARY_SIZE 2
+#define _TAG_PRIMARY_MASK 0x3
+#define TAG_PRIMARY_HEADER 0x0
+#define TAG_PRIMARY_LIST 0x1
+#define TAG_PRIMARY_BOXED 0x2
+#define TAG_PRIMARY_IMMED1 0x3
+
+#define primary_tag(x) ((x) & _TAG_PRIMARY_MASK)
+
+#define _TAG_IMMED1_SIZE 4
+#define _TAG_IMMED1_MASK 0xF
+#define _TAG_IMMED1_PID ((0x0 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
+#define _TAG_IMMED1_PORT ((0x1 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
+#define _TAG_IMMED1_IMMED2 ((0x2 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
+#define _TAG_IMMED1_SMALL ((0x3 << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_IMMED1)
+
+#define _TAG_IMMED2_SIZE 6
+#define _TAG_IMMED2_MASK 0x3F
+#define _TAG_IMMED2_ATOM ((0x0 << _TAG_IMMED1_SIZE) | _TAG_IMMED1_IMMED2)
+#define _TAG_IMMED2_CATCH ((0x1 << _TAG_IMMED1_SIZE) | _TAG_IMMED1_IMMED2)
+#define _TAG_IMMED2_NIL ((0x3 << _TAG_IMMED1_SIZE) | _TAG_IMMED1_IMMED2)
+
+/*
+ * HEADER representation:
+ *
+ * aaaaaaaaaaaaaaaaaaaaaaaaaatttt00 arity:26, tag:4
+ *
+ * HEADER tags:
+ *
+ * 0000 ARITYVAL
+ * 0001 BINARY_AGGREGATE |
+ * 001x BIGNUM with sign bit |
+ * 0100 REF |
+ * 0101 FUN | THINGS
+ * 0110 FLONUM |
+ * 0111 EXPORT |
+ * 1000 REFC_BINARY | |
+ * 1001 HEAP_BINARY | BINARIES |
+ * 1010 SUB_BINARY | |
+ * 1011 Not used
+ * 1100 EXTERNAL_PID | |
+ * 1101 EXTERNAL_PORT | EXTERNAL THINGS |
+ * 1110 EXTERNAL_REF | |
+ * 1111 Not used
+ *
+ * COMMENTS:
+ *
+ * - The tag is zero for arityval and non-zero for thing headers.
+ * - A single bit differentiates between positive and negative bignums.
+ * - If more tags are needed, the REF and and EXTERNAL_REF tags could probably
+ * be combined to one tag.
+ *
+ * XXX: globally replace XXX_SUBTAG with TAG_HEADER_XXX
+ */
+#define ARITYVAL_SUBTAG (0x0 << _TAG_PRIMARY_SIZE) /* TUPLE */
+#define BIN_MATCHSTATE_SUBTAG (0x1 << _TAG_PRIMARY_SIZE)
+#define POS_BIG_SUBTAG (0x2 << _TAG_PRIMARY_SIZE) /* BIG: tags 2&3 */
+#define NEG_BIG_SUBTAG (0x3 << _TAG_PRIMARY_SIZE) /* BIG: tags 2&3 */
+#define _BIG_SIGN_BIT (0x1 << _TAG_PRIMARY_SIZE)
+#define REF_SUBTAG (0x4 << _TAG_PRIMARY_SIZE) /* REF */
+#define FUN_SUBTAG (0x5 << _TAG_PRIMARY_SIZE) /* FUN */
+#define FLOAT_SUBTAG (0x6 << _TAG_PRIMARY_SIZE) /* FLOAT */
+#define EXPORT_SUBTAG (0x7 << _TAG_PRIMARY_SIZE) /* FLOAT */
+#define _BINARY_XXX_MASK (0x3 << _TAG_PRIMARY_SIZE)
+#define REFC_BINARY_SUBTAG (0x8 << _TAG_PRIMARY_SIZE) /* BINARY */
+#define HEAP_BINARY_SUBTAG (0x9 << _TAG_PRIMARY_SIZE) /* BINARY */
+#define SUB_BINARY_SUBTAG (0xA << _TAG_PRIMARY_SIZE) /* BINARY */
+#define EXTERNAL_PID_SUBTAG (0xC << _TAG_PRIMARY_SIZE) /* EXTERNAL_PID */
+#define EXTERNAL_PORT_SUBTAG (0xD << _TAG_PRIMARY_SIZE) /* EXTERNAL_PORT */
+#define EXTERNAL_REF_SUBTAG (0xE << _TAG_PRIMARY_SIZE) /* EXTERNAL_REF */
+
+
+#define _TAG_HEADER_ARITYVAL (TAG_PRIMARY_HEADER|ARITYVAL_SUBTAG)
+#define _TAG_HEADER_FUN (TAG_PRIMARY_HEADER|FUN_SUBTAG)
+#define _TAG_HEADER_POS_BIG (TAG_PRIMARY_HEADER|POS_BIG_SUBTAG)
+#define _TAG_HEADER_NEG_BIG (TAG_PRIMARY_HEADER|NEG_BIG_SUBTAG)
+#define _TAG_HEADER_FLOAT (TAG_PRIMARY_HEADER|FLOAT_SUBTAG)
+#define _TAG_HEADER_EXPORT (TAG_PRIMARY_HEADER|EXPORT_SUBTAG)
+#define _TAG_HEADER_REF (TAG_PRIMARY_HEADER|REF_SUBTAG)
+#define _TAG_HEADER_REFC_BIN (TAG_PRIMARY_HEADER|REFC_BINARY_SUBTAG)
+#define _TAG_HEADER_HEAP_BIN (TAG_PRIMARY_HEADER|HEAP_BINARY_SUBTAG)
+#define _TAG_HEADER_SUB_BIN (TAG_PRIMARY_HEADER|SUB_BINARY_SUBTAG)
+#define _TAG_HEADER_EXTERNAL_PID (TAG_PRIMARY_HEADER|EXTERNAL_PID_SUBTAG)
+#define _TAG_HEADER_EXTERNAL_PORT (TAG_PRIMARY_HEADER|EXTERNAL_PORT_SUBTAG)
+#define _TAG_HEADER_EXTERNAL_REF (TAG_PRIMARY_HEADER|EXTERNAL_REF_SUBTAG)
+#define _TAG_HEADER_BIN_MATCHSTATE (TAG_PRIMARY_HEADER|BIN_MATCHSTATE_SUBTAG)
+
+
+#define _TAG_HEADER_MASK 0x3F
+#define _HEADER_SUBTAG_MASK 0x3C /* 4 bits for subtag */
+#define _HEADER_ARITY_OFFS 6
+
+#define header_is_transparent(x) \
+ (((x) & (_HEADER_SUBTAG_MASK)) == ARITYVAL_SUBTAG)
+#define header_is_arityval(x) (((x) & _HEADER_SUBTAG_MASK) == ARITYVAL_SUBTAG)
+#define header_is_thing(x) (!header_is_transparent((x)))
+#define header_is_bin_matchstate(x) ((((x) & (_HEADER_SUBTAG_MASK)) == BIN_MATCHSTATE_SUBTAG))
+
+#define _CPMASK 0x3
+
+/* immediate object access methods */
+#define is_immed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_IMMED1)
+#define is_not_immed(x) (!is_immed((x)))
+#define IS_CONST(x) is_immed((x))
+#if TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK
+#define is_both_immed(x,y) is_immed(((x)&(y)))
+#else
+#define is_both_immed(x,y) (is_immed((x)) && is_immed((y)))
+#endif
+#define is_not_both_immed(x,y) (!is_both_immed((x),(y)))
+
+
+/* boxed object access methods */
+#define _is_aligned(x) (((Uint)(x) & 0x3) == 0)
+#define _unchecked_make_boxed(x) ((Uint)(x) + TAG_PRIMARY_BOXED)
+_ET_DECLARE_CHECKED(Eterm,make_boxed,Eterm*);
+#define make_boxed(x) _ET_APPLY(make_boxed,(x))
+#if 1
+#define _is_not_boxed(x) ((x) & (_TAG_PRIMARY_MASK-TAG_PRIMARY_BOXED))
+#define _unchecked_is_boxed(x) (!_is_not_boxed((x)))
+_ET_DECLARE_CHECKED(int,is_boxed,Eterm);
+#define is_boxed(x) _ET_APPLY(is_boxed,(x))
+#else
+#define is_boxed(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_BOXED)
+#endif
+#define _unchecked_boxed_val(x) ((Eterm*)((x) - TAG_PRIMARY_BOXED))
+_ET_DECLARE_CHECKED(Eterm*,boxed_val,Eterm);
+#define boxed_val(x) _ET_APPLY(boxed_val,(x))
+
+/* cons cell ("list") access methods */
+#define _unchecked_make_list(x) ((Uint)(x) + TAG_PRIMARY_LIST)
+_ET_DECLARE_CHECKED(Eterm,make_list,Eterm*);
+#define make_list(x) _ET_APPLY(make_list,(x))
+#if 1
+#define _unchecked_is_not_list(x) ((x) & (_TAG_PRIMARY_MASK-TAG_PRIMARY_LIST))
+_ET_DECLARE_CHECKED(int,is_not_list,Eterm);
+#define is_not_list(x) _ET_APPLY(is_not_list,(x))
+#define is_list(x) (!is_not_list((x)))
+#else
+#define is_list(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_LIST)
+#define is_not_list(x) (!is_list((x)))
+#endif
+#define _unchecked_list_val(x) ((Eterm*)((x) - TAG_PRIMARY_LIST))
+_ET_DECLARE_CHECKED(Eterm*,list_val,Eterm);
+#define list_val(x) _ET_APPLY(list_val,(x))
+
+#define CONS(hp, car, cdr) \
+ (CAR(hp)=(car), CDR(hp)=(cdr), make_list(hp))
+
+#define CAR(x) ((x)[0])
+#define CDR(x) ((x)[1])
+
+/* generic tagged pointer (boxed or list) access methods */
+#define _unchecked_ptr_val(x) ((Eterm*)((x) & ~((Uint) 0x3)))
+#define ptr_val(x) _unchecked_ptr_val((x)) /*XXX*/
+#define _unchecked_offset_ptr(x,offs) ((x)+((offs)*sizeof(Eterm)))
+#define offset_ptr(x,offs) _unchecked_offset_ptr(x,offs) /*XXX*/
+
+/* fixnum ("small") access methods */
+#if defined(ARCH_64)
+#define SMALL_BITS (64-4)
+#define SMALL_DIGITS (17)
+#else
+#define SMALL_BITS (28)
+#define SMALL_DIGITS (8)
+#endif
+#define MAX_SMALL ((1L << (SMALL_BITS-1))-1)
+#define MIN_SMALL (-(1L << (SMALL_BITS-1)))
+#define make_small(x) (((Uint)(x) << _TAG_IMMED1_SIZE) + _TAG_IMMED1_SMALL)
+#define is_small(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
+#define is_not_small(x) (!is_small((x)))
+#define is_byte(x) (((x) & ((~(Uint)0 << (_TAG_IMMED1_SIZE+8)) + _TAG_IMMED1_MASK)) == _TAG_IMMED1_SMALL)
+#define is_valid_bit_size(x) (((Sint)(x)) >= 0 && ((x) & 0x7F) == _TAG_IMMED1_SMALL)
+#define is_not_valid_bit_size(x) (!is_valid_bit_size((x)))
+#define MY_IS_SSMALL(x) (((Uint) (((x) >> (SMALL_BITS-1)) + 1)) < 2)
+#define _unchecked_unsigned_val(x) ((x) >> _TAG_IMMED1_SIZE)
+_ET_DECLARE_CHECKED(Uint,unsigned_val,Eterm);
+#define unsigned_val(x) _ET_APPLY(unsigned_val,(x))
+#define _unchecked_signed_val(x) ((Sint)(x) >> _TAG_IMMED1_SIZE)
+_ET_DECLARE_CHECKED(Sint,signed_val,Eterm);
+#define signed_val(x) _ET_APPLY(signed_val,(x))
+
+#if _TAG_IMMED1_SMALL == 0x0F
+#define is_both_small(x,y) (((x) & (y) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
+#elif _TAG_IMMED1_SMALL == 0x00
+#define is_both_small(x,y) ((((x)|(y)) & _TAG_IMMED1_MASK) == _TAG_IMMED1_SMALL)
+#else
+#define is_both_small(x,y) (is_small(x) && is_small(y))
+#endif
+
+/* NIL access methods */
+#define NIL ((~((Uint) 0) << _TAG_IMMED2_SIZE) | _TAG_IMMED2_NIL)
+#define is_nil(x) ((x) == NIL)
+#define is_not_nil(x) ((x) != NIL)
+
+#define MAX_ATOM_INDEX (~(~((Uint) 0) << (sizeof(Uint)*8 - _TAG_IMMED2_SIZE)))
+
+/* atom access methods */
+#define make_atom(x) ((Eterm)(((x) << _TAG_IMMED2_SIZE) + _TAG_IMMED2_ATOM))
+#define is_atom(x) (((x) & _TAG_IMMED2_MASK) == _TAG_IMMED2_ATOM)
+#define is_not_atom(x) (!is_atom(x))
+#define _unchecked_atom_val(x) ((x) >> _TAG_IMMED2_SIZE)
+_ET_DECLARE_CHECKED(Uint,atom_val,Eterm);
+#define atom_val(x) _ET_APPLY(atom_val,(x))
+
+/* header (arityval or thing) access methods */
+#define _make_header(sz,tag) ((Uint)(((sz) << _HEADER_ARITY_OFFS) + (tag)))
+#define is_header(x) (((x) & _TAG_PRIMARY_MASK) == TAG_PRIMARY_HEADER)
+#define _unchecked_header_arity(x) ((x) >> _HEADER_ARITY_OFFS)
+_ET_DECLARE_CHECKED(Uint,header_arity,Eterm);
+#define header_arity(x) _ET_APPLY(header_arity,(x))
+
+/* arityval access methods */
+#define make_arityval(sz) _make_header((sz),_TAG_HEADER_ARITYVAL)
+#define is_arity_value(x) (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_ARITYVAL)
+#define is_not_arity_value(x) (!is_arity_value((x)))
+#define _unchecked_arityval(x) _unchecked_header_arity((x))
+_ET_DECLARE_CHECKED(Uint,arityval,Eterm);
+#define arityval(x) _ET_APPLY(arityval,(x))
+
+/* thing access methods */
+#define is_thing(x) (is_header((x)) && header_is_thing((x)))
+#define _unchecked_thing_arityval(x) _unchecked_header_arity((x))
+_ET_DECLARE_CHECKED(Uint,thing_arityval,Eterm);
+#define thing_arityval(x) _ET_APPLY(thing_arityval,(x))
+#define _unchecked_thing_subtag(x) ((x) & _HEADER_SUBTAG_MASK)
+_ET_DECLARE_CHECKED(Uint,thing_subtag,Eterm);
+#define thing_subtag(x) _ET_APPLY(thing_subtag,(x))
+
+/*
+ * Magic non-value object.
+ * Used as function return error and "absent value" indicator
+ * in the original runtime system. The new runtime system also
+ * uses it as forwarding marker for CONS cells.
+ *
+ * This value is 0 in the original runtime system, which unfortunately
+ * promotes sloppy programming practices. It also prevents some useful
+ * tag assignment schemes, e.g. using a 2-bit tag 00 for FIXNUM.
+ *
+ * To help find code which makes unwarranted assumptions about zero,
+ * we now use a non-zero bit-pattern in debug mode.
+ */
+#if ET_DEBUG
+#define THE_NON_VALUE _make_header(0,_TAG_HEADER_FLOAT)
+#else
+#define THE_NON_VALUE (0)
+#endif
+#define is_non_value(x) ((x) == THE_NON_VALUE)
+#define is_value(x) ((x) != THE_NON_VALUE)
+
+/* binary object access methods */
+#define is_binary_header(x) (((x) & (_TAG_HEADER_MASK-_BINARY_XXX_MASK)) == _TAG_HEADER_REFC_BIN)
+#define make_binary(x) make_boxed((Eterm*)(x))
+#define is_binary(x) (is_boxed((x)) && is_binary_header(*boxed_val((x))))
+#define is_not_binary(x) (!is_binary((x)))
+#define _unchecked_binary_val(x) _unchecked_boxed_val((x))
+_ET_DECLARE_CHECKED(Eterm*,binary_val,Eterm);
+#define binary_val(x) _ET_APPLY(binary_val,(x))
+
+/* process binaries stuff (special case of binaries) */
+#define HEADER_PROC_BIN _make_header(PROC_BIN_SIZE-1,_TAG_HEADER_REFC_BIN)
+
+/* fun & export objects */
+#define is_any_fun(x) (is_fun((x)) || is_export((x)))
+#define is_not_any_fun(x) (!is_any_fun((x)))
+
+/* fun objects */
+#define HEADER_FUN _make_header(ERL_FUN_SIZE-2,_TAG_HEADER_FUN)
+#define is_fun_header(x) ((x) == HEADER_FUN)
+#define make_fun(x) make_boxed((Eterm*)(x))
+#define is_fun(x) (is_boxed((x)) && is_fun_header(*boxed_val((x))))
+#define is_not_fun(x) (!is_fun((x)))
+#define _unchecked_fun_val(x) _unchecked_boxed_val((x))
+_ET_DECLARE_CHECKED(Eterm*,fun_val,Eterm);
+#define fun_val(x) _ET_APPLY(fun_val,(x))
+
+/* export access methods */
+#define make_export(x) make_boxed((x))
+#define is_export(x) (is_boxed((x)) && is_export_header(*boxed_val((x))))
+#define is_not_export(x) (!is_export((x)))
+#define _unchecked_export_val(x) _unchecked_boxed_val(x)
+_ET_DECLARE_CHECKED(Eterm*,export_val,Eterm);
+#define export_val(x) _ET_APPLY(export_val,(x))
+#define is_export_header(x) ((x) == HEADER_EXPORT)
+#define HEADER_EXPORT _make_header(1,_TAG_HEADER_EXPORT)
+
+/* bignum access methods */
+#define make_pos_bignum_header(sz) _make_header((sz),_TAG_HEADER_POS_BIG)
+#define make_neg_bignum_header(sz) _make_header((sz),_TAG_HEADER_NEG_BIG)
+#define _is_bignum_header(x) (((x) & (_TAG_HEADER_MASK-_BIG_SIGN_BIT)) == _TAG_HEADER_POS_BIG)
+#define _unchecked_bignum_header_is_neg(x) ((x) & _BIG_SIGN_BIT)
+_ET_DECLARE_CHECKED(int,bignum_header_is_neg,Eterm);
+#define bignum_header_is_neg(x) _ET_APPLY(bignum_header_is_neg,(x))
+#define _unchecked_bignum_header_neg(x) ((x) | _BIG_SIGN_BIT)
+_ET_DECLARE_CHECKED(Eterm,bignum_header_neg,Eterm);
+#define bignum_header_neg(x) _ET_APPLY(bignum_header_neg,(x))
+#define _unchecked_bignum_header_arity(x) _unchecked_header_arity((x))
+_ET_DECLARE_CHECKED(Uint,bignum_header_arity,Eterm);
+#define bignum_header_arity(x) _ET_APPLY(bignum_header_arity,(x))
+#define BIG_ARITY_MAX ((1 << 19)-1)
+#define make_big(x) make_boxed((x))
+#define is_big(x) (is_boxed((x)) && _is_bignum_header(*boxed_val((x))))
+#define is_not_big(x) (!is_big((x)))
+#define _unchecked_big_val(x) _unchecked_boxed_val((x))
+_ET_DECLARE_CHECKED(Eterm*,big_val,Eterm);
+#define big_val(x) _ET_APPLY(big_val,(x))
+
+/* flonum ("float") access methods */
+#ifdef ARCH_64
+#define HEADER_FLONUM _make_header(1,_TAG_HEADER_FLOAT)
+#else
+#define HEADER_FLONUM _make_header(2,_TAG_HEADER_FLOAT)
+#endif
+#define make_float(x) make_boxed((x))
+#define is_float(x) (is_boxed((x)) && *boxed_val((x)) == HEADER_FLONUM)
+#define is_not_float(x) (!is_float(x))
+#define _unchecked_float_val(x) _unchecked_boxed_val((x))
+_ET_DECLARE_CHECKED(Eterm*,float_val,Eterm);
+#define float_val(x) _ET_APPLY(float_val,(x))
+
+/* Float definition for byte and word access */
+typedef double ieee754_8;
+
+typedef union float_def
+{
+ ieee754_8 fd;
+ byte fb[sizeof(ieee754_8)];
+ Uint16 fs[sizeof(ieee754_8) / sizeof(Uint16)];
+ Uint32 fw[sizeof(ieee754_8) / sizeof(Uint32)];
+#ifdef ARCH_64
+ Uint fdw;
+#endif
+} FloatDef;
+
+#ifdef ARCH_64
+#define GET_DOUBLE(x, f) (f).fdw = *(float_val(x)+1)
+
+#define PUT_DOUBLE(f, x) *(x) = HEADER_FLONUM, \
+ *((x)+1) = (f).fdw
+#define GET_DOUBLE_DATA(p, f) (f).fdw = *((Uint *) (p))
+#define PUT_DOUBLE_DATA(f,p) *((Uint *) (p)) = (f).fdw
+#else
+#define GET_DOUBLE(x, f) (f).fw[0] = *(float_val(x)+1), \
+ (f).fw[1] = *(float_val(x)+2)
+
+#define PUT_DOUBLE(f, x) *(x) = HEADER_FLONUM, \
+ *((x)+1) = (f).fw[0], \
+ *((x)+2) = (f).fw[1]
+#define GET_DOUBLE_DATA(p, f) (f).fw[0] = *((Uint *) (p)),\
+ (f).fw[1] = *(((Uint *) (p))+1)
+#define PUT_DOUBLE_DATA(f,p) *((Uint *) (p)) = (f).fw[0],\
+ *(((Uint *) (p))+1) = (f).fw[1]
+#endif
+#define DOUBLE_DATA_WORDS (sizeof(ieee754_8)/sizeof(Eterm))
+#define FLOAT_SIZE_OBJECT (DOUBLE_DATA_WORDS+1)
+
+/* tuple access methods */
+#define make_tuple(x) make_boxed((x))
+#define is_tuple(x) (is_boxed((x)) && is_arity_value(*boxed_val((x))))
+#define is_not_tuple(x) (!is_tuple((x)))
+#define is_tuple_arity(x, a) \
+ (is_boxed((x)) && *boxed_val((x)) == make_arityval((a)))
+#define is_not_tuple_arity(x, a) (!is_tuple_arity((x),(a)))
+#define _unchecked_tuple_val(x) _unchecked_boxed_val(x)
+_ET_DECLARE_CHECKED(Eterm*,tuple_val,Eterm);
+#define tuple_val(x) _ET_APPLY(tuple_val,(x))
+
+#define TUPLE0(t) \
+ ((t)[0] = make_arityval(0), \
+ make_tuple(t))
+#define TUPLE1(t,e1) \
+ ((t)[0] = make_arityval(1), \
+ (t)[1] = (e1), \
+ make_tuple(t))
+#define TUPLE2(t,e1,e2) \
+ ((t)[0] = make_arityval(2), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ make_tuple(t))
+#define TUPLE3(t,e1,e2,e3) \
+ ((t)[0] = make_arityval(3), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ (t)[3] = (e3), \
+ make_tuple(t))
+#define TUPLE4(t,e1,e2,e3,e4) \
+ ((t)[0] = make_arityval(4), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ (t)[3] = (e3), \
+ (t)[4] = (e4), \
+ make_tuple(t))
+#define TUPLE5(t,e1,e2,e3,e4,e5) \
+ ((t)[0] = make_arityval(5), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ (t)[3] = (e3), \
+ (t)[4] = (e4), \
+ (t)[5] = (e5), \
+ make_tuple(t))
+#define TUPLE6(t,e1,e2,e3,e4,e5,e6) \
+ ((t)[0] = make_arityval(6), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ (t)[3] = (e3), \
+ (t)[4] = (e4), \
+ (t)[5] = (e5), \
+ (t)[6] = (e6), \
+ make_tuple(t))
+
+#define TUPLE7(t,e1,e2,e3,e4,e5,e6,e7) \
+ ((t)[0] = make_arityval(7), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ (t)[3] = (e3), \
+ (t)[4] = (e4), \
+ (t)[5] = (e5), \
+ (t)[6] = (e6), \
+ (t)[7] = (e7), \
+ make_tuple(t))
+
+#define TUPLE8(t,e1,e2,e3,e4,e5,e6,e7,e8) \
+ ((t)[0] = make_arityval(8), \
+ (t)[1] = (e1), \
+ (t)[2] = (e2), \
+ (t)[3] = (e3), \
+ (t)[4] = (e4), \
+ (t)[5] = (e5), \
+ (t)[6] = (e6), \
+ (t)[7] = (e7), \
+ (t)[8] = (e8), \
+ make_tuple(t))
+
+/* This macro get Size bits starting at low order position Pos
+ and adjusts the bits to the right
+ bits are numbered from 0 - (sizeof(Uint)*8-1) */
+
+#define _GETBITS(X,Pos,Size) (((X) >> (Pos)) & ~(~((Uint) 0) << (Size)))
+
+/*
+ * Observe! New layout for pids, ports and references in R9 (see also note
+ * in erl_node_container_utils.h).
+ */
+
+
+/*
+ * Creation in node specific data (pids, ports, refs)
+ */
+
+#define _CRE_SIZE 2
+
+/* MAX value for the creation field in pid, port and reference */
+#define MAX_CREATION (1 << _CRE_SIZE)
+
+/*
+ * PID layout (internal pids):
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * n : number
+ *
+ * Old pid layout:
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * s : serial
+ * n : number
+ * c : creation
+ * N : node number
+ *
+ */
+
+#define _PID_R9_SER_SIZE 3
+#define _PID_SER_SIZE (_PID_DATA_SIZE - _PID_NUM_SIZE)
+#define _PID_NUM_SIZE 15
+
+#define _PID_DATA_SIZE 28
+#define _PID_DATA_SHIFT (_TAG_IMMED1_SIZE)
+
+#define _GET_PID_DATA(X) _GETBITS((X),_PID_DATA_SHIFT,_PID_DATA_SIZE)
+#define _GET_PID_NUM(X) _GETBITS((X),0,_PID_NUM_SIZE)
+#define _GET_PID_SER(X) _GETBITS((X),_PID_NUM_SIZE,_PID_SER_SIZE)
+
+#define make_pid_data(Ser, Num) \
+ ((Uint) ((Ser) << _PID_NUM_SIZE | (Num)))
+
+#define make_internal_pid(X) \
+ ((Eterm) (((X) << _PID_DATA_SHIFT) | _TAG_IMMED1_PID))
+
+#define is_internal_pid(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_PID)
+#define is_not_internal_pid(x) (!is_internal_pid((x)))
+
+#define _unchecked_internal_pid_data(x) _GET_PID_DATA((x))
+_ET_DECLARE_CHECKED(Uint,internal_pid_data,Eterm);
+#define internal_pid_data(x) _ET_APPLY(internal_pid_data,(x))
+
+#define _unchecked_internal_pid_node(x) erts_this_node
+_ET_DECLARE_CHECKED(struct erl_node_*,internal_pid_node,Eterm);
+#define internal_pid_node(x) _ET_APPLY(internal_pid_node,(x))
+
+#define internal_pid_number(x) _GET_PID_NUM(internal_pid_data((x)))
+#define internal_pid_serial(x) _GET_PID_SER(internal_pid_data((x)))
+
+#define internal_pid_data_words(x) (1)
+
+/*
+ * PORT layout (internal ports):
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * n : number
+ *
+ * Old port layout:
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * s : serial
+ * n : number
+ * c : creation
+ * N : node number
+ *
+ */
+#define _PORT_R9_NUM_SIZE 18
+#define _PORT_NUM_SIZE _PORT_DATA_SIZE
+
+#define _PORT_DATA_SIZE 28
+#define _PORT_DATA_SHIFT (_TAG_IMMED1_SIZE)
+
+#define _GET_PORT_DATA(X) _GETBITS((X),_PORT_DATA_SHIFT,_PORT_DATA_SIZE)
+#define _GET_PORT_NUM(X) _GETBITS((X), 0, _PORT_NUM_SIZE)
+
+
+#define make_internal_port(X) \
+ ((Eterm) (((X) << _PORT_DATA_SHIFT) | _TAG_IMMED1_PORT))
+
+#define is_internal_port(x) (((x) & _TAG_IMMED1_MASK) == _TAG_IMMED1_PORT)
+#define is_not_internal_port(x) (!is_internal_port(x))
+
+#define _unchecked_internal_port_data(x) _GET_PORT_DATA((x))
+_ET_DECLARE_CHECKED(Uint,internal_port_data,Eterm);
+#define internal_port_data(x) _ET_APPLY(internal_port_data,(x))
+
+#define internal_port_number(x) _GET_PORT_NUM(internal_port_data((x)))
+
+#define _unchecked_internal_port_node(x) erts_this_node
+_ET_DECLARE_CHECKED(struct erl_node_*,internal_port_node,Eterm);
+#define internal_port_node(x) _ET_APPLY(internal_port_node,(x))
+
+#define internal_port_data_words(x) (1)
+/*
+ * Ref layout (internal references):
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *
+ * r : reference number
+ * c : creation
+ *
+ *
+ * Old "heap ref" layout:
+ *
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * r : reference number
+ * c : creation
+ * N : node index
+ *
+ * Old "one-word ref" layout:
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * r : reference number
+ * c : creation
+ * N : node index
+ *
+ */
+#define _REF_NUM_SIZE 18
+
+/* Old maximum number of references in the system */
+#define MAX_REFERENCE (1 << _REF_NUM_SIZE)
+#define REF_MASK (~(~((Uint)0) << _REF_NUM_SIZE))
+#define ERTS_MAX_REF_NUMBERS 3
+#define ERTS_REF_NUMBERS ERTS_MAX_REF_NUMBERS
+
+#ifdef ARCH_64
+# define ERTS_REF_WORDS (ERTS_REF_NUMBERS/2 + 1)
+# define ERTS_REF_32BIT_WORDS (ERTS_REF_NUMBERS+1)
+#else
+# define ERTS_REF_WORDS ERTS_REF_NUMBERS
+# define ERTS_REF_32BIT_WORDS ERTS_REF_NUMBERS
+#endif
+
+typedef struct {
+ Eterm header;
+ union {
+ Uint32 ui32[ERTS_REF_32BIT_WORDS];
+ Uint ui[ERTS_REF_WORDS];
+ } data;
+} RefThing;
+
+#define REF_THING_SIZE (sizeof(RefThing)/sizeof(Uint))
+#define REF_THING_HEAD_SIZE (sizeof(Eterm)/sizeof(Uint))
+
+#define make_ref_thing_header(DW) \
+ _make_header((DW)+REF_THING_HEAD_SIZE-1,_TAG_HEADER_REF)
+
+#ifdef ARCH_64
+
+/*
+ * Ref layout on a 64-bit little endian machine:
+ *
+ * 63 31 0
+ * +--------------+--------------+
+ * | Thing word |
+ * +--------------+--------------+
+ * | Data 0 | 32-bit arity |
+ * +--------------+--------------+
+ * | Data 2 | Data 1 |
+ * +--------------+--------------+
+ *
+ * Data is stored as an Uint32 array with 32-bit arity as first number.
+ */
+
+#define write_ref_thing(Hp, R0, R1, R2) \
+do { \
+ ((RefThing *) (Hp))->header = make_ref_thing_header(ERTS_REF_WORDS); \
+ ((RefThing *) (Hp))->data.ui32[0] = ERTS_REF_NUMBERS; \
+ ((RefThing *) (Hp))->data.ui32[1] = (R0); \
+ ((RefThing *) (Hp))->data.ui32[2] = (R1); \
+ ((RefThing *) (Hp))->data.ui32[3] = (R2); \
+} while (0)
+
+#else
+
+#define write_ref_thing(Hp, R0, R1, R2) \
+do { \
+ ((RefThing *) (Hp))->header = make_ref_thing_header(ERTS_REF_WORDS); \
+ ((RefThing *) (Hp))->data.ui32[0] = (R0); \
+ ((RefThing *) (Hp))->data.ui32[1] = (R1); \
+ ((RefThing *) (Hp))->data.ui32[2] = (R2); \
+} while (0)
+
+#endif
+
+#define is_ref_thing_header(x) (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_REF)
+#define make_internal_ref(x) make_boxed((Eterm*)(x))
+
+#define _unchecked_ref_thing_ptr(x) \
+ ((RefThing*) _unchecked_internal_ref_val(x))
+#define ref_thing_ptr(x) \
+ ((RefThing*) internal_ref_val(x))
+
+#define is_internal_ref(x) \
+ (_unchecked_is_boxed((x)) && is_ref_thing_header(*boxed_val((x))))
+#define is_not_internal_ref(x) \
+ (!is_internal_ref((x)))
+
+#define _unchecked_internal_ref_val(x) _unchecked_boxed_val((x))
+_ET_DECLARE_CHECKED(Eterm*,internal_ref_val,Eterm);
+#define internal_ref_val(x) _ET_APPLY(internal_ref_val,(x))
+
+#define _unchecked_internal_ref_data_words(x) \
+ (_unchecked_thing_arityval(*_unchecked_internal_ref_val(x)))
+_ET_DECLARE_CHECKED(Uint,internal_ref_data_words,Eterm);
+#define internal_ref_data_words(x) _ET_APPLY(internal_ref_data_words,(x))
+
+#define _unchecked_internal_ref_data(x) (_unchecked_ref_thing_ptr(x)->data.ui32)
+_ET_DECLARE_CHECKED(Uint32*,internal_ref_data,Eterm);
+#define internal_ref_data(x) _ET_APPLY(internal_ref_data,(x))
+
+#define _unchecked_internal_ref_node(x) erts_this_node
+_ET_DECLARE_CHECKED(struct erl_node_*,internal_ref_node,Eterm);
+#define internal_ref_node(x) _ET_APPLY(internal_ref_node,(x))
+
+/*
+ *
+ * External thing layout (external pids, ports, and refs):
+ *
+ * |3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
+ * |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|
+ * | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . . .
+ * . . .
+ * . . .
+ *
+ * A : Arity
+ * t : External pid thing tag (1100)
+ * t : External port thing tag (1101)
+ * t : External ref thing tag (1110)
+ * N : Next (external thing) pointer
+ * E : ErlNode pointer
+ * X : Type specific data
+ *
+ * External pid and port layout:
+ * External pids and ports only have one data word (Data 0) which has
+ * the same layout as internal pids resp. internal ports.
+ *
+ * External refs layout:
+ * External refs has the same layout for the data words as in the internal
+ * ref.
+ *
+ */
+
+typedef struct external_thing_ {
+ /* ----+ */
+ Eterm header; /* | */
+ struct external_thing_ *next; /* > External thing head */
+ struct erl_node_ *node; /* | */
+ /* ----+ */
+ union {
+ Uint32 ui32[1];
+ Uint ui[1];
+ } data;
+} ExternalThing;
+
+#define EXTERNAL_THING_HEAD_SIZE (sizeof(ExternalThing)/sizeof(Uint) - 1)
+
+#define make_external_pid_header(DW) \
+ _make_header((DW)+EXTERNAL_THING_HEAD_SIZE-1,_TAG_HEADER_EXTERNAL_PID)
+#define is_external_pid_header(x) \
+ (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_PID)
+
+#define make_external_port_header(DW) \
+ _make_header((DW)+EXTERNAL_THING_HEAD_SIZE-1,_TAG_HEADER_EXTERNAL_PORT)
+#define is_external_port_header(x) \
+ (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_PORT)
+
+#define make_external_ref_header(DW) \
+ _make_header((DW)+EXTERNAL_THING_HEAD_SIZE-1,_TAG_HEADER_EXTERNAL_REF)
+#define is_external_ref_header(x) \
+ (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_EXTERNAL_REF)
+
+#define is_external_header(x) \
+ (((x) & (_TAG_HEADER_MASK-_BINARY_XXX_MASK)) == _TAG_HEADER_EXTERNAL_PID)
+
+#define is_external(x) \
+ (is_boxed((x)) && is_external_header(*boxed_val((x))))
+#define is_external_pid(x) \
+ (is_boxed((x)) && is_external_pid_header(*boxed_val((x))))
+#define is_external_port(x) \
+ (is_boxed((x)) && is_external_port_header(*boxed_val((x))))
+#define is_external_ref(x) \
+ (_unchecked_is_boxed((x)) && is_external_ref_header(*boxed_val((x))))
+
+#define _unchecked_is_external(x) \
+ (_unchecked_is_boxed((x)) && is_external_header(*_unchecked_boxed_val((x))))
+
+#define is_not_external(x) (!is_external((x)))
+#define is_not_external_pid(x) (!is_external_pid((x)))
+#define is_not_external_port(x) (!is_external_port((x)))
+#define is_not_external_ref(x) (!is_external_ref((x)))
+
+
+#define make_external(x) make_boxed((Eterm *) (x))
+
+#define make_external_pid make_external
+#define make_external_port make_external
+#define make_external_ref make_external
+
+#define _unchecked_external_val(x) _unchecked_boxed_val((x))
+_ET_DECLARE_CHECKED(Eterm*,external_val,Eterm);
+#define external_val(x) _ET_APPLY(external_val,(x))
+
+#define external_thing_ptr(x) ((ExternalThing *) external_val((x)))
+#define _unchecked_external_thing_ptr(x) \
+ ((ExternalThing *) _unchecked_external_val((x)))
+
+#define _unchecked_external_data_words(x) \
+ (_unchecked_thing_arityval(_unchecked_external_thing_ptr((x))->header) \
+ + (1 - EXTERNAL_THING_HEAD_SIZE))
+_ET_DECLARE_CHECKED(Uint,external_data_words,Eterm);
+#define external_data_words(x) _ET_APPLY(external_data_words,(x))
+
+#define _unchecked_external_data(x) (_unchecked_external_thing_ptr((x))->data.ui)
+#define _unchecked_external_node(x) (_unchecked_external_thing_ptr((x))->node)
+
+#define external_data(x) (external_thing_ptr((x))->data.ui)
+#define external_node(x) (external_thing_ptr((x))->node)
+
+#define _unchecked_external_pid_data_words(x) \
+ _unchecked_external_data_words((x))
+_ET_DECLARE_CHECKED(Uint,external_pid_data_words,Eterm);
+#define external_pid_data_words(x) _ET_APPLY(external_pid_data_words,(x))
+
+#define _unchecked_external_pid_data(x) _unchecked_external_data((x))[0]
+_ET_DECLARE_CHECKED(Uint,external_pid_data,Eterm);
+#define external_pid_data(x) _ET_APPLY(external_pid_data,(x))
+
+#define _unchecked_external_pid_node(x) _unchecked_external_node((x))
+_ET_DECLARE_CHECKED(struct erl_node_*,external_pid_node,Eterm);
+#define external_pid_node(x) _ET_APPLY(external_pid_node,(x))
+
+#define external_pid_number(x) _GET_PID_NUM(external_pid_data((x)))
+#define external_pid_serial(x) _GET_PID_SER(external_pid_data((x)))
+
+#define _unchecked_external_port_data_words(x) \
+ _unchecked_external_data_words((x))
+_ET_DECLARE_CHECKED(Uint,external_port_data_words,Eterm);
+#define external_port_data_words(x) _ET_APPLY(external_port_data_words,(x))
+
+#define _unchecked_external_port_data(x) _unchecked_external_data((x))[0]
+_ET_DECLARE_CHECKED(Uint,external_port_data,Eterm);
+#define external_port_data(x) _ET_APPLY(external_port_data,(x))
+
+#define _unchecked_external_port_node(x) _unchecked_external_node((x))
+_ET_DECLARE_CHECKED(struct erl_node_*,external_port_node,Eterm);
+#define external_port_node(x) _ET_APPLY(external_port_node,(x))
+
+#define external_port_number(x) _GET_PORT_NUM(external_port_data((x)))
+
+#define _unchecked_external_ref_data_words(x) \
+ _unchecked_external_data_words((x))
+_ET_DECLARE_CHECKED(Uint,external_ref_data_words,Eterm);
+#define external_ref_data_words(x) _ET_APPLY(external_ref_data_words,(x))
+
+#define _unchecked_external_ref_data(x) (_unchecked_external_thing_ptr((x))->data.ui32)
+_ET_DECLARE_CHECKED(Uint32*,external_ref_data,Eterm);
+#define external_ref_data(x) _ET_APPLY(external_ref_data,(x))
+
+#define _unchecked_external_ref_node(x) _unchecked_external_node((x))
+_ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm);
+#define external_ref_node(x) _ET_APPLY(external_ref_node,(x))
+
+/* number tests */
+
+#define is_integer(x) (is_small(x) || is_big(x))
+#define is_not_integer(x) (!is_integer(x))
+#define is_number(x) (is_integer(x) || is_float(x))
+
+#define SMALL_MINUS_ONE make_small(-1)
+#define SMALL_ZERO make_small(0)
+#define SMALL_ONE make_small(1)
+
+#define ENULL 0
+
+/* on some architectures CP contains labels which are not aligned */
+#ifdef NOT_ALIGNED
+#error "fix yer arch, like"
+#endif
+
+#define _unchecked_make_cp(x) ((Eterm)(x))
+_ET_DECLARE_CHECKED(Eterm,make_cp,Uint*);
+#define make_cp(x) _ET_APPLY(make_cp,(x))
+
+#define is_not_CP(x) ((x) & _CPMASK)
+#define is_CP(x) (!is_not_CP(x))
+
+#define _unchecked_cp_val(x) ((Uint*)(x))
+_ET_DECLARE_CHECKED(Uint*,cp_val,Eterm);
+#define cp_val(x) _ET_APPLY(cp_val,(x))
+
+#define make_catch(x) (((x) << _TAG_IMMED2_SIZE) | _TAG_IMMED2_CATCH)
+#define is_catch(x) (((x) & _TAG_IMMED2_MASK) == _TAG_IMMED2_CATCH)
+#define is_not_catch(x) (!is_catch(x))
+#define _unchecked_catch_val(x) ((x) >> _TAG_IMMED2_SIZE)
+_ET_DECLARE_CHECKED(Uint,catch_val,Eterm);
+#define catch_val(x) _ET_APPLY(catch_val,(x))
+
+#define make_blank(X) ((X) = NIL)
+
+/*
+ * Overloaded tags.
+ *
+ * SMALL = 15
+ * ATOM/NIL=7
+ *
+ * Note that the two least significant bits in SMALL/ATOM/NIL always are 3;
+ * thus, we can distinguish register from literals by looking at only these
+ * two bits.
+ */
+
+#define X_REG_DEF 0
+#define Y_REG_DEF 1
+#define R_REG_DEF 2
+
+#define beam_reg_tag(x) ((x) & 3)
+
+#define make_rreg() R_REG_DEF
+#define make_xreg(ix) (((ix) * sizeof(Eterm)) | X_REG_DEF)
+#define make_yreg(ix) (((ix) * sizeof(Eterm)) | Y_REG_DEF)
+
+#define _is_xreg(x) (beam_reg_tag(x) == X_REG_DEF)
+#define _is_yreg(x) (beam_reg_tag(x) == Y_REG_DEF)
+
+#define _unchecked_x_reg_offset(R) ((R) - X_REG_DEF)
+_ET_DECLARE_CHECKED(Uint,x_reg_offset,Uint);
+#define x_reg_offset(R) _ET_APPLY(x_reg_offset,(R))
+
+#define _unchecked_y_reg_offset(R) ((R) - Y_REG_DEF)
+_ET_DECLARE_CHECKED(Uint,y_reg_offset,Uint);
+#define y_reg_offset(R) _ET_APPLY(y_reg_offset,(R))
+
+#define reg_index(R) ((R) / sizeof(Eterm))
+
+#define _unchecked_x_reg_index(R) ((R) >> 2)
+_ET_DECLARE_CHECKED(Uint,x_reg_index,Uint);
+#define x_reg_index(R) _ET_APPLY(x_reg_index,(R))
+
+#define _unchecked_y_reg_index(R) ((R) >> 2)
+_ET_DECLARE_CHECKED(Uint,y_reg_index,Uint);
+#define y_reg_index(R) _ET_APPLY(y_reg_index,(R))
+
+/*
+ * Backwards compatibility definitions:
+ * - #define virtal *_DEF constants with values that fit term order:
+ * number < atom < ref < fun < port < pid < tuple < nil < cons < binary
+ * - tag_val_def() function generates virtual _DEF tag
+ * - not_eq_tags() and NUMBER_CODE() defined in terms
+ * of the tag_val_def() function
+ */
+
+#define BINARY_DEF 0x0
+#define LIST_DEF 0x1
+#define NIL_DEF 0x2
+#define TUPLE_DEF 0x3
+#define PID_DEF 0x4
+#define EXTERNAL_PID_DEF 0x5
+#define PORT_DEF 0x6
+#define EXTERNAL_PORT_DEF 0x7
+#define EXPORT_DEF 0x8
+#define FUN_DEF 0x9
+#define REF_DEF 0xa
+#define EXTERNAL_REF_DEF 0xb
+#define ATOM_DEF 0xc
+#define FLOAT_DEF 0xd
+#define BIG_DEF 0xe
+#define SMALL_DEF 0xf
+
+#if ET_DEBUG
+extern unsigned tag_val_def_debug(Eterm, const char*, unsigned);
+#define tag_val_def(x) tag_val_def_debug((x),__FILE__,__LINE__)
+#else
+extern unsigned tag_val_def(Eterm);
+#endif
+#define not_eq_tags(X,Y) (tag_val_def((X)) ^ tag_val_def((Y)))
+
+#define NUMBER_CODE(x,y) ((tag_val_def(x) << 4) | tag_val_def(y))
+#define _NUMBER_CODE(TX,TY) ((TX << 4) | TY)
+#define SMALL_SMALL _NUMBER_CODE(SMALL_DEF,SMALL_DEF)
+#define SMALL_BIG _NUMBER_CODE(SMALL_DEF,BIG_DEF)
+#define SMALL_FLOAT _NUMBER_CODE(SMALL_DEF,FLOAT_DEF)
+#define BIG_SMALL _NUMBER_CODE(BIG_DEF,SMALL_DEF)
+#define BIG_BIG _NUMBER_CODE(BIG_DEF,BIG_DEF)
+#define BIG_FLOAT _NUMBER_CODE(BIG_DEF,FLOAT_DEF)
+#define FLOAT_SMALL _NUMBER_CODE(FLOAT_DEF,SMALL_DEF)
+#define FLOAT_BIG _NUMBER_CODE(FLOAT_DEF,BIG_DEF)
+#define FLOAT_FLOAT _NUMBER_CODE(FLOAT_DEF,FLOAT_DEF)
+
+#endif /* __ERL_TERM_H */
+