aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ext_ffi_semantics.html5
-rw-r--r--src/lj_asm.c11
-rw-r--r--src/lj_asm_arm.h29
-rw-r--r--src/lj_asm_mips.h44
-rw-r--r--src/lj_asm_ppc.h29
-rw-r--r--src/lj_asm_x86.h25
-rw-r--r--src/lj_crecord.c53
-rw-r--r--src/lj_ircall.h1
-rw-r--r--src/lj_target_mips.h3
9 files changed, 139 insertions, 61 deletions
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html
index 15c9a6db..6f84533c 100644
--- a/doc/ext_ffi_semantics.html
+++ b/doc/ext_ffi_semantics.html
@@ -1219,9 +1219,8 @@ suboptimal performance, especially when used in inner loops:
1219<li>Vector operations.</li> 1219<li>Vector operations.</li>
1220<li>Table initializers.</li> 1220<li>Table initializers.</li>
1221<li>Initialization of nested <tt>struct</tt>/<tt>union</tt> types.</li> 1221<li>Initialization of nested <tt>struct</tt>/<tt>union</tt> types.</li>
1222<li>Allocations of variable-length arrays or structs.</li> 1222<li>Non-default initialization of VLA/VLS or large C&nbsp;types
1223<li>Allocations of C&nbsp;types with a size &gt; 128&nbsp;bytes or an 1223(&gt; 128&nbsp;bytes or &gt; 16 array elements.</li>
1224alignment &gt; 8&nbsp;bytes.</li>
1225<li>Conversions from lightuserdata to <tt>void&nbsp;*</tt>.</li> 1224<li>Conversions from lightuserdata to <tt>void&nbsp;*</tt>.</li>
1226<li>Pointer differences for element sizes that are not a power of 1225<li>Pointer differences for element sizes that are not a power of
1227two.</li> 1226two.</li>
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 7542c77c..a80d6adf 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -2050,7 +2050,16 @@ static void asm_setup_regsp(ASMState *as)
2050 case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT: 2050 case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT:
2051 if (REGARG_NUMGPR < 3 && as->evenspill < 3) 2051 if (REGARG_NUMGPR < 3 && as->evenspill < 3)
2052 as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */ 2052 as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */
2053 case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: 2053#if LJ_TARGET_X86 && LJ_HASFFI
2054 if (0) {
2055 case IR_CNEW:
2056 if (ir->op2 != REF_NIL && as->evenspill < 4)
2057 as->evenspill = 4; /* lj_cdata_newv needs 4 args. */
2058 }
2059#else
2060 case IR_CNEW:
2061#endif
2062 case IR_TNEW: case IR_TDUP: case IR_CNEWI: case IR_TOSTR:
2054 case IR_BUFSTR: 2063 case IR_BUFSTR:
2055 ir->prev = REGSP_HINT(RID_RET); 2064 ir->prev = REGSP_HINT(RID_RET);
2056 if (inloop) 2065 if (inloop)
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index ddf1480f..9b661eb7 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -1209,19 +1209,16 @@ dotypecheck:
1209static void asm_cnew(ASMState *as, IRIns *ir) 1209static void asm_cnew(ASMState *as, IRIns *ir)
1210{ 1210{
1211 CTState *cts = ctype_ctsG(J2G(as->J)); 1211 CTState *cts = ctype_ctsG(J2G(as->J));
1212 CTypeID ctypeid = (CTypeID)IR(ir->op1)->i; 1212 CTypeID id = (CTypeID)IR(ir->op1)->i;
1213 CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? 1213 CTSize sz;
1214 lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i; 1214 CTInfo info = lj_ctype_info(cts, id, &sz);
1215 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; 1215 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
1216 IRRef args[2]; 1216 IRRef args[4];
1217 RegSet allow = (RSET_GPR & ~RSET_SCRATCH); 1217 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
1218 RegSet drop = RSET_SCRATCH; 1218 RegSet drop = RSET_SCRATCH;
1219 lua_assert(sz != CTSIZE_INVALID); 1219 lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
1220 1220
1221 args[0] = ASMREF_L; /* lua_State *L */
1222 args[1] = ASMREF_TMP1; /* MSize size */
1223 as->gcsteps++; 1221 as->gcsteps++;
1224
1225 if (ra_hasreg(ir->r)) 1222 if (ra_hasreg(ir->r))
1226 rset_clear(drop, ir->r); /* Dest reg handled below. */ 1223 rset_clear(drop, ir->r); /* Dest reg handled below. */
1227 ra_evictset(as, drop); 1224 ra_evictset(as, drop);
@@ -1243,16 +1240,28 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1243 if (ofs == sizeof(GCcdata)) break; 1240 if (ofs == sizeof(GCcdata)) break;
1244 ofs -= 4; ir--; 1241 ofs -= 4; ir--;
1245 } 1242 }
1243 } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
1244 ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
1245 args[0] = ASMREF_L; /* lua_State *L */
1246 args[1] = ir->op1; /* CTypeID id */
1247 args[2] = ir->op2; /* CTSize sz */
1248 args[3] = ASMREF_TMP1; /* CTSize align */
1249 asm_gencall(as, ci, args);
1250 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info));
1251 return;
1246 } 1252 }
1253
1247 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */ 1254 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
1248 { 1255 {
1249 uint32_t k = emit_isk12(ARMI_MOV, ctypeid); 1256 uint32_t k = emit_isk12(ARMI_MOV, id);
1250 Reg r = k ? RID_R1 : ra_allock(as, ctypeid, allow); 1257 Reg r = k ? RID_R1 : ra_allock(as, id, allow);
1251 emit_lso(as, ARMI_STRB, RID_TMP, RID_RET, offsetof(GCcdata, gct)); 1258 emit_lso(as, ARMI_STRB, RID_TMP, RID_RET, offsetof(GCcdata, gct));
1252 emit_lsox(as, ARMI_STRH, r, RID_RET, offsetof(GCcdata, ctypeid)); 1259 emit_lsox(as, ARMI_STRH, r, RID_RET, offsetof(GCcdata, ctypeid));
1253 emit_d(as, ARMI_MOV|ARMI_K12|~LJ_TCDATA, RID_TMP); 1260 emit_d(as, ARMI_MOV|ARMI_K12|~LJ_TCDATA, RID_TMP);
1254 if (k) emit_d(as, ARMI_MOV^k, RID_R1); 1261 if (k) emit_d(as, ARMI_MOV^k, RID_R1);
1255 } 1262 }
1263 args[0] = ASMREF_L; /* lua_State *L */
1264 args[1] = ASMREF_TMP1; /* MSize size */
1256 asm_gencall(as, ci, args); 1265 asm_gencall(as, ci, args);
1257 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)), 1266 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
1258 ra_releasetmp(as, ASMREF_TMP1)); 1267 ra_releasetmp(as, ASMREF_TMP1));
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index fe7d55d3..3d061eb4 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -975,19 +975,15 @@ dotypecheck:
975static void asm_cnew(ASMState *as, IRIns *ir) 975static void asm_cnew(ASMState *as, IRIns *ir)
976{ 976{
977 CTState *cts = ctype_ctsG(J2G(as->J)); 977 CTState *cts = ctype_ctsG(J2G(as->J));
978 CTypeID ctypeid = (CTypeID)IR(ir->op1)->i; 978 CTypeID id = (CTypeID)IR(ir->op1)->i;
979 CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? 979 CTSize sz;
980 lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i; 980 CTInfo info = lj_ctype_info(cts, id, &sz);
981 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; 981 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
982 IRRef args[2]; 982 IRRef args[4];
983 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
984 RegSet drop = RSET_SCRATCH; 983 RegSet drop = RSET_SCRATCH;
985 lua_assert(sz != CTSIZE_INVALID); 984 lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
986 985
987 args[0] = ASMREF_L; /* lua_State *L */
988 args[1] = ASMREF_TMP1; /* MSize size */
989 as->gcsteps++; 986 as->gcsteps++;
990
991 if (ra_hasreg(ir->r)) 987 if (ra_hasreg(ir->r))
992 rset_clear(drop, ir->r); /* Dest reg handled below. */ 988 rset_clear(drop, ir->r); /* Dest reg handled below. */
993 ra_evictset(as, drop); 989 ra_evictset(as, drop);
@@ -996,6 +992,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
996 992
997 /* Initialize immutable cdata object. */ 993 /* Initialize immutable cdata object. */
998 if (ir->o == IR_CNEWI) { 994 if (ir->o == IR_CNEWI) {
995 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
999 int32_t ofs = sizeof(GCcdata); 996 int32_t ofs = sizeof(GCcdata);
1000 lua_assert(sz == 4 || sz == 8); 997 lua_assert(sz == 4 || sz == 8);
1001 if (sz == 8) { 998 if (sz == 8) {
@@ -1010,12 +1007,24 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1010 if (ofs == sizeof(GCcdata)) break; 1007 if (ofs == sizeof(GCcdata)) break;
1011 ofs -= 4; if (LJ_BE) ir++; else ir--; 1008 ofs -= 4; if (LJ_BE) ir++; else ir--;
1012 } 1009 }
1010 } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
1011 ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
1012 args[0] = ASMREF_L; /* lua_State *L */
1013 args[1] = ir->op1; /* CTypeID id */
1014 args[2] = ir->op2; /* CTSize sz */
1015 args[3] = ASMREF_TMP1; /* CTSize align */
1016 asm_gencall(as, ci, args);
1017 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info));
1018 return;
1013 } 1019 }
1020
1014 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */ 1021 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
1015 emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct)); 1022 emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
1016 emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid)); 1023 emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
1017 emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA); 1024 emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA);
1018 emit_ti(as, MIPSI_LI, RID_TMP, ctypeid); /* Lower 16 bit used. Sign-ext ok. */ 1025 emit_ti(as, MIPSI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */
1026 args[0] = ASMREF_L; /* lua_State *L */
1027 args[1] = ASMREF_TMP1; /* MSize size */
1019 asm_gencall(as, ci, args); 1028 asm_gencall(as, ci, args);
1020 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)), 1029 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
1021 ra_releasetmp(as, ASMREF_TMP1)); 1030 ra_releasetmp(as, ASMREF_TMP1));
@@ -1197,11 +1206,16 @@ static void asm_arithov(ASMState *as, IRIns *ir)
1197 1206
1198static void asm_mulov(ASMState *as, IRIns *ir) 1207static void asm_mulov(ASMState *as, IRIns *ir)
1199{ 1208{
1200#if LJ_DUALNUM 1209 Reg dest = ra_dest(as, ir, RSET_GPR);
1201#error "NYI: MULOV" 1210 Reg tmp, right, left = ra_alloc2(as, ir, RSET_GPR);
1202#else 1211 right = (left >> 8); left &= 255;
1203 UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused in single-number mode. */ 1212 tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_GPR, left),
1204#endif 1213 right), dest));
1214 asm_guard(as, MIPSI_BNE, RID_TMP, tmp);
1215 emit_dta(as, MIPSI_SRA, RID_TMP, dest, 31);
1216 emit_dst(as, MIPSI_MFHI, tmp, 0, 0);
1217 emit_dst(as, MIPSI_MFLO, dest, 0, 0);
1218 emit_dst(as, MIPSI_MULT, 0, left, right);
1205} 1219}
1206 1220
1207#if LJ_HASFFI 1221#if LJ_HASFFI
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h
index 1cac6fa9..10cd79dd 100644
--- a/src/lj_asm_ppc.h
+++ b/src/lj_asm_ppc.h
@@ -1009,19 +1009,15 @@ dotypecheck:
1009static void asm_cnew(ASMState *as, IRIns *ir) 1009static void asm_cnew(ASMState *as, IRIns *ir)
1010{ 1010{
1011 CTState *cts = ctype_ctsG(J2G(as->J)); 1011 CTState *cts = ctype_ctsG(J2G(as->J));
1012 CTypeID ctypeid = (CTypeID)IR(ir->op1)->i; 1012 CTypeID id = (CTypeID)IR(ir->op1)->i;
1013 CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? 1013 CTSize sz;
1014 lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i; 1014 CTInfo info = lj_ctype_info(cts, id, &sz);
1015 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; 1015 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
1016 IRRef args[2]; 1016 IRRef args[4];
1017 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
1018 RegSet drop = RSET_SCRATCH; 1017 RegSet drop = RSET_SCRATCH;
1019 lua_assert(sz != CTSIZE_INVALID); 1018 lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
1020 1019
1021 args[0] = ASMREF_L; /* lua_State *L */
1022 args[1] = ASMREF_TMP1; /* MSize size */
1023 as->gcsteps++; 1020 as->gcsteps++;
1024
1025 if (ra_hasreg(ir->r)) 1021 if (ra_hasreg(ir->r))
1026 rset_clear(drop, ir->r); /* Dest reg handled below. */ 1022 rset_clear(drop, ir->r); /* Dest reg handled below. */
1027 ra_evictset(as, drop); 1023 ra_evictset(as, drop);
@@ -1030,6 +1026,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1030 1026
1031 /* Initialize immutable cdata object. */ 1027 /* Initialize immutable cdata object. */
1032 if (ir->o == IR_CNEWI) { 1028 if (ir->o == IR_CNEWI) {
1029 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
1033 int32_t ofs = sizeof(GCcdata); 1030 int32_t ofs = sizeof(GCcdata);
1034 lua_assert(sz == 4 || sz == 8); 1031 lua_assert(sz == 4 || sz == 8);
1035 if (sz == 8) { 1032 if (sz == 8) {
@@ -1043,12 +1040,24 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1043 if (ofs == sizeof(GCcdata)) break; 1040 if (ofs == sizeof(GCcdata)) break;
1044 ofs -= 4; ir++; 1041 ofs -= 4; ir++;
1045 } 1042 }
1043 } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
1044 ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
1045 args[0] = ASMREF_L; /* lua_State *L */
1046 args[1] = ir->op1; /* CTypeID id */
1047 args[2] = ir->op2; /* CTSize sz */
1048 args[3] = ASMREF_TMP1; /* CTSize align */
1049 asm_gencall(as, ci, args);
1050 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info));
1051 return;
1046 } 1052 }
1053
1047 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */ 1054 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
1048 emit_tai(as, PPCI_STB, RID_RET+1, RID_RET, offsetof(GCcdata, gct)); 1055 emit_tai(as, PPCI_STB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
1049 emit_tai(as, PPCI_STH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid)); 1056 emit_tai(as, PPCI_STH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
1050 emit_ti(as, PPCI_LI, RID_RET+1, ~LJ_TCDATA); 1057 emit_ti(as, PPCI_LI, RID_RET+1, ~LJ_TCDATA);
1051 emit_ti(as, PPCI_LI, RID_TMP, ctypeid); /* Lower 16 bit used. Sign-ext ok. */ 1058 emit_ti(as, PPCI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */
1059 args[0] = ASMREF_L; /* lua_State *L */
1060 args[1] = ASMREF_TMP1; /* MSize size */
1052 asm_gencall(as, ci, args); 1061 asm_gencall(as, ci, args);
1053 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)), 1062 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
1054 ra_releasetmp(as, ASMREF_TMP1)); 1063 ra_releasetmp(as, ASMREF_TMP1));
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index 25da5246..f2f8157d 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -1438,15 +1438,13 @@ static void asm_sload(ASMState *as, IRIns *ir)
1438static void asm_cnew(ASMState *as, IRIns *ir) 1438static void asm_cnew(ASMState *as, IRIns *ir)
1439{ 1439{
1440 CTState *cts = ctype_ctsG(J2G(as->J)); 1440 CTState *cts = ctype_ctsG(J2G(as->J));
1441 CTypeID ctypeid = (CTypeID)IR(ir->op1)->i; 1441 CTypeID id = (CTypeID)IR(ir->op1)->i;
1442 CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? 1442 CTSize sz;
1443 lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i; 1443 CTInfo info = lj_ctype_info(cts, id, &sz);
1444 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; 1444 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
1445 IRRef args[2]; 1445 IRRef args[4];
1446 lua_assert(sz != CTSIZE_INVALID); 1446 lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
1447 1447
1448 args[0] = ASMREF_L; /* lua_State *L */
1449 args[1] = ASMREF_TMP1; /* MSize size */
1450 as->gcsteps++; 1448 as->gcsteps++;
1451 asm_setupresult(as, ir, ci); /* GCcdata * */ 1449 asm_setupresult(as, ir, ci); /* GCcdata * */
1452 1450
@@ -1489,15 +1487,26 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1489 } while (1); 1487 } while (1);
1490#endif 1488#endif
1491 lua_assert(sz == 4 || sz == 8); 1489 lua_assert(sz == 4 || sz == 8);
1490 } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
1491 ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
1492 args[0] = ASMREF_L; /* lua_State *L */
1493 args[1] = ir->op1; /* CTypeID id */
1494 args[2] = ir->op2; /* CTSize sz */
1495 args[3] = ASMREF_TMP1; /* CTSize align */
1496 asm_gencall(as, ci, args);
1497 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info));
1498 return;
1492 } 1499 }
1493 1500
1494 /* Combine initialization of marked, gct and ctypeid. */ 1501 /* Combine initialization of marked, gct and ctypeid. */
1495 emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked)); 1502 emit_movtomro(as, RID_ECX, RID_RET, offsetof(GCcdata, marked));
1496 emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX, 1503 emit_gri(as, XG_ARITHi(XOg_OR), RID_ECX,
1497 (int32_t)((~LJ_TCDATA<<8)+(ctypeid<<16))); 1504 (int32_t)((~LJ_TCDATA<<8)+(id<<16)));
1498 emit_gri(as, XG_ARITHi(XOg_AND), RID_ECX, LJ_GC_WHITES); 1505 emit_gri(as, XG_ARITHi(XOg_AND), RID_ECX, LJ_GC_WHITES);
1499 emit_opgl(as, XO_MOVZXb, RID_ECX, gc.currentwhite); 1506 emit_opgl(as, XO_MOVZXb, RID_ECX, gc.currentwhite);
1500 1507
1508 args[0] = ASMREF_L; /* lua_State *L */
1509 args[1] = ASMREF_TMP1; /* MSize size */
1501 asm_gencall(as, ci, args); 1510 asm_gencall(as, ci, args);
1502 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)(sz+sizeof(GCcdata))); 1511 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)(sz+sizeof(GCcdata)));
1503} 1512}
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index e88e3579..ef6e5f82 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -888,10 +888,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
888 CTSize sz; 888 CTSize sz;
889 CTInfo info = lj_ctype_info(cts, id, &sz); 889 CTInfo info = lj_ctype_info(cts, id, &sz);
890 CType *d = ctype_raw(cts, id); 890 CType *d = ctype_raw(cts, id);
891 TRef trid; 891 TRef trcd, trid = lj_ir_kint(J, id);
892 if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN) 892 cTValue *fin;
893 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */
894 trid = lj_ir_kint(J, id);
895 /* Use special instruction to box pointer or 32/64 bit integer. */ 893 /* Use special instruction to box pointer or 32/64 bit integer. */
896 if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { 894 if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) {
897 TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : 895 TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) :
@@ -899,11 +897,36 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
899 sz == 4 ? lj_ir_kint(J, 0) : 897 sz == 4 ? lj_ir_kint(J, 0) :
900 (lj_needsplit(J), lj_ir_kint64(J, 0)); 898 (lj_needsplit(J), lj_ir_kint64(J, 0));
901 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); 899 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
900 return;
902 } else { 901 } else {
903 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); 902 TRef trsz = TREF_NIL;
904 cTValue *fin; 903 if ((info & CTF_VLA)) { /* Calculate VLA/VLS size at runtime. */
905 J->base[0] = trcd; 904 CTSize sz0, sz1;
906 if (J->base[1] && !J->base[2] && 905 if (!J->base[1] || J->base[2])
906 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init VLA/VLS. */
907 trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0,
908 J->base[1], &rd->argv[1]);
909 sz0 = lj_ctype_vlsize(cts, d, 0);
910 sz1 = lj_ctype_vlsize(cts, d, 1);
911 trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0)));
912 trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0));
913 J->base[1] = 0; /* Simplify logic below. */
914 } else if (ctype_align(info) > CT_MEMALIGN) {
915 trsz = lj_ir_kint(J, sz);
916 }
917 trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz);
918 if (sz > 128 || (info & CTF_VLA)) {
919 TRef dp;
920 CTSize align;
921 special: /* Only handle bulk zero-fill for large/VLA/VLS types. */
922 if (J->base[1])
923 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init large/VLA/VLS types. */
924 dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
925 if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz);
926 align = ctype_align(info);
927 if (align < CT_MEMALIGN) align = CT_MEMALIGN;
928 crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align));
929 } else if (J->base[1] && !J->base[2] &&
907 !lj_cconv_multi_init(cts, d, &rd->argv[1])) { 930 !lj_cconv_multi_init(cts, d, &rd->argv[1])) {
908 goto single_init; 931 goto single_init;
909 } else if (ctype_isarray(d->info)) { 932 } else if (ctype_isarray(d->info)) {
@@ -914,8 +937,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
914 TValue *sval = &tv; 937 TValue *sval = &tv;
915 MSize i; 938 MSize i;
916 tv.u64 = 0; 939 tv.u64 = 0;
917 if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) 940 if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) ||
918 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ 941 esize * CREC_FILL_MAXUNROLL < sz)
942 goto special;
919 for (i = 1, ofs = 0; ofs < sz; ofs += esize) { 943 for (i = 1, ofs = 0; ofs < sz; ofs += esize) {
920 TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, 944 TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
921 lj_ir_kintp(J, ofs + sizeof(GCcdata))); 945 lj_ir_kintp(J, ofs + sizeof(GCcdata)));
@@ -972,11 +996,12 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
972 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); 996 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
973 } 997 }
974 } 998 }
975 /* Handle __gc metamethod. */
976 fin = lj_ctype_meta(cts, id, MM_gc);
977 if (fin)
978 crec_finalizer(J, trcd, fin);
979 } 999 }
1000 J->base[0] = trcd;
1001 /* Handle __gc metamethod. */
1002 fin = lj_ctype_meta(cts, id, MM_gc);
1003 if (fin)
1004 crec_finalizer(J, trcd, fin);
980} 1005}
981 1006
982/* Record argument conversions. */ 1007/* Record argument conversions. */
diff --git a/src/lj_ircall.h b/src/lj_ircall.h
index 7271ceca..bdcfea0b 100644
--- a/src/lj_ircall.h
+++ b/src/lj_ircall.h
@@ -202,6 +202,7 @@ typedef struct CCallInfo {
202 _(FFI, lj_carith_modu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \ 202 _(FFI, lj_carith_modu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \
203 _(FFI, lj_carith_powi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \ 203 _(FFI, lj_carith_powi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \
204 _(FFI, lj_carith_powu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \ 204 _(FFI, lj_carith_powu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \
205 _(FFI, lj_cdata_newv, 4, S, CDATA, CCI_L) \
205 _(FFI, lj_cdata_setfin, 2, FN, P32, CCI_L) \ 206 _(FFI, lj_cdata_setfin, 2, FN, P32, CCI_L) \
206 _(FFI, strlen, 1, L, INTP, 0) \ 207 _(FFI, strlen, 1, L, INTP, 0) \
207 _(FFI, memcpy, 3, S, PTR, 0) \ 208 _(FFI, memcpy, 3, S, PTR, 0) \
diff --git a/src/lj_target_mips.h b/src/lj_target_mips.h
index 36f46c83..9bf1d2cb 100644
--- a/src/lj_target_mips.h
+++ b/src/lj_target_mips.h
@@ -169,6 +169,9 @@ typedef enum MIPSIns {
169 MIPSI_SLTU = 0x0000002b, 169 MIPSI_SLTU = 0x0000002b,
170 MIPSI_MOVZ = 0x0000000a, 170 MIPSI_MOVZ = 0x0000000a,
171 MIPSI_MOVN = 0x0000000b, 171 MIPSI_MOVN = 0x0000000b,
172 MIPSI_MFHI = 0x00000010,
173 MIPSI_MFLO = 0x00000012,
174 MIPSI_MULT = 0x00000018,
172 175
173 MIPSI_SLL = 0x00000000, 176 MIPSI_SLL = 0x00000000,
174 MIPSI_SRL = 0x00000002, 177 MIPSI_SRL = 0x00000002,