1 /* 2 * ECMAScript compiler. 3 */ 4 5 #if !defined(DUK_JS_COMPILER_H_INCLUDED) 6 #define DUK_JS_COMPILER_H_INCLUDED 7 8 /* ECMAScript compiler limits */ 9 #define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */ 10 11 /* maximum loopcount for peephole optimization */ 12 #define DUK_COMPILER_PEEPHOLE_MAXITER 3 13 14 /* maximum bytecode length in instructions */ 15 #define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */ 16 17 /* 18 * Compiler intermediate values 19 * 20 * Intermediate values describe either plain values (e.g. strings or 21 * numbers) or binary operations which have not yet been coerced into 22 * either a left-hand-side or right-hand-side role (e.g. object property). 23 */ 24 25 #define DUK_IVAL_NONE 0 /* no value */ 26 #define DUK_IVAL_PLAIN 1 /* register, constant, or value */ 27 #define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */ 28 #define DUK_IVAL_PROP 3 /* property access */ 29 #define DUK_IVAL_VAR 4 /* variable access */ 30 31 #define DUK_ISPEC_NONE 0 /* no value */ 32 #define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */ 33 #define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */ 34 35 /* Bit mask which indicates that a regconst is a constant instead of a register. 36 * Chosen so that when a regconst is cast to duk_int32_t, all consts are 37 * negative values. 38 */ 39 #define DUK_REGCONST_CONST_MARKER DUK_INT32_MIN /* = -0x80000000 */ 40 41 /* Type to represent a reg/const reference during compilation, with <0 42 * indicating a constant. Some call sites also use -1 to indicate 'none'. 43 */ 44 typedef duk_int32_t duk_regconst_t; 45 46 typedef struct { 47 duk_small_uint_t t; /* DUK_ISPEC_XXX */ 48 duk_regconst_t regconst; 49 duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */ 50 } duk_ispec; 51 52 typedef struct { 53 /* 54 * PLAIN: x1 55 * ARITH: x1 <op> x2 56 * PROP: x1.x2 57 * VAR: x1 (name) 58 */ 59 60 /* XXX: can be optimized for smaller footprint esp. on 32-bit environments */ 61 duk_small_uint_t t; /* DUK_IVAL_XXX */ 62 duk_small_uint_t op; /* bytecode opcode for binary ops */ 63 duk_ispec x1; 64 duk_ispec x2; 65 } duk_ivalue; 66 67 /* 68 * Bytecode instruction representation during compilation 69 * 70 * Contains the actual instruction and (optionally) debug info. 71 */ 72 73 struct duk_compiler_instr { 74 duk_instr_t ins; 75 #if defined(DUK_USE_PC2LINE) 76 duk_uint32_t line; 77 #endif 78 }; 79 80 /* 81 * Compiler state 82 */ 83 84 #define DUK_LABEL_FLAG_ALLOW_BREAK (1U << 0) 85 #define DUK_LABEL_FLAG_ALLOW_CONTINUE (1U << 1) 86 87 #define DUK_DECL_TYPE_VAR 0 88 #define DUK_DECL_TYPE_FUNC 1 89 90 /* XXX: optimize to 16 bytes */ 91 typedef struct { 92 duk_small_uint_t flags; 93 duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */ 94 duk_hstring *h_label; /* borrowed label name */ 95 duk_int_t catch_depth; /* catch depth at point of definition */ 96 duk_int_t pc_label; /* pc of label statement: 97 * pc+1: break jump site 98 * pc+2: continue jump site 99 */ 100 101 /* Fast jumps (which avoid longjmp) jump directly to the jump sites 102 * which are always known even while the iteration/switch statement 103 * is still being parsed. A final peephole pass "straightens out" 104 * the jumps. 105 */ 106 } duk_labelinfo; 107 108 /* Compiling state of one function, eventually converted to duk_hcompfunc */ 109 struct duk_compiler_func { 110 /* These pointers are at the start of the struct so that they pack 111 * nicely. Mixing pointers and integer values is bad on some 112 * platforms (e.g. if int is 32 bits and pointers are 64 bits). 113 */ 114 115 duk_bufwriter_ctx bw_code; /* bufwriter for code */ 116 117 duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */ 118 /* h_code: held in bw_code */ 119 duk_hobject *h_consts; /* array */ 120 duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2] 121 * offset/line points to closing brace to allow skipping on pass 2 122 */ 123 duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ] 124 * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars) 125 * record function and variable declarations in pass 1 126 */ 127 duk_hobject *h_labelnames; /* array of active label names */ 128 duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */ 129 duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */ 130 duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */ 131 132 /* Value stack indices for tracking objects. */ 133 /* code_idx: not needed */ 134 duk_idx_t consts_idx; 135 duk_idx_t funcs_idx; 136 duk_idx_t decls_idx; 137 duk_idx_t labelnames_idx; 138 duk_idx_t labelinfos_idx; 139 duk_idx_t argnames_idx; 140 duk_idx_t varmap_idx; 141 142 /* Temp reg handling. */ 143 duk_regconst_t temp_first; /* first register that is a temporary (below: variables) */ 144 duk_regconst_t temp_next; /* next temporary register to allocate */ 145 duk_regconst_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */ 146 147 /* Shuffle registers if large number of regs/consts. */ 148 duk_regconst_t shuffle1; 149 duk_regconst_t shuffle2; 150 duk_regconst_t shuffle3; 151 152 /* Stats for current expression being parsed. */ 153 duk_int_t nud_count; 154 duk_int_t led_count; 155 duk_int_t paren_level; /* parenthesis count, 0 = top level */ 156 duk_bool_t expr_lhs; /* expression is left-hand-side compatible */ 157 duk_bool_t allow_in; /* current paren level allows 'in' token */ 158 159 /* Misc. */ 160 duk_int_t stmt_next; /* statement id allocation (running counter) */ 161 duk_int_t label_next; /* label id allocation (running counter) */ 162 duk_int_t catch_depth; /* catch stack depth */ 163 duk_int_t with_depth; /* with stack depth (affects identifier lookups) */ 164 duk_int_t fnum_next; /* inner function numbering */ 165 duk_int_t num_formals; /* number of formal arguments */ 166 duk_regconst_t reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */ 167 #if defined(DUK_USE_DEBUGGER_SUPPORT) 168 duk_int_t min_line; /* XXX: typing (duk_hcompfunc has duk_uint32_t) */ 169 duk_int_t max_line; 170 #endif 171 172 /* Status booleans. */ 173 duk_uint8_t is_function; /* is an actual function (not global/eval code) */ 174 duk_uint8_t is_eval; /* is eval code */ 175 duk_uint8_t is_global; /* is global code */ 176 duk_uint8_t is_namebinding; /* needs a name binding */ 177 duk_uint8_t is_constructable; /* result is constructable */ 178 duk_uint8_t is_setget; /* is a setter/getter */ 179 duk_uint8_t is_strict; /* function is strict */ 180 duk_uint8_t is_notail; /* function must not be tail called */ 181 duk_uint8_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */ 182 duk_uint8_t in_scanning; /* parsing in "scanning" phase (first pass) */ 183 duk_uint8_t may_direct_eval; /* function may call direct eval */ 184 duk_uint8_t id_access_arguments; /* function refers to 'arguments' identifier */ 185 duk_uint8_t id_access_slow; /* function makes one or more slow path accesses that won't match own static variables */ 186 duk_uint8_t id_access_slow_own; /* function makes one or more slow path accesses that may match own static variables */ 187 duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */ 188 duk_uint8_t needs_shuffle; /* function needs shuffle registers */ 189 duk_uint8_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */ 190 duk_uint8_t allow_regexp_in_adv; /* allow RegExp literal on next advance() call */ 191 }; 192 193 struct duk_compiler_ctx { 194 duk_hthread *thr; 195 196 /* filename being compiled (ends up in functions' '_filename' property) */ 197 duk_hstring *h_filename; /* borrowed reference */ 198 199 /* lexing (tokenization) state (contains two valstack slot indices) */ 200 duk_lexer_ctx lex; 201 202 /* current and previous token for parsing */ 203 duk_token prev_token; 204 duk_token curr_token; 205 duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */ 206 duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */ 207 duk_idx_t tok21_idx; /* prev_token slot1 */ 208 duk_idx_t tok22_idx; /* prev_token slot2 */ 209 210 /* recursion limit */ 211 duk_int_t recursion_depth; 212 duk_int_t recursion_limit; 213 214 /* code emission temporary */ 215 duk_int_t emit_jumpslot_pc; 216 217 /* current function being compiled (embedded instead of pointer for more compact access) */ 218 duk_compiler_func curr_func; 219 }; 220 221 /* 222 * Prototypes 223 */ 224 225 DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags); 226 227 #endif /* DUK_JS_COMPILER_H_INCLUDED */ 228