1 /* 2 * Heap compiled function (ECMAScript function) representation. 3 * 4 * There is a single data buffer containing the ECMAScript function's 5 * bytecode, constants, and inner functions. 6 */ 7 8 #if !defined(DUK_HCOMPFUNC_H_INCLUDED) 9 #define DUK_HCOMPFUNC_H_INCLUDED 10 11 /* 12 * Field accessor macros 13 */ 14 15 /* XXX: casts could be improved, especially for GET/SET DATA */ 16 17 #if defined(DUK_USE_HEAPPTR16) 18 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \ 19 ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16)) 20 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \ 21 (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ 22 } while (0) 23 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h) \ 24 ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16))) 25 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \ 26 (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ 27 } while (0) 28 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) \ 29 ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16))) 30 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \ 31 (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ 32 } while (0) 33 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h) \ 34 ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16))) 35 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \ 36 (h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ 37 } while (0) 38 #define DUK_HCOMPFUNC_GET_VARENV(heap,h) \ 39 ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16))) 40 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \ 41 (h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ 42 } while (0) 43 #else 44 #define DUK_HCOMPFUNC_GET_DATA(heap,h) ((duk_hbuffer_fixed *) (void *) (h)->data) 45 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \ 46 (h)->data = (duk_hbuffer *) (v); \ 47 } while (0) 48 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h) ((h)->funcs) 49 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \ 50 (h)->funcs = (v); \ 51 } while (0) 52 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) ((h)->bytecode) 53 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \ 54 (h)->bytecode = (v); \ 55 } while (0) 56 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h) ((h)->lex_env) 57 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \ 58 (h)->lex_env = (v); \ 59 } while (0) 60 #define DUK_HCOMPFUNC_GET_VARENV(heap,h) ((h)->var_env) 61 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \ 62 (h)->var_env = (v); \ 63 } while (0) 64 #endif 65 66 /* 67 * Accessor macros for function specific data areas 68 */ 69 70 /* Note: assumes 'data' is always a fixed buffer */ 71 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h) \ 72 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) 73 74 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h) \ 75 ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h))) 76 77 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h) \ 78 DUK_HCOMPFUNC_GET_FUNCS((heap), (h)) 79 80 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h) \ 81 DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)) 82 83 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h) \ 84 ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h))) 85 86 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h) \ 87 ((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))) 88 89 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */ 90 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h) \ 91 ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \ 92 DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h)))) 93 94 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h) \ 95 ( \ 96 (duk_size_t) \ 97 ( \ 98 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \ 99 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \ 100 ) \ 101 ) 102 103 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h) \ 104 ( \ 105 (duk_size_t) \ 106 ( \ 107 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \ 108 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \ 109 ) \ 110 ) 111 112 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h) \ 113 ( \ 114 (duk_size_t) \ 115 ( \ 116 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \ 117 ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \ 118 ) \ 119 ) 120 121 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h) \ 122 ((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval))) 123 124 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h) \ 125 ((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *))) 126 127 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h) \ 128 ((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t))) 129 130 /* 131 * Validity assert 132 */ 133 134 #if defined(DUK_USE_ASSERTIONS) 135 DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h); 136 #define DUK_HCOMPFUNC_ASSERT_VALID(h) do { duk_hcompfunc_assert_valid((h)); } while (0) 137 #else 138 #define DUK_HCOMPFUNC_ASSERT_VALID(h) do {} while (0) 139 #endif 140 141 /* 142 * Main struct 143 */ 144 145 struct duk_hcompfunc { 146 /* shared object part */ 147 duk_hobject obj; 148 149 /* 150 * Pointers to function data area for faster access. Function 151 * data is a buffer shared between all closures of the same 152 * "template" function. The data buffer is always fixed (non- 153 * dynamic, hence stable), with a layout as follows: 154 * 155 * constants (duk_tval) 156 * inner functions (duk_hobject *) 157 * bytecode (duk_instr_t) 158 * 159 * Note: bytecode end address can be computed from 'data' buffer 160 * size. It is not strictly necessary functionally, assuming 161 * bytecode never jumps outside its allocated area. However, 162 * it's a safety/robustness feature for avoiding the chance of 163 * executing random data as bytecode due to a compiler error. 164 * 165 * Note: values in the data buffer must be incref'd (they will 166 * be decref'd on release) for every compiledfunction referring 167 * to the 'data' element. 168 */ 169 170 /* Data area, fixed allocation, stable data ptrs. */ 171 #if defined(DUK_USE_HEAPPTR16) 172 duk_uint16_t data16; 173 #else 174 duk_hbuffer *data; 175 #endif 176 177 /* No need for constants pointer (= same as data). 178 * 179 * When using 16-bit packing alignment to 4 is nice. 'funcs' will be 180 * 4-byte aligned because 'constants' are duk_tvals. For now the 181 * inner function pointers are not compressed, so that 'bytecode' will 182 * also be 4-byte aligned. 183 */ 184 #if defined(DUK_USE_HEAPPTR16) 185 duk_uint16_t funcs16; 186 duk_uint16_t bytecode16; 187 #else 188 duk_hobject **funcs; 189 duk_instr_t *bytecode; 190 #endif 191 192 /* Lexenv: lexical environment of closure, NULL for templates. 193 * Varenv: variable environment of closure, NULL for templates. 194 */ 195 #if defined(DUK_USE_HEAPPTR16) 196 duk_uint16_t lex_env16; 197 duk_uint16_t var_env16; 198 #else 199 duk_hobject *lex_env; 200 duk_hobject *var_env; 201 #endif 202 203 /* 204 * 'nregs' registers are allocated on function entry, at most 'nargs' 205 * are initialized to arguments, and the rest to undefined. Arguments 206 * above 'nregs' are not mapped to registers. All registers in the 207 * active stack range must be initialized because they are GC reachable. 208 * 'nargs' is needed so that if the function is given more than 'nargs' 209 * arguments, the additional arguments do not 'clobber' registers 210 * beyond 'nregs' which must be consistently initialized to undefined. 211 * 212 * Usually there is no need to know which registers are mapped to 213 * local variables. Registers may be allocated to variable in any 214 * way (even including gaps). However, a register-variable mapping 215 * must be the same for the duration of the function execution and 216 * the register cannot be used for anything else. 217 * 218 * When looking up variables by name, the '_Varmap' map is used. 219 * When an activation closes, registers mapped to arguments are 220 * copied into the environment record based on the same map. The 221 * reverse map (from register to variable) is not currently needed 222 * at run time, except for debugging, so it is not maintained. 223 */ 224 225 duk_uint16_t nregs; /* regs to allocate */ 226 duk_uint16_t nargs; /* number of arguments allocated to regs */ 227 228 /* 229 * Additional control information is placed into the object itself 230 * as internal properties to avoid unnecessary fields for the 231 * majority of functions. The compiler tries to omit internal 232 * control fields when possible. 233 * 234 * Function templates: 235 * 236 * { 237 * name: "func", // declaration, named function expressions 238 * fileName: <debug info for creating nice errors> 239 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 }, 240 * _Formals: [ "arg1", "arg2" ], 241 * _Source: "function func(arg1, arg2) { ... }", 242 * _Pc2line: <debug info for pc-to-line mapping>, 243 * } 244 * 245 * Function instances: 246 * 247 * { 248 * length: 2, 249 * prototype: { constructor: <func> }, 250 * caller: <thrower>, 251 * arguments: <thrower>, 252 * name: "func", // declaration, named function expressions 253 * fileName: <debug info for creating nice errors> 254 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 }, 255 * _Formals: [ "arg1", "arg2" ], 256 * _Source: "function func(arg1, arg2) { ... }", 257 * _Pc2line: <debug info for pc-to-line mapping>, 258 * } 259 * 260 * More detailed description of these properties can be found 261 * in the documentation. 262 */ 263 264 #if defined(DUK_USE_DEBUGGER_SUPPORT) 265 /* Line number range for function. Needed during debugging to 266 * determine active breakpoints. 267 */ 268 duk_uint32_t start_line; 269 duk_uint32_t end_line; 270 #endif 271 }; 272 273 #endif /* DUK_HCOMPFUNC_H_INCLUDED */ 274