1 /* 2 * %CopyrightBegin% 3 * 4 * Copyright Ericsson AB 1996-2020. 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_VM_H__ 22 #define __ERL_VM_H__ 23 24 /* FORCE_HEAP_FRAGS: 25 * Debug provocation to make HAlloc always create heap fragments (if allowed) 26 * even if there is room on heap. 27 */ 28 /* #define FORCE_HEAP_FRAGS */ 29 30 31 #if defined(DEBUG) && !defined(CHECK_FOR_HOLES) && !defined(__WIN32__) 32 # define CHECK_FOR_HOLES 33 #endif 34 35 #define BEAM 1 36 #define EMULATOR "BEAM" 37 #define SEQ_TRACE 1 38 39 #define CONTEXT_REDS 4000 /* Swap process out after this number */ 40 #define MAX_ARG 255 /* Max number of arguments allowed */ 41 #define MAX_REG 1024 /* Max number of x(N) registers used */ 42 43 /* 44 * The new trapping length/1 implementation need 3 extra registers in the 45 * register array. 46 */ 47 #define ERTS_X_REGS_ALLOCATED (MAX_REG+3) 48 49 #define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */ 50 #define VH_DEFAULT_SIZE 32768 /* default virtual (bin) heap min size (words) */ 51 #define H_DEFAULT_MAX_SIZE 0 /* default max heap size is off */ 52 53 #define CP_SIZE 1 54 55 #define ErtsHAllocLockCheck(P) \ 56 ERTS_LC_ASSERT(erts_dbg_check_halloc_lock((P))) 57 58 59 #ifdef DEBUG 60 /* 61 * Debug HAlloc that initialize all memory to bad things. 62 * 63 * To get information about where memory is allocated, insert the two 64 * lines below directly after the memset line and use the flag +va. 65 * 66 VERBOSE(DEBUG_ALLOCATION,("HAlloc @ 0x%08lx (%d) %s:%d\n", \ 67 (unsigned long)HEAP_TOP(p),(sz),__FILE__,__LINE__)), \ 68 */ 69 # ifdef CHECK_FOR_HOLES 70 Eterm* erts_set_hole_marker(Eterm* ptr, Uint sz); 71 # define INIT_HEAP_MEM(p,sz) erts_set_hole_marker(p, (sz)) 72 # else 73 # define INIT_HEAP_MEM(p,sz) sys_memset(p,0x01,(sz)*sizeof(Eterm*)) 74 # endif 75 #else 76 # define INIT_HEAP_MEM(p,sz) ((void)0) 77 #endif /* DEBUG */ 78 79 80 #ifdef FORCE_HEAP_FRAGS 81 # define IS_FORCE_HEAP_FRAGS 1 82 #else 83 # define IS_FORCE_HEAP_FRAGS 0 84 #endif 85 86 /* 87 * Allocate heap memory, first on the ordinary heap; 88 * failing that, in a heap fragment. 89 */ 90 #define HAllocX(p, sz, xtra) \ 91 (ASSERT((sz) >= 0), \ 92 ErtsHAllocLockCheck(p), \ 93 (IS_FORCE_HEAP_FRAGS || (((HEAP_LIMIT(p) - HEAP_TOP(p)) < (sz))) \ 94 ? erts_heap_alloc((p),(sz),(xtra)) \ 95 : (INIT_HEAP_MEM(HEAP_TOP(p),sz), \ 96 HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz)))) 97 98 #define HAlloc(P, SZ) HAllocX(P,SZ,0) 99 100 #define HRelease(p, endp, ptr) \ 101 if ((ptr) == (endp)) { \ 102 ; \ 103 } else if (HEAP_START(p) <= (ptr) && (ptr) < HEAP_TOP(p)) { \ 104 ASSERT(HEAP_TOP(p) == (endp)); \ 105 HEAP_TOP(p) = (ptr); \ 106 } else { \ 107 ASSERT(MBUF(p)->mem + MBUF(p)->used_size == (endp)); \ 108 erts_heap_frag_shrink(p, ptr); \ 109 } 110 111 #define HeapWordsLeft(p) (HEAP_LIMIT(p) - HEAP_TOP(p)) 112 113 #if defined(DEBUG) || defined(CHECK_FOR_HOLES) 114 115 /* 116 * ERTS_HOLE_MARKER must *not* be mistaken for a valid term 117 * on the heap... 118 */ 119 # ifdef ARCH_64 120 # define ERTS_HOLE_MARKER \ 121 make_catch(UWORD_CONSTANT(0xdeadbeaf00000000) >> _TAG_IMMED2_SIZE) 122 /* Will (at the time of writing) appear as 0xdeadbeaf0000001b */ 123 # else 124 # define ERTS_HOLE_MARKER \ 125 make_catch(UWORD_CONSTANT(0xdead0000) >> _TAG_IMMED2_SIZE) 126 /* Will (at the time of writing) appear as 0xdead001b */ 127 # endif 128 #endif 129 130 /* 131 * Allocate heap memory on the ordinary heap, NEVER in a heap 132 * segment. The caller must ensure that there is enough words 133 * left on the heap before calling HeapOnlyAlloc() (for instance, 134 * by testing HeapWordsLeft() and calling the garbage collector 135 * if not enough). 136 */ 137 #ifdef CHECK_FOR_HOLES 138 # define HeapOnlyAlloc(p, sz) \ 139 (ASSERT((sz) >= 0), \ 140 (ASSERT(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \ 141 (erts_set_hole_marker(HEAP_TOP(p), (sz)), \ 142 (HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz))))) 143 #else 144 # define HeapOnlyAlloc(p, sz) \ 145 (ASSERT((sz) >= 0), \ 146 (ASSERT(((HEAP_LIMIT(p) - HEAP_TOP(p)) >= (sz))), \ 147 (HEAP_TOP(p) = HEAP_TOP(p) + (sz), HEAP_TOP(p) - (sz)))) 148 #endif 149 150 /* 151 * Always allocate in a heap fragment, never on the heap. 152 */ 153 #if defined(VALGRIND) 154 /* Running under valgrind, allocate exactly as much as needed.*/ 155 # define HeapFragOnlyAlloc(p, sz) \ 156 (ASSERT((sz) >= 0), \ 157 ErtsHAllocLockCheck(p), \ 158 erts_heap_alloc((p),(sz),0)) 159 #else 160 # define HeapFragOnlyAlloc(p, sz) \ 161 (ASSERT((sz) >= 0), \ 162 ErtsHAllocLockCheck(p), \ 163 erts_heap_alloc((p),(sz),512)) 164 #endif 165 166 /* 167 * Description for each instruction (defined here because the name and 168 * count fields are interesting outside the emulator proper). 169 */ 170 171 typedef struct op_entry { 172 char* name; /* Name of instruction. */ 173 Uint32 mask[3]; /* Signature mask. */ 174 unsigned involves_r; /* Needs special attention when matching. */ 175 int sz; /* Number of loaded words. */ 176 int adjust; /* Adjustment for start of instruction. */ 177 char* pack; /* Instructions for packing engine. */ 178 char* sign; /* Signature string. */ 179 } OpEntry; 180 181 extern const OpEntry opc[]; /* Description of all instructions. */ 182 extern const int num_instructions; /* Number of instruction in opc[]. */ 183 184 extern Uint erts_instr_count[]; 185 186 /* some constants for various table sizes etc */ 187 188 #define ATOM_TEXT_SIZE 32768 /* Increment for allocating atom text space */ 189 190 #define ITIME 100 /* Number of milliseconds per clock tick */ 191 #define MAX_PORT_LINK 8 /* Maximum number of links to a port */ 192 193 extern int H_MIN_SIZE; /* minimum (heap + stack) */ 194 extern int BIN_VH_MIN_SIZE; /* minimum virtual (bin) heap */ 195 extern int H_MAX_SIZE; /* maximum (heap + stack) */ 196 extern int H_MAX_FLAGS; /* maximum heap flags */ 197 198 extern int erts_atom_table_size;/* Atom table size */ 199 extern int erts_pd_initial_size;/* Initial Process dictionary table size */ 200 201 #define ORIG_CREATION 0 202 203 /* macros for extracting bytes from uint16's */ 204 205 #define hi_byte(a) ((a) >> 8) 206 #define lo_byte(a) ((a) & 255) 207 208 /* macros for combining bytes */ 209 210 #define make_16(x, y) (((x) << 8) | (y)) 211 #define make_24(x,y,z) (((x) << 16) | ((y) << 8) | (z)) 212 #define make_32(x3,x2,x1,x0) (((x3)<<24) | ((x2)<<16) | ((x1)<<8) | (x0)) 213 214 #define make_signed_24(x,y,z) ((sint32) (((x) << 24) | ((y) << 16) | ((z) << 8)) >> 8) 215 #define make_signed_32(x3,x2,x1,x0) ((sint32) (((x3) << 24) | ((x2) << 16) | ((x1) << 8) | (x0))) 216 217 #include "erl_term.h" 218 219 #if defined(NO_JUMP_TABLE) 220 # define BeamOpsAreInitialized() (1) 221 # define BeamOpCodeAddr(OpCode) ((BeamInstr)(OpCode)) 222 #else 223 extern void** beam_ops; 224 # define BeamOpsAreInitialized() (beam_ops != 0) 225 # define BeamOpCodeAddr(OpCode) ((BeamInstr)beam_ops[(OpCode)]) 226 #endif 227 228 #if defined(ARCH_64) && defined(CODE_MODEL_SMALL) 229 # define BeamCodeAddr(InstrWord) ((BeamInstr)(Uint32)(InstrWord)) 230 # define BeamSetCodeAddr(InstrWord, Addr) (((InstrWord) & ~((1ull << 32)-1)) | (Addr)) 231 # define BeamExtraData(InstrWord) ((InstrWord) >> 32) 232 #else 233 # define BeamCodeAddr(InstrWord) ((BeamInstr)(InstrWord)) 234 # define BeamSetCodeAddr(InstrWord, Addr) (Addr) 235 #endif 236 237 #define BeamIsOpCode(InstrWord, OpCode) (BeamCodeAddr(InstrWord) == BeamOpCodeAddr(OpCode)) 238 239 #endif /* __ERL_VM_H__ */ 240