Initial import
This commit is contained in:
273
third_party/duktape/duk_hcompfunc.h
vendored
Normal file
273
third_party/duktape/duk_hcompfunc.h
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Heap compiled function (ECMAScript function) representation.
|
||||
*
|
||||
* There is a single data buffer containing the ECMAScript function's
|
||||
* bytecode, constants, and inner functions.
|
||||
*/
|
||||
|
||||
#if !defined(DUK_HCOMPFUNC_H_INCLUDED)
|
||||
#define DUK_HCOMPFUNC_H_INCLUDED
|
||||
|
||||
/*
|
||||
* Field accessor macros
|
||||
*/
|
||||
|
||||
/* XXX: casts could be improved, especially for GET/SET DATA */
|
||||
|
||||
#if defined(DUK_USE_HEAPPTR16)
|
||||
#define DUK_HCOMPFUNC_GET_DATA(heap,h) \
|
||||
((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
|
||||
#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
|
||||
(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_FUNCS(heap,h) \
|
||||
((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
|
||||
#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \
|
||||
(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) \
|
||||
((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
|
||||
#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \
|
||||
(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_LEXENV(heap,h) \
|
||||
((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
|
||||
#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \
|
||||
(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_VARENV(heap,h) \
|
||||
((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
|
||||
#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \
|
||||
(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DUK_HCOMPFUNC_GET_DATA(heap,h) ((duk_hbuffer_fixed *) (void *) (h)->data)
|
||||
#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
|
||||
(h)->data = (duk_hbuffer *) (v); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_FUNCS(heap,h) ((h)->funcs)
|
||||
#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \
|
||||
(h)->funcs = (v); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) ((h)->bytecode)
|
||||
#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \
|
||||
(h)->bytecode = (v); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_LEXENV(heap,h) ((h)->lex_env)
|
||||
#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \
|
||||
(h)->lex_env = (v); \
|
||||
} while (0)
|
||||
#define DUK_HCOMPFUNC_GET_VARENV(heap,h) ((h)->var_env)
|
||||
#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \
|
||||
(h)->var_env = (v); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Accessor macros for function specific data areas
|
||||
*/
|
||||
|
||||
/* Note: assumes 'data' is always a fixed buffer */
|
||||
#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h) \
|
||||
DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h) \
|
||||
((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h) \
|
||||
DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h) \
|
||||
DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h) \
|
||||
((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h) \
|
||||
((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
|
||||
|
||||
/* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
|
||||
#define DUK_HCOMPFUNC_GET_CODE_END(heap,h) \
|
||||
((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
|
||||
DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h) \
|
||||
( \
|
||||
(duk_size_t) \
|
||||
( \
|
||||
((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
|
||||
((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h) \
|
||||
( \
|
||||
(duk_size_t) \
|
||||
( \
|
||||
((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
|
||||
((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h) \
|
||||
( \
|
||||
(duk_size_t) \
|
||||
( \
|
||||
((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
|
||||
((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h) \
|
||||
((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h) \
|
||||
((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
|
||||
|
||||
#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h) \
|
||||
((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
|
||||
|
||||
/*
|
||||
* Validity assert
|
||||
*/
|
||||
|
||||
#if defined(DUK_USE_ASSERTIONS)
|
||||
DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
|
||||
#define DUK_HCOMPFUNC_ASSERT_VALID(h) do { duk_hcompfunc_assert_valid((h)); } while (0)
|
||||
#else
|
||||
#define DUK_HCOMPFUNC_ASSERT_VALID(h) do {} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Main struct
|
||||
*/
|
||||
|
||||
struct duk_hcompfunc {
|
||||
/* shared object part */
|
||||
duk_hobject obj;
|
||||
|
||||
/*
|
||||
* Pointers to function data area for faster access. Function
|
||||
* data is a buffer shared between all closures of the same
|
||||
* "template" function. The data buffer is always fixed (non-
|
||||
* dynamic, hence stable), with a layout as follows:
|
||||
*
|
||||
* constants (duk_tval)
|
||||
* inner functions (duk_hobject *)
|
||||
* bytecode (duk_instr_t)
|
||||
*
|
||||
* Note: bytecode end address can be computed from 'data' buffer
|
||||
* size. It is not strictly necessary functionally, assuming
|
||||
* bytecode never jumps outside its allocated area. However,
|
||||
* it's a safety/robustness feature for avoiding the chance of
|
||||
* executing random data as bytecode due to a compiler error.
|
||||
*
|
||||
* Note: values in the data buffer must be incref'd (they will
|
||||
* be decref'd on release) for every compiledfunction referring
|
||||
* to the 'data' element.
|
||||
*/
|
||||
|
||||
/* Data area, fixed allocation, stable data ptrs. */
|
||||
#if defined(DUK_USE_HEAPPTR16)
|
||||
duk_uint16_t data16;
|
||||
#else
|
||||
duk_hbuffer *data;
|
||||
#endif
|
||||
|
||||
/* No need for constants pointer (= same as data).
|
||||
*
|
||||
* When using 16-bit packing alignment to 4 is nice. 'funcs' will be
|
||||
* 4-byte aligned because 'constants' are duk_tvals. For now the
|
||||
* inner function pointers are not compressed, so that 'bytecode' will
|
||||
* also be 4-byte aligned.
|
||||
*/
|
||||
#if defined(DUK_USE_HEAPPTR16)
|
||||
duk_uint16_t funcs16;
|
||||
duk_uint16_t bytecode16;
|
||||
#else
|
||||
duk_hobject **funcs;
|
||||
duk_instr_t *bytecode;
|
||||
#endif
|
||||
|
||||
/* Lexenv: lexical environment of closure, NULL for templates.
|
||||
* Varenv: variable environment of closure, NULL for templates.
|
||||
*/
|
||||
#if defined(DUK_USE_HEAPPTR16)
|
||||
duk_uint16_t lex_env16;
|
||||
duk_uint16_t var_env16;
|
||||
#else
|
||||
duk_hobject *lex_env;
|
||||
duk_hobject *var_env;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 'nregs' registers are allocated on function entry, at most 'nargs'
|
||||
* are initialized to arguments, and the rest to undefined. Arguments
|
||||
* above 'nregs' are not mapped to registers. All registers in the
|
||||
* active stack range must be initialized because they are GC reachable.
|
||||
* 'nargs' is needed so that if the function is given more than 'nargs'
|
||||
* arguments, the additional arguments do not 'clobber' registers
|
||||
* beyond 'nregs' which must be consistently initialized to undefined.
|
||||
*
|
||||
* Usually there is no need to know which registers are mapped to
|
||||
* local variables. Registers may be allocated to variable in any
|
||||
* way (even including gaps). However, a register-variable mapping
|
||||
* must be the same for the duration of the function execution and
|
||||
* the register cannot be used for anything else.
|
||||
*
|
||||
* When looking up variables by name, the '_Varmap' map is used.
|
||||
* When an activation closes, registers mapped to arguments are
|
||||
* copied into the environment record based on the same map. The
|
||||
* reverse map (from register to variable) is not currently needed
|
||||
* at run time, except for debugging, so it is not maintained.
|
||||
*/
|
||||
|
||||
duk_uint16_t nregs; /* regs to allocate */
|
||||
duk_uint16_t nargs; /* number of arguments allocated to regs */
|
||||
|
||||
/*
|
||||
* Additional control information is placed into the object itself
|
||||
* as internal properties to avoid unnecessary fields for the
|
||||
* majority of functions. The compiler tries to omit internal
|
||||
* control fields when possible.
|
||||
*
|
||||
* Function templates:
|
||||
*
|
||||
* {
|
||||
* name: "func", // declaration, named function expressions
|
||||
* fileName: <debug info for creating nice errors>
|
||||
* _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
|
||||
* _Formals: [ "arg1", "arg2" ],
|
||||
* _Source: "function func(arg1, arg2) { ... }",
|
||||
* _Pc2line: <debug info for pc-to-line mapping>,
|
||||
* }
|
||||
*
|
||||
* Function instances:
|
||||
*
|
||||
* {
|
||||
* length: 2,
|
||||
* prototype: { constructor: <func> },
|
||||
* caller: <thrower>,
|
||||
* arguments: <thrower>,
|
||||
* name: "func", // declaration, named function expressions
|
||||
* fileName: <debug info for creating nice errors>
|
||||
* _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
|
||||
* _Formals: [ "arg1", "arg2" ],
|
||||
* _Source: "function func(arg1, arg2) { ... }",
|
||||
* _Pc2line: <debug info for pc-to-line mapping>,
|
||||
* }
|
||||
*
|
||||
* More detailed description of these properties can be found
|
||||
* in the documentation.
|
||||
*/
|
||||
|
||||
#if defined(DUK_USE_DEBUGGER_SUPPORT)
|
||||
/* Line number range for function. Needed during debugging to
|
||||
* determine active breakpoints.
|
||||
*/
|
||||
duk_uint32_t start_line;
|
||||
duk_uint32_t end_line;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* DUK_HCOMPFUNC_H_INCLUDED */
|
||||
Reference in New Issue
Block a user