/* * %CopyrightBegin% * * Copyright Ericsson AB 1996-2018. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * %CopyrightEnd% */ #ifndef __ERL_VM_H__ #define __ERL_VM_H__ /* FORCE_HEAP_FRAGS: * Debug provocation to make HAlloc always create heap fragments (if allowed) * even if there is room on heap. */ /* #define FORCE_HEAP_FRAGS */ #if defined(DEBUG) && !defined(CHECK_FOR_HOLES) && !defined(__WIN32__) # define CHECK_FOR_HOLES #endif #define BEAM 1 #define EMULATOR "BEAM" #define SEQ_TRACE 1 #define CONTEXT_REDS 4000 /* Swap process out after this number */ #define MAX_ARG 255 /* Max number of arguments allowed */ #define MAX_REG 1024 /* Max number of x(N) registers used */ /* * The new trapping length/1 implementation need 3 extra registers in the * register array. */ #define ERTS_X_REGS_ALLOCATED (MAX_REG+3) #define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */ #define VH_DEFAULT_SIZE 32768 /* default virtual (bin) heap min size (words) */ #define H_DEFAULT_MAX_SIZE 0 /* default max heap size is off */ #define CP_SIZE 1 #define ErtsHAllocLockCheck(P) \ ERTS_LC_ASSERT(erts_dbg_check_halloc_lock((P))) #ifdef DEBUG /* * Debug HAlloc that initialize all memory to bad things. * * To get information about where memory is allocated, insert the two * lines below directly after the memset line and use the flag +va. * VERBOSE(DEBUG_ALLOCATION,("HAlloc @ 0x%08lx (%d) %s:%d\n", \ (unsigned long)HEAP_TOP(p),(sz),__FILE__,__LINE__)), \ */ # ifdef CHECK_FOR_HOLES Eterm* erts_set_hole_marker(Eterm* ptr, Uint sz); # define INIT_HEAP_MEM(p,sz) erts_set_hole_marker(p, (sz)) # else # define INIT_HEAP_MEM(p,sz) sys_memset(p,0x01,(sz)*sizeof(Eterm*)) # endif #else # define INIT_HEAP_MEM(p,sz) ((void)0) #endif /* DEBUG */ #ifdef FORCE_HEAP_FRAGS # define IS_FORCE_HEAP_FRAGS 1 #else # define IS_FORCE_HEAP_FRAGS 0 #endif /* * Allocate heap memory, first on the ordinary heap; * failing that, in a heap fragment. */ #define HAllocX(p, sz, xtra) \ (ASSERT((sz) >= 0), \ ErtsHAllocLockCheck(p), \ (IS_FORCE_HEAP_FRAGS || (((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \ ? erts_heap_alloc((p),(sz),(xtra)) \ : (INIT_HEAP_MEM(HEAP_TOP(p),sz), \ HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz)))) #define HAlloc(P, SZ) HAllocX(P,SZ,0) #define HRelease(p, endp, ptr) \ if ((ptr) == (endp)) { \ ; \ } else if (HEAP_START(p) <= (ptr) && (ptr) < HEAP_TOP(p)) { \ ASSERT(HEAP_TOP(p) == (endp)); \ HEAP_TOP(p) = (ptr); \ } else { \ ASSERT(MBUF(p)->mem + MBUF(p)->used_size == (endp)); \ erts_heap_frag_shrink(p, ptr); \ } #define HeapWordsLeft(p) (HEAP_LIMIT(p) - HEAP_TOP(p)) #if defined(DEBUG) || defined(CHECK_FOR_HOLES) /* * ERTS_HOLE_MARKER must *not* be mistaken for a valid term * on the heap... */ # ifdef ARCH_64 # define ERTS_HOLE_MARKER \ make_catch(UWORD_CONSTANT(0xdeadbeaf00000000) >> _TAG_IMMED2_SIZE) /* Will (at the time of writing) appear as 0xdeadbeaf0000001b */ # else # define ERTS_HOLE_MARKER \ make_catch(UWORD_CONSTANT(0xdead0000) >> _TAG_IMMED2_SIZE) /* Will (at the time of writing) appear as 0xdead001b */ # endif #endif /* * Allocate heap memory on the ordinary heap, NEVER in a heap * segment. The caller must ensure that there is enough words * left on the heap before calling HeapOnlyAlloc() (for instance, * by testing HeapWordsLeft() and calling the garbage collector * if not enough). */ #ifdef CHECK_FOR_HOLES # define HeapOnlyAlloc(p, sz) \ (ASSERT((sz) >= 0), \ (ASSERT(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \ (erts_set_hole_marker(HEAP_TOP(p), (sz)), \ (HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))) #else # define HeapOnlyAlloc(p, sz) \ (ASSERT((sz) >= 0), \ (ASSERT(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \ (HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz)))) #endif /* * Always allocate in a heap fragment, never on the heap. */ #if defined(VALGRIND) /* Running under valgrind, allocate exactly as much as needed.*/ # define HeapFragOnlyAlloc(p, sz) \ (ASSERT((sz) >= 0), \ ErtsHAllocLockCheck(p), \ erts_heap_alloc((p),(sz),0)) #else # define HeapFragOnlyAlloc(p, sz) \ (ASSERT((sz) >= 0), \ ErtsHAllocLockCheck(p), \ erts_heap_alloc((p),(sz),512)) #endif /* * Description for each instruction (defined here because the name and * count fields are interesting outside the emulator proper). */ typedef struct op_entry { char* name; /* Name of instruction. */ Uint32 mask[3]; /* Signature mask. */ unsigned involves_r; /* Needs special attention when matching. */ int sz; /* Number of loaded words. */ int adjust; /* Adjustment for start of instruction. */ char* pack; /* Instructions for packing engine. */ char* sign; /* Signature string. */ } OpEntry; extern const OpEntry opc[]; /* Description of all instructions. */ extern const int num_instructions; /* Number of instruction in opc[]. */ extern Uint erts_instr_count[]; /* some constants for various table sizes etc */ #define ATOM_TEXT_SIZE 32768 /* Increment for allocating atom text space */ #define ITIME 100 /* Number of milliseconds per clock tick */ #define MAX_PORT_LINK 8 /* Maximum number of links to a port */ extern int H_MIN_SIZE; /* minimum (heap + stack) */ extern int BIN_VH_MIN_SIZE; /* minimum virtual (bin) heap */ extern int H_MAX_SIZE; /* maximum (heap + stack) */ extern int H_MAX_FLAGS; /* maximum heap flags */ extern int erts_atom_table_size;/* Atom table size */ extern int erts_pd_initial_size;/* Initial Process dictionary table size */ #define ORIG_CREATION 0 /* macros for extracting bytes from uint16's */ #define hi_byte(a) ((a) >> 8) #define lo_byte(a) ((a) & 255) /* macros for combining bytes */ #define make_16(x, y) (((x) << 8) | (y)) #define make_24(x,y,z) (((x) << 16) | ((y) << 8) | (z)) #define make_32(x3,x2,x1,x0) (((x3)<<24) | ((x2)<<16) | ((x1)<<8) | (x0)) #define make_signed_24(x,y,z) ((sint32) (((x) << 24) | ((y) << 16) | ((z) << 8)) >> 8) #define make_signed_32(x3,x2,x1,x0) ((sint32) (((x3) << 24) | ((x2) << 16) | ((x1) << 8) | (x0))) #include "erl_term.h" #if defined(NO_JUMP_TABLE) # define BeamOpsAreInitialized() (1) # define BeamOpCodeAddr(OpCode) ((BeamInstr)(OpCode)) #else extern void** beam_ops; # define BeamOpsAreInitialized() (beam_ops != 0) # define BeamOpCodeAddr(OpCode) ((BeamInstr)beam_ops[(OpCode)]) #endif #if defined(ARCH_64) && defined(CODE_MODEL_SMALL) # define BeamCodeAddr(InstrWord) ((BeamInstr)(Uint32)(InstrWord)) # define BeamSetCodeAddr(InstrWord, Addr) (((InstrWord) & ~((1ull << 32)-1)) | (Addr)) # define BeamExtraData(InstrWord) ((InstrWord) >> 32) #else # define BeamCodeAddr(InstrWord) ((BeamInstr)(InstrWord)) # define BeamSetCodeAddr(InstrWord, Addr) (Addr) #endif #define BeamIsOpCode(InstrWord, OpCode) (BeamCodeAddr(InstrWord) == BeamOpCodeAddr(OpCode)) #endif /* __ERL_VM_H__ */