Browse Source

change emit_loadint to support full 32-bit signed range, add support for emitting LDINT+LDINTX for larger constants

pull/1/head
Sami Vaarala 11 years ago
parent
commit
7049399008
  1. 17
      src/duk_js_bytecode.h
  2. 47
      src/duk_js_compiler.c

17
src/duk_js_bytecode.h

@ -44,18 +44,21 @@ typedef duk_uint32_t duk_instr;
#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)
/* 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 0x3fUL
#define DUK_BC_OP_MAX 0x3fL
#define DUK_BC_A_MIN 0
#define DUK_BC_A_MAX 0xffUL
#define DUK_BC_A_MAX 0xffL
#define DUK_BC_B_MIN 0
#define DUK_BC_B_MAX 0x1ffUL
#define DUK_BC_B_MAX 0x1ffL
#define DUK_BC_C_MIN 0
#define DUK_BC_C_MAX 0x1ffUL
#define DUK_BC_C_MAX 0x1ffL
#define DUK_BC_BC_MIN 0
#define DUK_BC_BC_MAX 0x3ffffUL
#define DUK_BC_BC_MAX 0x3ffffL
#define DUK_BC_ABC_MIN 0
#define DUK_BC_ABC_MAX 0x3ffffffUL
#define DUK_BC_ABC_MAX 0x3ffffffL
#define DUK_BC_EXTRAOP_MIN DUK_BC_A_MIN
#define DUK_BC_EXTRAOP_MAX DUK_BC_A_MAX
@ -63,7 +66,7 @@ typedef duk_uint32_t duk_instr;
#define DUK_OP_STREG 1
#define DUK_OP_LDCONST 2
#define DUK_OP_LDINT 3
#define DUK_OP_LDINTX 4 /* FIXME: UNUSED */
#define DUK_OP_LDINTX 4
#define DUK_OP_MPUTOBJ 5
#define DUK_OP_MPUTARR 6
#define DUK_OP_NEW 7

47
src/duk_js_compiler.c

@ -1130,14 +1130,27 @@ static void emit_extraop_only(duk_compiler_ctx *comp_ctx, int extraop) {
emit_a_b_c(comp_ctx, DUK_OP_EXTRA, extraop, 0, 0);
}
static void emit_loadint(duk_compiler_ctx *comp_ctx, int reg, int val) {
static void emit_loadint(duk_compiler_ctx *comp_ctx, int reg, duk_int32_t val) {
/* FIXME: typing */
/* FIXME: LDINTX support */
DUK_DDDPRINT("emit loadint: %d -> reg %d", val, reg);
/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
* would only shuffle once (instead of twice). The current code works
* and has a smaller compiler footprint.
*/
DUK_ASSERT(reg >= DUK_BC_A_MIN && reg <= DUK_BC_A_MAX);
DUK_ASSERT(val + DUK_BC_LDINT_BIAS >= DUK_BC_BC_MIN);
DUK_ASSERT(val + DUK_BC_LDINT_BIAS <= DUK_BC_BC_MAX);
emit_a_bc(comp_ctx, DUK_OP_LDINT, reg, val + DUK_BC_LDINT_BIAS);
if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
(val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
DUK_DDDPRINT("emit LDINT to reg %d for %d", (int) reg, (int) val);
emit_a_bc(comp_ctx, DUK_OP_LDINT, reg, val + (duk_int32_t) DUK_BC_LDINT_BIAS);
} else {
duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
DUK_DDDPRINT("emit LDINT+LDINTX to reg %d for %d -> hi %d, lo %d",
(int) reg, (int) val, (int) hi, (int) lo);
emit_a_bc(comp_ctx, DUK_OP_LDINT, reg, hi + (duk_int32_t) DUK_BC_LDINT_BIAS);
emit_a_bc(comp_ctx, DUK_OP_LDINTX, reg, lo);
}
}
static void emit_jump(duk_compiler_ctx *comp_ctx, int target_pc) {
@ -1544,22 +1557,16 @@ static int ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
dval = DUK_TVAL_GET_NUMBER(tv);
if (!(flags & IVAL_FLAG_ALLOW_CONST)) {
/* A number can be loaded either through a constant or
* using LDINT+LDINTX. Which is better depends on the
* context and how many times a certain constant would
* be reused.
*
* Currently, use LDINT if a constant is not allowed
* and a LDINT would work.
/* A number can be loaded either through a constant, using
* LDINT, or using LDINT+LDINTX. LDINT is always a size win,
* LDINT+LDINTX is not if the constant is used multiple times.
* Currently always prefer LDINT+LDINTX over a double constant.
*/
if (is_whole_get_i32(dval, &ival)) { /* FIXME: to util */
ival += DUK_BC_LDINT_BIAS;
if (ival >= DUK_BC_BC_MIN && ival <= DUK_BC_BC_MAX) {
dest = (forced_reg >= 0 ? forced_reg : ALLOCTEMP(comp_ctx));
emit_a_bc(comp_ctx, DUK_OP_LDINT, dest, ival);
return dest;
}
if (is_whole_get_i32(dval, &ival)) {
dest = (forced_reg >= 0 ? forced_reg : ALLOCTEMP(comp_ctx));
emit_loadint(comp_ctx, dest, ival);
return dest;
}
}

Loading…
Cancel
Save