diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 3d4060b2..215dfb13 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -14,6 +14,9 @@ | |||
14 | #include "lj_str.h" | 14 | #include "lj_str.h" |
15 | #include "lj_tab.h" | 15 | #include "lj_tab.h" |
16 | #include "lj_frame.h" | 16 | #include "lj_frame.h" |
17 | #if LJ_HASFFI | ||
18 | #include "lj_ctype.h" | ||
19 | #endif | ||
17 | #include "lj_ir.h" | 20 | #include "lj_ir.h" |
18 | #include "lj_jit.h" | 21 | #include "lj_jit.h" |
19 | #include "lj_iropt.h" | 22 | #include "lj_iropt.h" |
@@ -2279,6 +2282,91 @@ static void asm_tdup(ASMState *as, IRIns *ir) | |||
2279 | asm_gencall(as, ci, args); | 2282 | asm_gencall(as, ci, args); |
2280 | } | 2283 | } |
2281 | 2284 | ||
2285 | #if LJ_HASFFI | ||
2286 | static RegSet asm_cnew_init(ASMState *as, IRRef ref, int32_t ofs, RegSet allow) | ||
2287 | { | ||
2288 | IRIns *ir = IR(ref); | ||
2289 | if (irref_isk(ref)) { | ||
2290 | #if LJ_64 | ||
2291 | if (ir->o == IR_KNUM || ir->o == IR_KINT64) { | ||
2292 | uint64_t k = ir_k64(ir)->u64; | ||
2293 | if (checki32((int64_t)k)) { | ||
2294 | emit_i32(as, (int32_t)k); | ||
2295 | emit_rmro(as, XO_MOVmi, REX_64, RID_RET, ofs); | ||
2296 | } else { | ||
2297 | emit_movtomro(as, RID_ECX|REX_64, RID_RET, ofs); | ||
2298 | emit_loadu64(as, RID_ECX, k); | ||
2299 | } | ||
2300 | } else { | ||
2301 | emit_movmroi(as, RID_RET, ofs, ir->i); | ||
2302 | } | ||
2303 | #else | ||
2304 | if (ir->o == IR_KNUM) { | ||
2305 | emit_rmro(as, XO_MOVSDto, RID_XMM0, RID_RET, ofs); | ||
2306 | emit_loadn(as, RID_XMM0, ir_k64(ir)); | ||
2307 | } else if (ir->o == IR_KINT64) { | ||
2308 | uint64_t k = ir_k64(ir)->u64; | ||
2309 | emit_movmroi(as, RID_RET, ofs, (int32_t)k); | ||
2310 | emit_movmroi(as, RID_RET, ofs+4, (int32_t)(k >> 32)); | ||
2311 | } else { | ||
2312 | emit_movmroi(as, RID_RET, ofs, ir->i); | ||
2313 | } | ||
2314 | #endif | ||
2315 | } else { | ||
2316 | Reg r; | ||
2317 | if (irt_isnum(ir->t)) { | ||
2318 | r = ra_alloc1(as, ref, (RSET_FPR & allow)); | ||
2319 | emit_rmro(as, XO_MOVSDto, r, RID_RET, ofs); | ||
2320 | } else { | ||
2321 | r = ra_alloc1(as, ref, (RSET_GPR & allow)); | ||
2322 | emit_movtomro(as, REX_64IR(ir, r), RID_RET, ofs); | ||
2323 | } | ||
2324 | rset_clear(allow, r); | ||
2325 | } | ||
2326 | return allow; | ||
2327 | } | ||
2328 | |||
2329 | static void asm_cnew(ASMState *as, IRIns *ir) | ||
2330 | { | ||
2331 | CTState *cts = ctype_ctsG(J2G(as->J)); | ||
2332 | CTypeID typeid = (CTypeID)IR(ir->op2)->i; | ||
2333 | CTSize sz = (ir->o == IR_CNEWI || ir->op1 == REF_NIL) ? | ||
2334 | lj_ctype_size(cts, typeid) : (CTSize)IR(ir->op1)->i; | ||
2335 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; | ||
2336 | IRRef args[2]; | ||
2337 | lua_assert(sz != CTSIZE_INVALID); | ||
2338 | |||
2339 | args[0] = ASMREF_L; /* lua_State *L */ | ||
2340 | args[1] = ASMREF_TMP1; /* MSize size */ | ||
2341 | as->gcsteps++; | ||
2342 | asm_setupresult(as, ir, ci); /* GCobj * */ | ||
2343 | |||
2344 | /* Initialize immutable cdata object. */ | ||
2345 | if (ir->o == IR_CNEWI) { | ||
2346 | RegSet allow = ~RSET_SCRATCH; | ||
2347 | IRRef ref = ir->op1; | ||
2348 | if (IR(ref)->o == IR_CARG) { /* 2nd initializer. */ | ||
2349 | IRIns *ira = IR(ref); | ||
2350 | allow = asm_cnew_init(as, ira->op2, sizeof(GCcdata) + (sz>>1), allow); | ||
2351 | ref = ira->op1; | ||
2352 | } | ||
2353 | asm_cnew_init(as, ref, sizeof(GCcdata), allow); /* 1st initializer. */ | ||
2354 | } | ||
2355 | |||
2356 | /* Combine initialization of marked, gct and typeid. */ | ||
2357 | emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked)); | ||
2358 | emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX, | ||
2359 | (int32_t)((~LJ_TCDATA<<8)+(typeid<<16))); | ||
2360 | emit_gri(as, XG_ARITHi(XOg_AND), RID_ECX, LJ_GC_WHITES); | ||
2361 | emit_opgl(as, XO_MOVZXb, RID_ECX, gc.currentwhite); | ||
2362 | |||
2363 | asm_gencall(as, ci, args); | ||
2364 | emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)(sz+sizeof(GCcdata))); | ||
2365 | } | ||
2366 | #else | ||
2367 | #define asm_cnew(as, ir) ((void)0) | ||
2368 | #endif | ||
2369 | |||
2282 | /* -- Write barriers ------------------------------------------------------ */ | 2370 | /* -- Write barriers ------------------------------------------------------ */ |
2283 | 2371 | ||
2284 | static void asm_tbar(ASMState *as, IRIns *ir) | 2372 | static void asm_tbar(ASMState *as, IRIns *ir) |
@@ -3587,6 +3675,7 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
3587 | case IR_SNEW: asm_snew(as, ir); break; | 3675 | case IR_SNEW: asm_snew(as, ir); break; |
3588 | case IR_TNEW: asm_tnew(as, ir); break; | 3676 | case IR_TNEW: asm_tnew(as, ir); break; |
3589 | case IR_TDUP: asm_tdup(as, ir); break; | 3677 | case IR_TDUP: asm_tdup(as, ir); break; |
3678 | case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break; | ||
3590 | 3679 | ||
3591 | /* Write barriers. */ | 3680 | /* Write barriers. */ |
3592 | case IR_TBAR: asm_tbar(as, ir); break; | 3681 | case IR_TBAR: asm_tbar(as, ir); break; |
@@ -3704,7 +3793,7 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
3704 | if (as->evenspill < 3) /* lj_str_new and lj_tab_newkey need 3 args. */ | 3793 | if (as->evenspill < 3) /* lj_str_new and lj_tab_newkey need 3 args. */ |
3705 | as->evenspill = 3; | 3794 | as->evenspill = 3; |
3706 | #endif | 3795 | #endif |
3707 | case IR_TNEW: case IR_TDUP: case IR_TOSTR: | 3796 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: |
3708 | ir->prev = REGSP_HINT(RID_RET); | 3797 | ir->prev = REGSP_HINT(RID_RET); |
3709 | if (inloop) | 3798 | if (inloop) |
3710 | as->modset = RSET_SCRATCH; | 3799 | as->modset = RSET_SCRATCH; |