]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 */ |