diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 8864c9a3..77b55f0c 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -2518,7 +2518,7 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
2518 | { | 2518 | { |
2519 | CTState *cts = ctype_ctsG(J2G(as->J)); | 2519 | CTState *cts = ctype_ctsG(J2G(as->J)); |
2520 | CTypeID typeid = (CTypeID)IR(ir->op1)->i; | 2520 | CTypeID typeid = (CTypeID)IR(ir->op1)->i; |
2521 | CTSize sz = (ir->o == IR_CNEWP || ir->op2 == REF_NIL) ? | 2521 | CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? |
2522 | lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op2)->i; | 2522 | lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op2)->i; |
2523 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; | 2523 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; |
2524 | IRRef args[2]; | 2524 | IRRef args[2]; |
@@ -2529,33 +2529,45 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
2529 | as->gcsteps++; | 2529 | as->gcsteps++; |
2530 | asm_setupresult(as, ir, ci); /* GCcdata * */ | 2530 | asm_setupresult(as, ir, ci); /* GCcdata * */ |
2531 | 2531 | ||
2532 | /* Initialize pointer cdata object. */ | 2532 | /* Initialize immutable cdata object. */ |
2533 | if (ir->o == IR_CNEWP) { | 2533 | if (ir->o == IR_CNEWI) { |
2534 | RegSet allow = (RSET_GPR & ~RSET_SCRATCH); | ||
2535 | #if LJ_64 | ||
2536 | Reg r64 = sz == 8 ? REX_64 : 0; | ||
2534 | if (irref_isk(ir->op2)) { | 2537 | if (irref_isk(ir->op2)) { |
2535 | IRIns *irk = IR(ir->op2); | 2538 | IRIns *irk = IR(ir->op2); |
2536 | #if LJ_64 | 2539 | uint64_t k = irk->o == IR_KINT64 ? ir_k64(irk)->u64 : |
2537 | if (irk->o == IR_KINT64) { | 2540 | (uint64_t)(uint32_t)irk->i; |
2538 | uint64_t k = ir_k64(irk)->u64; | 2541 | if (sz == 4 || checki32((int64_t)k)) { |
2539 | lua_assert(sz == 8); | 2542 | emit_i32(as, (int32_t)k); |
2540 | if (checki32((int64_t)k)) { | 2543 | emit_rmro(as, XO_MOVmi, r64, RID_RET, sizeof(GCcdata)); |
2541 | emit_i32(as, (int32_t)k); | ||
2542 | emit_rmro(as, XO_MOVmi, REX_64, RID_RET, sizeof(GCcdata)); | ||
2543 | } else { | ||
2544 | emit_movtomro(as, RID_ECX|REX_64, RID_RET, sizeof(GCcdata)); | ||
2545 | emit_loadu64(as, RID_ECX, k); | ||
2546 | } | ||
2547 | } else { | 2544 | } else { |
2548 | #endif | 2545 | emit_movtomro(as, RID_ECX + r64, RID_RET, sizeof(GCcdata)); |
2549 | lua_assert(sz == 4); | 2546 | emit_loadu64(as, RID_ECX, k); |
2550 | emit_movmroi(as, RID_RET, sizeof(GCcdata), irk->i); | ||
2551 | #if LJ_64 | ||
2552 | } | 2547 | } |
2553 | #endif | ||
2554 | } else { | 2548 | } else { |
2555 | Reg r = ra_alloc1(as, ir->op2, (RSET_GPR & ~RSET_SCRATCH)); | 2549 | Reg r = ra_alloc1(as, ir->op2, allow); |
2556 | emit_movtomro(as, r + ((LJ_64 && sz == 8) ? REX_64 : 0), | 2550 | emit_movtomro(as, r + r64, RID_RET, sizeof(GCcdata)); |
2557 | RID_RET, sizeof(GCcdata)); | 2551 | } |
2552 | #else | ||
2553 | int32_t ofs = sizeof(GCcdata); | ||
2554 | if (LJ_HASFFI && sz == 8) { | ||
2555 | ofs += 4; ir++; | ||
2556 | lua_assert(ir->o == IR_HIOP); | ||
2558 | } | 2557 | } |
2558 | do { | ||
2559 | if (irref_isk(ir->op2)) { | ||
2560 | emit_movmroi(as, RID_RET, ofs, IR(ir->op2)->i); | ||
2561 | } else { | ||
2562 | Reg r = ra_alloc1(as, ir->op2, allow); | ||
2563 | emit_movtomro(as, r, RID_RET, ofs); | ||
2564 | rset_clear(allow, r); | ||
2565 | } | ||
2566 | if (!LJ_HASFFI || ofs == sizeof(GCcdata)) break; | ||
2567 | ofs -= 4; ir--; | ||
2568 | } while (1); | ||
2569 | #endif | ||
2570 | lua_assert(sz == 4 || (sz == 8 && (LJ_64 || LJ_HASFFI))); | ||
2559 | } | 2571 | } |
2560 | 2572 | ||
2561 | /* Combine initialization of marked, gct and typeid. */ | 2573 | /* Combine initialization of marked, gct and typeid. */ |
@@ -3289,6 +3301,9 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
3289 | if (!uselo) | 3301 | if (!uselo) |
3290 | ra_allocref(as, ir->op1, RID2RSET(RID_RET)); /* Mark call as used. */ | 3302 | ra_allocref(as, ir->op1, RID2RSET(RID_RET)); /* Mark call as used. */ |
3291 | break; | 3303 | break; |
3304 | case IR_CNEWI: | ||
3305 | /* Nothing to do here. Handled by CNEWI itself. */ | ||
3306 | break; | ||
3292 | default: lua_assert(0); break; | 3307 | default: lua_assert(0); break; |
3293 | } | 3308 | } |
3294 | #else | 3309 | #else |
@@ -4057,7 +4072,7 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
4057 | case IR_SNEW: asm_snew(as, ir); break; | 4072 | case IR_SNEW: asm_snew(as, ir); break; |
4058 | case IR_TNEW: asm_tnew(as, ir); break; | 4073 | case IR_TNEW: asm_tnew(as, ir); break; |
4059 | case IR_TDUP: asm_tdup(as, ir); break; | 4074 | case IR_TDUP: asm_tdup(as, ir); break; |
4060 | case IR_CNEW: case IR_CNEWP: asm_cnew(as, ir); break; | 4075 | case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break; |
4061 | 4076 | ||
4062 | /* Write barriers. */ | 4077 | /* Write barriers. */ |
4063 | case IR_TBAR: asm_tbar(as, ir); break; | 4078 | case IR_TBAR: asm_tbar(as, ir); break; |
@@ -4164,8 +4179,10 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
4164 | } | 4179 | } |
4165 | #if LJ_32 && LJ_HASFFI | 4180 | #if LJ_32 && LJ_HASFFI |
4166 | case IR_HIOP: | 4181 | case IR_HIOP: |
4167 | if ((ir-1)->o == IR_CALLN) | 4182 | if ((ir-1)->o == IR_CALLN) { |
4168 | ir->prev = REGSP_HINT(RID_RETHI); | 4183 | ir->prev = REGSP_HINT(RID_RETHI); |
4184 | continue; | ||
4185 | } | ||
4169 | break; | 4186 | break; |
4170 | #endif | 4187 | #endif |
4171 | /* C calls evict all scratch regs and return results in RID_RET. */ | 4188 | /* C calls evict all scratch regs and return results in RID_RET. */ |
@@ -4174,7 +4191,7 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
4174 | if (as->evenspill < 3) /* lj_str_new and lj_tab_newkey need 3 args. */ | 4191 | if (as->evenspill < 3) /* lj_str_new and lj_tab_newkey need 3 args. */ |
4175 | as->evenspill = 3; | 4192 | as->evenspill = 3; |
4176 | #endif | 4193 | #endif |
4177 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWP: case IR_TOSTR: | 4194 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: |
4178 | ir->prev = REGSP_HINT(RID_RET); | 4195 | ir->prev = REGSP_HINT(RID_RET); |
4179 | if (inloop) | 4196 | if (inloop) |
4180 | as->modset = RSET_SCRATCH; | 4197 | as->modset = RSET_SCRATCH; |