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