diff options
-rw-r--r-- | doc/ext_ffi_semantics.html | 5 | ||||
-rw-r--r-- | src/lj_asm.c | 11 | ||||
-rw-r--r-- | src/lj_asm_arm.h | 29 | ||||
-rw-r--r-- | src/lj_asm_mips.h | 44 | ||||
-rw-r--r-- | src/lj_asm_ppc.h | 29 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 25 | ||||
-rw-r--r-- | src/lj_crecord.c | 53 | ||||
-rw-r--r-- | src/lj_ircall.h | 1 | ||||
-rw-r--r-- | src/lj_target_mips.h | 3 |
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 types |
1223 | <li>Allocations of C types with a size > 128 bytes or an | 1223 | (> 128 bytes or > 16 array elements.</li> |
1224 | alignment > 8 bytes.</li> | ||
1225 | <li>Conversions from lightuserdata to <tt>void *</tt>.</li> | 1224 | <li>Conversions from lightuserdata to <tt>void *</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 |
1227 | two.</li> | 1226 | two.</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: | |||
1209 | static void asm_cnew(ASMState *as, IRIns *ir) | 1209 | static 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: | |||
975 | static void asm_cnew(ASMState *as, IRIns *ir) | 975 | static 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 | ||
1198 | static void asm_mulov(ASMState *as, IRIns *ir) | 1207 | static 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: | |||
1009 | static void asm_cnew(ASMState *as, IRIns *ir) | 1009 | static 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) | |||
1438 | static void asm_cnew(ASMState *as, IRIns *ir) | 1438 | static 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, |