|
|
|
/*
|
|
|
|
* Ecmascript bytecode
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if !defined(DUK_JS_BYTECODE_H_INCLUDED)
|
|
|
|
#define DUK_JS_BYTECODE_H_INCLUDED
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bytecode instruction layout
|
|
|
|
* ===========================
|
|
|
|
*
|
|
|
|
* Instructions are unsigned 32-bit integers divided as follows:
|
|
|
|
*
|
|
|
|
* !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
|
|
|
|
* !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
|
|
|
|
* +-----------------------------------------------+---------------+
|
|
|
|
* ! C ! B ! A ! OP !
|
|
|
|
* +-----------------------------------------------+---------------+
|
|
|
|
*
|
|
|
|
* OP (8 bits): opcode (DUK_OP_*), access should be fastest
|
|
|
|
* consecutive opcodes allocated when opcode needs flags
|
|
|
|
* A (8 bits): typically a target register number
|
|
|
|
* B (8 bits): typically first source register/constant number
|
|
|
|
* C (8 bits): typically second source register/constant number
|
|
|
|
*
|
|
|
|
* Some instructions combine BC or ABC together for larger parameter values.
|
|
|
|
* Signed integers (e.g. jump offsets) are encoded as unsigned, with an
|
|
|
|
* opcode specific bias.
|
|
|
|
*
|
|
|
|
* Some opcodes have flags which are handled by allocating consecutive
|
|
|
|
* opcodes to make space for 1-N flags. Flags can also be e.g. in the 'A'
|
|
|
|
* field when there's room for the specific opcode.
|
|
|
|
*
|
|
|
|
* For example, if three flags were needed, they could be allocated from
|
|
|
|
* the opcode field as follows:
|
|
|
|
*
|
|
|
|
* !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
|
|
|
|
* !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
|
|
|
|
* +-----------------------------------------------+---------------+
|
|
|
|
* ! C ! B ! A ! OP !Z!Y!X!
|
|
|
|
* +-----------------------------------------------+---------------+
|
|
|
|
*
|
|
|
|
* Some opcodes accept a reg/const argument which is handled by allocating
|
|
|
|
* flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST(). The
|
|
|
|
* following convention is shared by most opcodes, so that the compiler
|
|
|
|
* can handle reg/const flagging without opcode specific code paths:
|
|
|
|
*
|
|
|
|
* !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
|
|
|
|
* !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!
|
|
|
|
* +-----------------------------------------------+---------------+
|
|
|
|
* ! C ! B ! A ! OP !Y!X!
|
|
|
|
* +-----------------------------------------------+---------------+
|
|
|
|
*
|
|
|
|
* X 1=B is const, 0=B is reg
|
|
|
|
* Y 1=C is const, 0=C is reg
|
|
|
|
*
|
|
|
|
* In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
|
|
|
|
* 8-bit opcode space for a single logical opcode. The base opcode
|
|
|
|
* number should be divisible by 4. If the opcode is called 'FOO'
|
|
|
|
* the following opcode constants would be defined:
|
|
|
|
*
|
|
|
|
* DUK_OP_FOO 100 // base opcode number
|
|
|
|
* DUK_OP_FOO_RR 100 // FOO, B=reg, C=reg
|
|
|
|
* DUK_OP_FOO_CR 101 // FOO, B=const, C=reg
|
|
|
|
* DUK_OP_FOO_RC 102 // FOO, B=reg, C=const
|
|
|
|
* DUK_OP_FOO_CC 103 // FOO, B=const, C=const
|
|
|
|
*
|
|
|
|
* If only B or C is a reg/const, the unused opcode combinations can be
|
|
|
|
* used for other opcodes (which take no reg/const argument). However,
|
|
|
|
* such opcode values are initially reserved, at least while opcode space
|
|
|
|
* is available. For example, if 'BAR' uses B for a register field and
|
|
|
|
* C is a reg/const:
|
|
|
|
*
|
|
|
|
* DUK_OP_BAR 116 // base opcode number
|
|
|
|
* DUK_OP_BAR_RR 116 // BAR, B=reg, C=reg
|
|
|
|
* DUK_OP_BAR_CR_UNUSED 117 // unused, could be repurposed
|
|
|
|
* DUK_OP_BAR_RC 118 // BAR, B=reg, C=const
|
|
|
|
* DUK_OP_BAR_CC_UNUSED 119 // unused, could be repurposed
|
|
|
|
*
|
|
|
|
* Macro naming is a bit misleading, e.g. "ABC" in macro name but the
|
|
|
|
* field layout is concretely "CBA" in the register.
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef duk_uint32_t duk_instr_t;
|
|
|
|
|
|
|
|
#define DUK_BC_SHIFT_OP 0
|
|
|
|
#define DUK_BC_SHIFT_A 8
|
|
|
|
#define DUK_BC_SHIFT_B 16
|
|
|
|
#define DUK_BC_SHIFT_C 24
|
|
|
|
#define DUK_BC_SHIFT_BC DUK_BC_SHIFT_B
|
|
|
|
#define DUK_BC_SHIFT_ABC DUK_BC_SHIFT_A
|
|
|
|
|
|
|
|
#define DUK_BC_UNSHIFTED_MASK_OP 0xffUL
|
|
|
|
#define DUK_BC_UNSHIFTED_MASK_A 0xffUL
|
|
|
|
#define DUK_BC_UNSHIFTED_MASK_B 0xffUL
|
|
|
|
#define DUK_BC_UNSHIFTED_MASK_C 0xffUL
|
|
|
|
#define DUK_BC_UNSHIFTED_MASK_BC 0xffffUL
|
|
|
|
#define DUK_BC_UNSHIFTED_MASK_ABC 0xffffffUL
|
|
|
|
|
|
|
|
#define DUK_BC_SHIFTED_MASK_OP (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
|
|
|
|
#define DUK_BC_SHIFTED_MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
|
|
|
|
#define DUK_BC_SHIFTED_MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
|
|
|
|
#define DUK_BC_SHIFTED_MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
|
|
|
|
#define DUK_BC_SHIFTED_MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
|
|
|
|
#define DUK_BC_SHIFTED_MASK_ABC (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
|
|
|
|
|
|
|
|
#define DUK_DEC_OP(x) ((x) & 0xffUL)
|
|
|
|
#define DUK_DEC_A(x) (((x) >> 8) & 0xffUL)
|
|
|
|
#define DUK_DEC_B(x) (((x) >> 16) & 0xffUL)
|
|
|
|
#define DUK_DEC_C(x) (((x) >> 24) & 0xffUL)
|
|
|
|
#define DUK_DEC_BC(x) (((x) >> 16) & 0xffffUL)
|
|
|
|
#define DUK_DEC_ABC(x) (((x) >> 8) & 0xffffffUL)
|
|
|
|
|
Rework pre/post inc/dec in compiler and executor
Pre/post inc/dec are an important fast path for fastints. Reimplement these
operations as atomic opcodes so that fast pathing is easier. Opcodes emitted
for typical loop constructs are also reduced by the change. Several opcodes
were moved to extraops to make space for the 12 pre/post inc/dec reg/var/prop
variants, and the compiler was changed to support two-argument (dest, dest,
src) extraop arithmetic for its ispec/ivalue.
Example of bytecode change, in Duktape 1.1.0:
function foo() { var x = 10; print(x++, x++, x--, x--, x--); print(x); }
BC 0000: LDINT 0, 10, 256 ; 0x80028003 op=3 (LDINT) a=0 b=10 c=256
BC 0001: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0002: LDREG 3, 0, 0 ; 0x000000c0 op=0 (LDREG) a=3 b=0 c=0
BC 0003: TONUM 3, 3 ; 0x0180c2fe op=62 (EXTRA) a=11 b=3 c=3
BC 0004: INC 0, 3 ; 0x0180067e op=62 (EXTRA) a=25 b=0 c=3
BC 0005: LDREG 4, 0, 0 ; 0x00000100 op=0 (LDREG) a=4 b=0 c=0
BC 0006: TONUM 4, 4 ; 0x020102fe op=62 (EXTRA) a=11 b=4 c=4
BC 0007: INC 0, 4 ; 0x0200067e op=62 (EXTRA) a=25 b=0 c=4
BC 0008: LDREG 5, 0, 0 ; 0x00000140 op=0 (LDREG) a=5 b=0 c=0
BC 0009: TONUM 5, 5 ; 0x028142fe op=62 (EXTRA) a=11 b=5 c=5
BC 0010: DEC 0, 5 ; 0x028006be op=62 (EXTRA) a=26 b=0 c=5
BC 0011: LDREG 6, 0, 0 ; 0x00000180 op=0 (LDREG) a=6 b=0 c=0
BC 0012: TONUM 6, 6 ; 0x030182fe op=62 (EXTRA) a=11 b=6 c=6
BC 0013: DEC 0, 6 ; 0x030006be op=62 (EXTRA) a=26 b=0 c=6
BC 0014: LDREG 7, 0, 0 ; 0x000001c0 op=0 (LDREG) a=7 b=0 c=0
BC 0015: TONUM 7, 7 ; 0x0381c2fe op=62 (EXTRA) a=11 b=7 c=7
BC 0016: DEC 0, 7 ; 0x038006be op=62 (EXTRA) a=26 b=0 c=7
BC 0017: CALL 0, 1, 5 ; 0x02804034 op=52 (CALL) a=0 b=1 c=5
BC 0018: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0019: LDREG 3, 0, 0 ; 0x000000c0 op=0 (LDREG) a=3 b=0 c=0
BC 0020: CALL 0, 1, 1 ; 0x00804034 op=52 (CALL) a=0 b=1 c=1
BC 0021: RETURN 1, 0, 0 ; 0x00000073 op=51 (RETURN) a=1 b=0 c=0
After this commit:
function foo() { var x = 10; print(x++, x++, x--, x--, x--); print(x); }
BC 0000: LDINT 0, 10, 256 ; 0x80028003 op=3 (LDINT) a=0 b=10 c=256
BC 0001: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0002: POSTINC 3, 0, 0 ; 0x000000f9 op=57 (POSTINC) a=3 b=0 c=0
BC 0003: POSTINC 4, 0, 0 ; 0x00000139 op=57 (POSTINC) a=4 b=0 c=0
BC 0004: POSTDEC 5, 0, 0 ; 0x0000017c op=60 (POSTDEC) a=5 b=0 c=0
BC 0005: POSTDEC 6, 0, 0 ; 0x000001bc op=60 (POSTDEC) a=6 b=0 c=0
BC 0006: POSTDEC 7, 0, 0 ; 0x000001fc op=60 (POSTDEC) a=7 b=0 c=0
BC 0007: CALL 0, 1, 5 ; 0x02804030 op=48 (CALL) a=0 b=1 c=5
BC 0008: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0009: LDREG 3, 0, 0 ; 0x000000c0 op=0 (LDREG) a=3 b=0 c=0
BC 0010: CALL 0, 1, 1 ; 0x00804030 op=48 (CALL) a=0 b=1 c=1
BC 0011: RETURN 1, 0, 0 ; 0x0000006f op=47 (RETURN) a=1 b=0 c=0
For an empty for-loop, in Duktape 1.1.0:
function foo() { for (var i = 0; i < 1000; i++) {} }
BC 0000: LABEL 0, 0, 0 ; 0x00000036 op=54 (LABEL) a=0 b=0 c=0
BC 0001: JUMP 11 (to pc+12) ; 0x800002f2 op=50 (JUMP) a=11 b=0 c=256
BC 0002: JUMP 5 (to pc+6) ; 0x80000172 op=50 (JUMP) a=5 b=0 c=256
BC 0003: LDINT 0, 0, 256 ; 0x80000003 op=3 (LDINT) a=0 b=0 c=256
BC 0004: LT 1, 0, 256 ; 0x8000006d op=45 (LT) a=1 b=0 c=256
BC 0005: IF 0, 1, 0 ; 0x0000402f op=47 (IF) a=0 b=1 c=0
BC 0006: JUMP 1 (to pc+2) ; 0x80000072 op=50 (JUMP) a=1 b=0 c=256
BC 0007: JUMP 5 (to pc+6) ; 0x80000172 op=50 (JUMP) a=5 b=0 c=256
BC 0008: LDREG 1, 0, 0 ; 0x00000040 op=0 (LDREG) a=1 b=0 c=0
BC 0009: TONUM 1, 1 ; 0x008042fe op=62 (EXTRA) a=11 b=1 c=1
BC 0010: INC 0, 1 ; 0x0080067e op=62 (EXTRA) a=25 b=0 c=1
BC 0011: JUMP -8 (to pc-7) ; 0x7ffffe32 op=50 (JUMP) a=248 b=511 c=255
BC 0012: JUMP -5 (to pc-4) ; 0x7ffffef2 op=50 (JUMP) a=251 b=511 c=255
BC 0013: ENDLABEL 0, 0, 0 ; 0x00000037 op=55 (ENDLABEL) a=0 b=0 c=0
BC 0014: RETURN 1, 0, 0 ; 0x00000073 op=51 (RETURN) a=1 b=0 c=0
After this commit:
function foo() { for (var i = 0; i < 1000; i++) {} }
BC 0000: LABEL 0, 0 ; 0x0000083f op=63 (EXTRA) a=32 b=0 c=0
BC 0001: JUMP 9 (to pc+10) ; 0x8000026e op=46 (JUMP) a=9 b=0 c=256
BC 0002: JUMP 5 (to pc+6) ; 0x8000016e op=46 (JUMP) a=5 b=0 c=256
BC 0003: LDINT 0, 0, 256 ; 0x80000003 op=3 (LDINT) a=0 b=0 c=256
BC 0004: LT 1, 0, 256 ; 0x8000006b op=43 (LT) a=1 b=0 c=256
BC 0005: IF 0, 1, 0 ; 0x0000402d op=45 (IF) a=0 b=1 c=0
BC 0006: JUMP 1 (to pc+2) ; 0x8000006e op=46 (JUMP) a=1 b=0 c=256
BC 0007: JUMP 3 (to pc+4) ; 0x800000ee op=46 (JUMP) a=3 b=0 c=256
BC 0008: POSTINC 1, 0, 0 ; 0x00000079 op=57 (POSTINC) a=1 b=0 c=0
BC 0009: JUMP -6 (to pc-5) ; 0x7ffffeae op=46 (JUMP) a=250 b=511 c=255
BC 0010: JUMP -3 (to pc-2) ; 0x7fffff6e op=46 (JUMP) a=253 b=511 c=255
BC 0011: ENDLABEL 0, 0 ; 0x0000087f op=63 (EXTRA) a=33 b=0 c=0
BC 0012: RETURN 1, 0, 0 ; 0x0000006f op=47 (RETURN) a=1 b=0 c=0
10 years ago
|
|
|
#define DUK_ENC_OP(op) ((duk_instr_t) (op))
|
|
|
|
#define DUK_ENC_OP_ABC(op,abc) ((duk_instr_t) ( \
|
|
|
|
(((duk_instr_t) (abc)) << 8) | \
|
|
|
|
((duk_instr_t) (op)) \
|
|
|
|
))
|
|
|
|
#define DUK_ENC_OP_A_BC(op,a,bc) ((duk_instr_t) ( \
|
|
|
|
(((duk_instr_t) (bc)) << 16) | \
|
|
|
|
(((duk_instr_t) (a)) << 8) | \
|
|
|
|
((duk_instr_t) (op)) \
|
|
|
|
))
|
|
|
|
#define DUK_ENC_OP_A_B_C(op,a,b,c) ((duk_instr_t) ( \
|
|
|
|
(((duk_instr_t) (c)) << 24) | \
|
|
|
|
(((duk_instr_t) (b)) << 16) | \
|
|
|
|
(((duk_instr_t) (a)) << 8) | \
|
|
|
|
((duk_instr_t) (op)) \
|
|
|
|
))
|
|
|
|
#define DUK_ENC_OP_A_B(op,a,b) DUK_ENC_OP_A_B_C((op),(a),(b),0)
|
|
|
|
#define DUK_ENC_OP_A(op,a) DUK_ENC_OP_A_B_C((op),(a),0,0)
|
|
|
|
#define DUK_ENC_OP_BC(op,bc) DUK_ENC_OP_A_BC((op),0,(bc))
|
|
|
|
|
|
|
|
/* Get opcode base value with B/C reg/const flags cleared. */
|
|
|
|
#define DUK_BC_NOREGCONST_OP(op) ((op) & 0xfc)
|
|
|
|
|
|
|
|
/* Constants should be signed so that signed arithmetic involving them
|
|
|
|
* won't cause values to be coerced accidentally to unsigned.
|
|
|
|
*/
|
|
|
|
#define DUK_BC_OP_MIN 0
|
|
|
|
#define DUK_BC_OP_MAX 0xffL
|
|
|
|
#define DUK_BC_A_MIN 0
|
|
|
|
#define DUK_BC_A_MAX 0xffL
|
|
|
|
#define DUK_BC_B_MIN 0
|
|
|
|
#define DUK_BC_B_MAX 0xffL
|
|
|
|
#define DUK_BC_C_MIN 0
|
|
|
|
#define DUK_BC_C_MAX 0xffL
|
|
|
|
#define DUK_BC_BC_MIN 0
|
|
|
|
#define DUK_BC_BC_MAX 0xffffL
|
|
|
|
#define DUK_BC_ABC_MIN 0
|
|
|
|
#define DUK_BC_ABC_MAX 0xffffffL
|
|
|
|
|
|
|
|
/* Masks for B/C reg/const indicator in opcode field. */
|
|
|
|
#define DUK_BC_REGCONST_B (0x01UL)
|
|
|
|
#define DUK_BC_REGCONST_C (0x02UL)
|
|
|
|
|
|
|
|
/* Misc. masks for opcode field. */
|
|
|
|
#define DUK_BC_INCDECP_FLAG_DEC (0x04UL)
|
|
|
|
#define DUK_BC_INCDECP_FLAG_POST (0x08UL)
|
|
|
|
|
|
|
|
/* Opcodes. */
|
|
|
|
#define DUK_OP_LDREG 0
|
|
|
|
#define DUK_OP_STREG 1
|
|
|
|
#define DUK_OP_LDCONST 2
|
|
|
|
#define DUK_OP_LDINT 3
|
|
|
|
#define DUK_OP_LDINTX 4
|
|
|
|
#define DUK_OP_LDTHIS 5
|
|
|
|
#define DUK_OP_LDUNDEF 6
|
|
|
|
#define DUK_OP_LDNULL 7
|
|
|
|
#define DUK_OP_LDTRUE 8
|
|
|
|
#define DUK_OP_LDFALSE 9
|
|
|
|
#define DUK_OP_BNOT 10
|
|
|
|
#define DUK_OP_LNOT 11
|
|
|
|
#define DUK_OP_UNM 12
|
|
|
|
#define DUK_OP_UNP 13
|
|
|
|
#define DUK_OP_TYPEOF 14
|
|
|
|
#define DUK_OP_TYPEOFID 15
|
|
|
|
#define DUK_OP_EQ 16
|
|
|
|
#define DUK_OP_EQ_RR 16
|
|
|
|
#define DUK_OP_EQ_CR 17
|
|
|
|
#define DUK_OP_EQ_RC 18
|
|
|
|
#define DUK_OP_EQ_CC 19
|
|
|
|
#define DUK_OP_NEQ 20
|
|
|
|
#define DUK_OP_NEQ_RR 20
|
|
|
|
#define DUK_OP_NEQ_CR 21
|
|
|
|
#define DUK_OP_NEQ_RC 22
|
|
|
|
#define DUK_OP_NEQ_CC 23
|
|
|
|
#define DUK_OP_SEQ 24
|
|
|
|
#define DUK_OP_SEQ_RR 24
|
|
|
|
#define DUK_OP_SEQ_CR 25
|
|
|
|
#define DUK_OP_SEQ_RC 26
|
|
|
|
#define DUK_OP_SEQ_CC 27
|
|
|
|
#define DUK_OP_SNEQ 28
|
|
|
|
#define DUK_OP_SNEQ_RR 28
|
|
|
|
#define DUK_OP_SNEQ_CR 29
|
|
|
|
#define DUK_OP_SNEQ_RC 30
|
|
|
|
#define DUK_OP_SNEQ_CC 31
|
|
|
|
#define DUK_OP_GT 32
|
|
|
|
#define DUK_OP_GT_RR 32
|
|
|
|
#define DUK_OP_GT_CR 33
|
|
|
|
#define DUK_OP_GT_RC 34
|
|
|
|
#define DUK_OP_GT_CC 35
|
|
|
|
#define DUK_OP_GE 36
|
|
|
|
#define DUK_OP_GE_RR 36
|
|
|
|
#define DUK_OP_GE_CR 37
|
|
|
|
#define DUK_OP_GE_RC 38
|
|
|
|
#define DUK_OP_GE_CC 39
|
|
|
|
#define DUK_OP_LT 40
|
|
|
|
#define DUK_OP_LT_RR 40
|
|
|
|
#define DUK_OP_LT_CR 41
|
|
|
|
#define DUK_OP_LT_RC 42
|
|
|
|
#define DUK_OP_LT_CC 43
|
Rework pre/post inc/dec in compiler and executor
Pre/post inc/dec are an important fast path for fastints. Reimplement these
operations as atomic opcodes so that fast pathing is easier. Opcodes emitted
for typical loop constructs are also reduced by the change. Several opcodes
were moved to extraops to make space for the 12 pre/post inc/dec reg/var/prop
variants, and the compiler was changed to support two-argument (dest, dest,
src) extraop arithmetic for its ispec/ivalue.
Example of bytecode change, in Duktape 1.1.0:
function foo() { var x = 10; print(x++, x++, x--, x--, x--); print(x); }
BC 0000: LDINT 0, 10, 256 ; 0x80028003 op=3 (LDINT) a=0 b=10 c=256
BC 0001: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0002: LDREG 3, 0, 0 ; 0x000000c0 op=0 (LDREG) a=3 b=0 c=0
BC 0003: TONUM 3, 3 ; 0x0180c2fe op=62 (EXTRA) a=11 b=3 c=3
BC 0004: INC 0, 3 ; 0x0180067e op=62 (EXTRA) a=25 b=0 c=3
BC 0005: LDREG 4, 0, 0 ; 0x00000100 op=0 (LDREG) a=4 b=0 c=0
BC 0006: TONUM 4, 4 ; 0x020102fe op=62 (EXTRA) a=11 b=4 c=4
BC 0007: INC 0, 4 ; 0x0200067e op=62 (EXTRA) a=25 b=0 c=4
BC 0008: LDREG 5, 0, 0 ; 0x00000140 op=0 (LDREG) a=5 b=0 c=0
BC 0009: TONUM 5, 5 ; 0x028142fe op=62 (EXTRA) a=11 b=5 c=5
BC 0010: DEC 0, 5 ; 0x028006be op=62 (EXTRA) a=26 b=0 c=5
BC 0011: LDREG 6, 0, 0 ; 0x00000180 op=0 (LDREG) a=6 b=0 c=0
BC 0012: TONUM 6, 6 ; 0x030182fe op=62 (EXTRA) a=11 b=6 c=6
BC 0013: DEC 0, 6 ; 0x030006be op=62 (EXTRA) a=26 b=0 c=6
BC 0014: LDREG 7, 0, 0 ; 0x000001c0 op=0 (LDREG) a=7 b=0 c=0
BC 0015: TONUM 7, 7 ; 0x0381c2fe op=62 (EXTRA) a=11 b=7 c=7
BC 0016: DEC 0, 7 ; 0x038006be op=62 (EXTRA) a=26 b=0 c=7
BC 0017: CALL 0, 1, 5 ; 0x02804034 op=52 (CALL) a=0 b=1 c=5
BC 0018: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0019: LDREG 3, 0, 0 ; 0x000000c0 op=0 (LDREG) a=3 b=0 c=0
BC 0020: CALL 0, 1, 1 ; 0x00804034 op=52 (CALL) a=0 b=1 c=1
BC 0021: RETURN 1, 0, 0 ; 0x00000073 op=51 (RETURN) a=1 b=0 c=0
After this commit:
function foo() { var x = 10; print(x++, x++, x--, x--, x--); print(x); }
BC 0000: LDINT 0, 10, 256 ; 0x80028003 op=3 (LDINT) a=0 b=10 c=256
BC 0001: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0002: POSTINC 3, 0, 0 ; 0x000000f9 op=57 (POSTINC) a=3 b=0 c=0
BC 0003: POSTINC 4, 0, 0 ; 0x00000139 op=57 (POSTINC) a=4 b=0 c=0
BC 0004: POSTDEC 5, 0, 0 ; 0x0000017c op=60 (POSTDEC) a=5 b=0 c=0
BC 0005: POSTDEC 6, 0, 0 ; 0x000001bc op=60 (POSTDEC) a=6 b=0 c=0
BC 0006: POSTDEC 7, 0, 0 ; 0x000001fc op=60 (POSTDEC) a=7 b=0 c=0
BC 0007: CALL 0, 1, 5 ; 0x02804030 op=48 (CALL) a=0 b=1 c=5
BC 0008: CSVAR 1, 256, 0 ; 0x00400052 op=18 (CSVAR) a=1 b=256 c=0
BC 0009: LDREG 3, 0, 0 ; 0x000000c0 op=0 (LDREG) a=3 b=0 c=0
BC 0010: CALL 0, 1, 1 ; 0x00804030 op=48 (CALL) a=0 b=1 c=1
BC 0011: RETURN 1, 0, 0 ; 0x0000006f op=47 (RETURN) a=1 b=0 c=0
For an empty for-loop, in Duktape 1.1.0:
function foo() { for (var i = 0; i < 1000; i++) {} }
BC 0000: LABEL 0, 0, 0 ; 0x00000036 op=54 (LABEL) a=0 b=0 c=0
BC 0001: JUMP 11 (to pc+12) ; 0x800002f2 op=50 (JUMP) a=11 b=0 c=256
BC 0002: JUMP 5 (to pc+6) ; 0x80000172 op=50 (JUMP) a=5 b=0 c=256
BC 0003: LDINT 0, 0, 256 ; 0x80000003 op=3 (LDINT) a=0 b=0 c=256
BC 0004: LT 1, 0, 256 ; 0x8000006d op=45 (LT) a=1 b=0 c=256
BC 0005: IF 0, 1, 0 ; 0x0000402f op=47 (IF) a=0 b=1 c=0
BC 0006: JUMP 1 (to pc+2) ; 0x80000072 op=50 (JUMP) a=1 b=0 c=256
BC 0007: JUMP 5 (to pc+6) ; 0x80000172 op=50 (JUMP) a=5 b=0 c=256
BC 0008: LDREG 1, 0, 0 ; 0x00000040 op=0 (LDREG) a=1 b=0 c=0
BC 0009: TONUM 1, 1 ; 0x008042fe op=62 (EXTRA) a=11 b=1 c=1
BC 0010: INC 0, 1 ; 0x0080067e op=62 (EXTRA) a=25 b=0 c=1
BC 0011: JUMP -8 (to pc-7) ; 0x7ffffe32 op=50 (JUMP) a=248 b=511 c=255
BC 0012: JUMP -5 (to pc-4) ; 0x7ffffef2 op=50 (JUMP) a=251 b=511 c=255
BC 0013: ENDLABEL 0, 0, 0 ; 0x00000037 op=55 (ENDLABEL) a=0 b=0 c=0
BC 0014: RETURN 1, 0, 0 ; 0x00000073 op=51 (RETURN) a=1 b=0 c=0
After this commit:
function foo() { for (var i = 0; i < 1000; i++) {} }
BC 0000: LABEL 0, 0 ; 0x0000083f op=63 (EXTRA) a=32 b=0 c=0
BC 0001: JUMP 9 (to pc+10) ; 0x8000026e op=46 (JUMP) a=9 b=0 c=256
BC 0002: JUMP 5 (to pc+6) ; 0x8000016e op=46 (JUMP) a=5 b=0 c=256
BC 0003: LDINT 0, 0, 256 ; 0x80000003 op=3 (LDINT) a=0 b=0 c=256
BC 0004: LT 1, 0, 256 ; 0x8000006b op=43 (LT) a=1 b=0 c=256
BC 0005: IF 0, 1, 0 ; 0x0000402d op=45 (IF) a=0 b=1 c=0
BC 0006: JUMP 1 (to pc+2) ; 0x8000006e op=46 (JUMP) a=1 b=0 c=256
BC 0007: JUMP 3 (to pc+4) ; 0x800000ee op=46 (JUMP) a=3 b=0 c=256
BC 0008: POSTINC 1, 0, 0 ; 0x00000079 op=57 (POSTINC) a=1 b=0 c=0
BC 0009: JUMP -6 (to pc-5) ; 0x7ffffeae op=46 (JUMP) a=250 b=511 c=255
BC 0010: JUMP -3 (to pc-2) ; 0x7fffff6e op=46 (JUMP) a=253 b=511 c=255
BC 0011: ENDLABEL 0, 0 ; 0x0000087f op=63 (EXTRA) a=33 b=0 c=0
BC 0012: RETURN 1, 0, 0 ; 0x0000006f op=47 (RETURN) a=1 b=0 c=0
10 years ago
|
|
|
#define DUK_OP_LE 44
|
|
|
|
#define DUK_OP_LE_RR 44
|
|
|
|
#define DUK_OP_LE_CR 45
|
|
|
|
#define DUK_OP_LE_RC 46
|
|
|
|
#define DUK_OP_LE_CC 47
|
|
|
|
#define DUK_OP_IFTRUE 48
|
|
|
|
#define DUK_OP_IFTRUE_R 48
|
|
|
|
#define DUK_OP_IFTRUE_C 49
|
|
|
|
#define DUK_OP_IFFALSE 50
|
|
|
|
#define DUK_OP_IFFALSE_R 50
|
|
|
|
#define DUK_OP_IFFALSE_C 51
|
|
|
|
#define DUK_OP_ADD 52
|
|
|
|
#define DUK_OP_ADD_RR 52
|
|
|
|
#define DUK_OP_ADD_CR 53
|
|
|
|
#define DUK_OP_ADD_RC 54
|
|
|
|
#define DUK_OP_ADD_CC 55
|
|
|
|
#define DUK_OP_SUB 56
|
|
|
|
#define DUK_OP_SUB_RR 56
|
|
|
|
#define DUK_OP_SUB_CR 57
|
|
|
|
#define DUK_OP_SUB_RC 58
|
|
|
|
#define DUK_OP_SUB_CC 59
|
|
|
|
#define DUK_OP_MUL 60
|
|
|
|
#define DUK_OP_MUL_RR 60
|
|
|
|
#define DUK_OP_MUL_CR 61
|
|
|
|
#define DUK_OP_MUL_RC 62
|
|
|
|
#define DUK_OP_MUL_CC 63
|
|
|
|
#define DUK_OP_DIV 64
|
|
|
|
#define DUK_OP_DIV_RR 64
|
|
|
|
#define DUK_OP_DIV_CR 65
|
|
|
|
#define DUK_OP_DIV_RC 66
|
|
|
|
#define DUK_OP_DIV_CC 67
|
|
|
|
#define DUK_OP_MOD 68
|
|
|
|
#define DUK_OP_MOD_RR 68
|
|
|
|
#define DUK_OP_MOD_CR 69
|
|
|
|
#define DUK_OP_MOD_RC 70
|
|
|
|
#define DUK_OP_MOD_CC 71
|
|
|
|
#define DUK_OP_EXP 72
|
|
|
|
#define DUK_OP_EXP_RR 72
|
|
|
|
#define DUK_OP_EXP_CR 73
|
|
|
|
#define DUK_OP_EXP_RC 74
|
|
|
|
#define DUK_OP_EXP_CC 75
|
|
|
|
#define DUK_OP_BAND 76
|
|
|
|
#define DUK_OP_BAND_RR 76
|
|
|
|
#define DUK_OP_BAND_CR 77
|
|
|
|
#define DUK_OP_BAND_RC 78
|
|
|
|
#define DUK_OP_BAND_CC 79
|
|
|
|
#define DUK_OP_BOR 80
|
|
|
|
#define DUK_OP_BOR_RR 80
|
|
|
|
#define DUK_OP_BOR_CR 81
|
|
|
|
#define DUK_OP_BOR_RC 82
|
|
|
|
#define DUK_OP_BOR_CC 83
|
|
|
|
#define DUK_OP_BXOR 84
|
|
|
|
#define DUK_OP_BXOR_RR 84
|
|
|
|
#define DUK_OP_BXOR_CR 85
|
|
|
|
#define DUK_OP_BXOR_RC 86
|
|
|
|
#define DUK_OP_BXOR_CC 87
|
|
|
|
#define DUK_OP_BASL 88
|
|
|
|
#define DUK_OP_BASL_RR 88
|
|
|
|
#define DUK_OP_BASL_CR 89
|
|
|
|
#define DUK_OP_BASL_RC 90
|
|
|
|
#define DUK_OP_BASL_CC 91
|
|
|
|
#define DUK_OP_BLSR 92
|
|
|
|
#define DUK_OP_BLSR_RR 92
|
|
|
|
#define DUK_OP_BLSR_CR 93
|
|
|
|
#define DUK_OP_BLSR_RC 94
|
|
|
|
#define DUK_OP_BLSR_CC 95
|
|
|
|
#define DUK_OP_BASR 96
|
|
|
|
#define DUK_OP_BASR_RR 96
|
|
|
|
#define DUK_OP_BASR_CR 97
|
|
|
|
#define DUK_OP_BASR_RC 98
|
|
|
|
#define DUK_OP_BASR_CC 99
|
|
|
|
#define DUK_OP_INSTOF 100
|
|
|
|
#define DUK_OP_INSTOF_RR 100
|
|
|
|
#define DUK_OP_INSTOF_CR 101
|
|
|
|
#define DUK_OP_INSTOF_RC 102
|
|
|
|
#define DUK_OP_INSTOF_CC 103
|
|
|
|
#define DUK_OP_IN 104
|
|
|
|
#define DUK_OP_IN_RR 104
|
|
|
|
#define DUK_OP_IN_CR 105
|
|
|
|
#define DUK_OP_IN_RC 106
|
|
|
|
#define DUK_OP_IN_CC 107
|
|
|
|
#define DUK_OP_GETPROP 108
|
|
|
|
#define DUK_OP_GETPROP_RR 108
|
|
|
|
#define DUK_OP_GETPROP_CR 109
|
|
|
|
#define DUK_OP_GETPROP_RC 110
|
|
|
|
#define DUK_OP_GETPROP_CC 111
|
|
|
|
#define DUK_OP_PUTPROP 112
|
|
|
|
#define DUK_OP_PUTPROP_RR 112
|
|
|
|
#define DUK_OP_PUTPROP_CR 113
|
|
|
|
#define DUK_OP_PUTPROP_RC 114
|
|
|
|
#define DUK_OP_PUTPROP_CC 115
|
|
|
|
#define DUK_OP_DELPROP 116
|
|
|
|
#define DUK_OP_DELPROP_RR 116
|
|
|
|
#define DUK_OP_DELPROP_CR_UNUSED 117 /* unused now */
|
|
|
|
#define DUK_OP_DELPROP_RC 118
|
|
|
|
#define DUK_OP_DELPROP_CC_UNUSED 119 /* unused now */
|
|
|
|
#define DUK_OP_PREINCR 120 /* pre/post opcode values have constraints, */
|
|
|
|
#define DUK_OP_PREDECR 121 /* see duk_js_executor.c and duk_js_compiler.c. */
|
|
|
|
#define DUK_OP_POSTINCR 122
|
|
|
|
#define DUK_OP_POSTDECR 123
|
|
|
|
#define DUK_OP_PREINCV 124
|
|
|
|
#define DUK_OP_PREDECV 125
|
|
|
|
#define DUK_OP_POSTINCV 126
|
|
|
|
#define DUK_OP_POSTDECV 127
|
|
|
|
#define DUK_OP_PREINCP 128 /* pre/post inc/dec prop opcodes have constraints */
|
|
|
|
#define DUK_OP_PREINCP_RR 128
|
|
|
|
#define DUK_OP_PREINCP_CR 129
|
|
|
|
#define DUK_OP_PREINCP_RC 130
|
|
|
|
#define DUK_OP_PREINCP_CC 131
|
|
|
|
#define DUK_OP_PREDECP 132
|
|
|
|
#define DUK_OP_PREDECP_RR 132
|
|
|
|
#define DUK_OP_PREDECP_CR 133
|
|
|
|
#define DUK_OP_PREDECP_RC 134
|
|
|
|
#define DUK_OP_PREDECP_CC 135
|
|
|
|
#define DUK_OP_POSTINCP 136
|
|
|
|
#define DUK_OP_POSTINCP_RR 136
|
|
|
|
#define DUK_OP_POSTINCP_CR 137
|
|
|
|
#define DUK_OP_POSTINCP_RC 138
|
|
|
|
#define DUK_OP_POSTINCP_CC 139
|
|
|
|
#define DUK_OP_POSTDECP 140
|
|
|
|
#define DUK_OP_POSTDECP_RR 140
|
|
|
|
#define DUK_OP_POSTDECP_CR 141
|
|
|
|
#define DUK_OP_POSTDECP_RC 142
|
|
|
|
#define DUK_OP_POSTDECP_CC 143
|
|
|
|
#define DUK_OP_DECLVAR 144
|
|
|
|
#define DUK_OP_DECLVAR_RR 144
|
|
|
|
#define DUK_OP_DECLVAR_CR 145
|
|
|
|
#define DUK_OP_DECLVAR_RC 146
|
|
|
|
#define DUK_OP_DECLVAR_CC 147
|
|
|
|
#define DUK_OP_REGEXP 148
|
|
|
|
#define DUK_OP_REGEXP_RR 148
|
|
|
|
#define DUK_OP_REGEXP_CR 149
|
|
|
|
#define DUK_OP_REGEXP_RC 150
|
|
|
|
#define DUK_OP_REGEXP_CC 151
|
|
|
|
#define DUK_OP_CSVAR 152
|
|
|
|
#define DUK_OP_CSVAR_RR 152
|
|
|
|
#define DUK_OP_CSVAR_CR 153
|
|
|
|
#define DUK_OP_CSVAR_RC 154
|
|
|
|
#define DUK_OP_CSVAR_CC 155
|
|
|
|
#define DUK_OP_CLOSURE 156
|
|
|
|
#define DUK_OP_GETVAR 157
|
|
|
|
#define DUK_OP_PUTVAR 158
|
|
|
|
#define DUK_OP_DELVAR 159
|
|
|
|
#define DUK_OP_JUMP 160
|
|
|
|
#define DUK_OP_RETREG 161
|
|
|
|
#define DUK_OP_RETUNDEF 162
|
|
|
|
#define DUK_OP_RETCONST 163
|
|
|
|
#define DUK_OP_RETCONSTN 164 /* return const without incref (e.g. number) */
|
|
|
|
#define DUK_OP_LABEL 165
|
|
|
|
#define DUK_OP_ENDLABEL 166
|
|
|
|
#define DUK_OP_BREAK 167
|
|
|
|
#define DUK_OP_CONTINUE 168
|
|
|
|
#define DUK_OP_TRYCATCH 169
|
|
|
|
#define DUK_OP_ENDTRY 170
|
|
|
|
#define DUK_OP_ENDCATCH 171
|
|
|
|
#define DUK_OP_ENDFIN 172
|
|
|
|
#define DUK_OP_THROW 173
|
|
|
|
#define DUK_OP_CSREG 174
|
|
|
|
#define DUK_OP_EVALCALL 175
|
|
|
|
#define DUK_OP_CALL 176 /* op & 0x03 must be 0 */
|
|
|
|
#define DUK_OP_TAILCALL 177 /* op & 0x03 must be 1 */
|
|
|
|
#define DUK_OP_CONSCALL 178 /* op & 0x03 must be 2 */
|
|
|
|
#define DUK_OP_NEWOBJ 179
|
|
|
|
#define DUK_OP_NEWARR 180
|
|
|
|
#define DUK_OP_MPUTOBJ 181
|
|
|
|
#define DUK_OP_MPUTOBJI 182
|
|
|
|
#define DUK_OP_INITSET 183
|
|
|
|
#define DUK_OP_INITGET 184
|
|
|
|
#define DUK_OP_MPUTARR 185
|
|
|
|
#define DUK_OP_MPUTARRI 186
|
|
|
|
#define DUK_OP_SETALEN 187
|
|
|
|
#define DUK_OP_INITENUM 188
|
|
|
|
#define DUK_OP_NEXTENUM 189
|
|
|
|
#define DUK_OP_INVLHS 190
|
|
|
|
#define DUK_OP_DEBUGGER 191
|
|
|
|
#define DUK_OP_NOP 192
|
|
|
|
#define DUK_OP_INVALID 193
|
|
|
|
#define DUK_OP_NEWTARGET 194
|
|
|
|
#define DUK_OP_UNUSED195 195
|
|
|
|
#define DUK_OP_UNUSED196 196
|
|
|
|
#define DUK_OP_UNUSED197 197
|
|
|
|
#define DUK_OP_UNUSED198 198
|
|
|
|
#define DUK_OP_UNUSED199 199
|
|
|
|
#define DUK_OP_UNUSED200 200
|
|
|
|
#define DUK_OP_UNUSED201 201
|
|
|
|
#define DUK_OP_UNUSED202 202
|
|
|
|
#define DUK_OP_UNUSED203 203
|
|
|
|
#define DUK_OP_UNUSED204 204
|
|
|
|
#define DUK_OP_UNUSED205 205
|
|
|
|
#define DUK_OP_UNUSED206 206
|
|
|
|
#define DUK_OP_UNUSED207 207
|
|
|
|
#define DUK_OP_UNUSED208 208
|
|
|
|
#define DUK_OP_UNUSED209 209
|
|
|
|
#define DUK_OP_UNUSED210 210
|
|
|
|
#define DUK_OP_UNUSED211 211
|
|
|
|
#define DUK_OP_UNUSED212 212
|
|
|
|
#define DUK_OP_UNUSED213 213
|
|
|
|
#define DUK_OP_UNUSED214 214
|
|
|
|
#define DUK_OP_UNUSED215 215
|
|
|
|
#define DUK_OP_UNUSED216 216
|
|
|
|
#define DUK_OP_UNUSED217 217
|
|
|
|
#define DUK_OP_UNUSED218 218
|
|
|
|
#define DUK_OP_UNUSED219 219
|
|
|
|
#define DUK_OP_UNUSED220 220
|
|
|
|
#define DUK_OP_UNUSED221 221
|
|
|
|
#define DUK_OP_UNUSED222 222
|
|
|
|
#define DUK_OP_UNUSED223 223
|
|
|
|
#define DUK_OP_UNUSED224 224
|
|
|
|
#define DUK_OP_UNUSED225 225
|
|
|
|
#define DUK_OP_UNUSED226 226
|
|
|
|
#define DUK_OP_UNUSED227 227
|
|
|
|
#define DUK_OP_UNUSED228 228
|
|
|
|
#define DUK_OP_UNUSED229 229
|
|
|
|
#define DUK_OP_UNUSED230 230
|
|
|
|
#define DUK_OP_UNUSED231 231
|
|
|
|
#define DUK_OP_UNUSED232 232
|
|
|
|
#define DUK_OP_UNUSED233 233
|
|
|
|
#define DUK_OP_UNUSED234 234
|
|
|
|
#define DUK_OP_UNUSED235 235
|
|
|
|
#define DUK_OP_UNUSED236 236
|
|
|
|
#define DUK_OP_UNUSED237 237
|
|
|
|
#define DUK_OP_UNUSED238 238
|
|
|
|
#define DUK_OP_UNUSED239 239
|
|
|
|
#define DUK_OP_UNUSED240 240
|
|
|
|
#define DUK_OP_UNUSED241 241
|
|
|
|
#define DUK_OP_UNUSED242 242
|
|
|
|
#define DUK_OP_UNUSED243 243
|
|
|
|
#define DUK_OP_UNUSED244 244
|
|
|
|
#define DUK_OP_UNUSED245 245
|
|
|
|
#define DUK_OP_UNUSED246 246
|
|
|
|
#define DUK_OP_UNUSED247 247
|
|
|
|
#define DUK_OP_UNUSED248 248
|
|
|
|
#define DUK_OP_UNUSED249 249
|
|
|
|
#define DUK_OP_UNUSED250 250
|
|
|
|
#define DUK_OP_UNUSED251 251
|
|
|
|
#define DUK_OP_UNUSED252 252
|
|
|
|
#define DUK_OP_UNUSED253 253
|
|
|
|
#define DUK_OP_UNUSED254 254
|
|
|
|
#define DUK_OP_UNUSED255 255
|
|
|
|
#define DUK_OP_NONE 256 /* dummy value used as marker (doesn't fit in 8-bit field) */
|
|
|
|
|
|
|
|
/* XXX: Allocate flags from opcode field? Would take 16 opcode slots
|
|
|
|
* but avoids shuffling in more cases. Maybe not worth it.
|
|
|
|
*/
|
|
|
|
/* DUK_OP_TRYCATCH flags in A */
|
|
|
|
#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1 << 0)
|
|
|
|
#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1 << 1)
|
|
|
|
#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1 << 2)
|
|
|
|
#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1 << 3)
|
|
|
|
|
|
|
|
/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags (DUK_PROPDESC_FLAG_XXX) */
|
|
|
|
#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1 << 4) /* function declaration */
|
|
|
|
|
|
|
|
/* Misc constants and helper macros. */
|
|
|
|
#define DUK_BC_LDINT_BIAS (1L << 15)
|
|
|
|
#define DUK_BC_LDINTX_SHIFT 16
|
|
|
|
#define DUK_BC_JUMP_BIAS (1L << 23)
|
|
|
|
|
|
|
|
#endif /* DUK_JS_BYTECODE_H_INCLUDED */
|