aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r--src/lj_asm.c67
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;