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