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