📄 erl_term.h
字号:
/* ``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 via the world wide web 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. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ */#ifndef __ERL_TERM_H#define __ERL_TERM_Hstruct 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))#define is_not_both_immed(x,y) is_not_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) (((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) (((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))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -