diff options
author | Mike Pall <mike> | 2021-09-19 17:38:49 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2021-09-19 17:38:49 +0200 |
commit | c6f5ef649b645db9cf3d11d1b5c63602c49c6411 (patch) | |
tree | 4d299528ff4e77c2f9059b8e24c50755ff638d2d | |
parent | 4e0ea654a81e68b1bcd20ddc2026ff1bc9288b84 (diff) | |
download | luajit-c6f5ef649b645db9cf3d11d1b5c63602c49c6411.tar.gz luajit-c6f5ef649b645db9cf3d11d1b5c63602c49c6411.tar.bz2 luajit-c6f5ef649b645db9cf3d11d1b5c63602c49c6411.zip |
Refactor table traversal.
Sponsored by OpenResty Inc.
-rw-r--r-- | src/lib_base.c | 1 | ||||
-rw-r--r-- | src/lj_api.c | 8 | ||||
-rw-r--r-- | src/lj_obj.h | 3 | ||||
-rw-r--r-- | src/lj_tab.c | 56 | ||||
-rw-r--r-- | src/lj_tab.h | 3 | ||||
-rw-r--r-- | src/vm_arm.dasc | 28 | ||||
-rw-r--r-- | src/vm_arm64.dasc | 24 | ||||
-rw-r--r-- | src/vm_mips.dasc | 38 | ||||
-rw-r--r-- | src/vm_mips64.dasc | 36 | ||||
-rw-r--r-- | src/vm_ppc.dasc | 49 | ||||
-rw-r--r-- | src/vm_x64.dasc | 52 | ||||
-rw-r--r-- | src/vm_x86.dasc | 62 |
12 files changed, 153 insertions, 207 deletions
diff --git a/src/lib_base.c b/src/lib_base.c index 1c8816f0..f16c66f5 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
@@ -79,6 +79,7 @@ LJ_STATIC_ASSERT((int)FF_next == FF_next_N); | |||
79 | LJLIB_ASM(next) | 79 | LJLIB_ASM(next) |
80 | { | 80 | { |
81 | lj_lib_checktab(L, 1); | 81 | lj_lib_checktab(L, 1); |
82 | lj_err_msg(L, LJ_ERR_NEXTIDX); | ||
82 | return FFH_UNREACHABLE; | 83 | return FFH_UNREACHABLE; |
83 | } | 84 | } |
84 | 85 | ||
diff --git a/src/lj_api.c b/src/lj_api.c index 18a7ecbc..8c60c058 100644 --- a/src/lj_api.c +++ b/src/lj_api.c | |||
@@ -893,11 +893,13 @@ LUA_API int lua_next(lua_State *L, int idx) | |||
893 | cTValue *t = index2adr(L, idx); | 893 | cTValue *t = index2adr(L, idx); |
894 | int more; | 894 | int more; |
895 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); | 895 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); |
896 | more = lj_tab_next(L, tabV(t), L->top-1); | 896 | more = lj_tab_next(tabV(t), L->top-1, L->top-1); |
897 | if (more) { | 897 | if (more > 0) { |
898 | incr_top(L); /* Return new key and value slot. */ | 898 | incr_top(L); /* Return new key and value slot. */ |
899 | } else { /* End of traversal. */ | 899 | } else if (!more) { /* End of traversal. */ |
900 | L->top--; /* Remove key slot. */ | 900 | L->top--; /* Remove key slot. */ |
901 | } else { | ||
902 | lj_err_msg(L, LJ_ERR_NEXTIDX); | ||
901 | } | 903 | } |
902 | return more; | 904 | return more; |
903 | } | 905 | } |
diff --git a/src/lj_obj.h b/src/lj_obj.h index 5547a79b..1a6445fc 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
@@ -284,6 +284,9 @@ typedef const TValue cTValue; | |||
284 | #define LJ_TISGCV (LJ_TSTR+1) | 284 | #define LJ_TISGCV (LJ_TSTR+1) |
285 | #define LJ_TISTABUD LJ_TTAB | 285 | #define LJ_TISTABUD LJ_TTAB |
286 | 286 | ||
287 | /* Type marker for slot holding a traversal index. Must be lightuserdata. */ | ||
288 | #define LJ_KEYINDEX 0xfffe7fffu | ||
289 | |||
287 | #if LJ_GC64 | 290 | #if LJ_GC64 |
288 | #define LJ_GCVMASK (((uint64_t)1 << 47) - 1) | 291 | #define LJ_GCVMASK (((uint64_t)1 << 47) - 1) |
289 | #endif | 292 | #endif |
diff --git a/src/lj_tab.c b/src/lj_tab.c index ed5fd2dd..4113839f 100644 --- a/src/lj_tab.c +++ b/src/lj_tab.c | |||
@@ -568,56 +568,66 @@ TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key) | |||
568 | 568 | ||
569 | /* -- Table traversal ----------------------------------------------------- */ | 569 | /* -- Table traversal ----------------------------------------------------- */ |
570 | 570 | ||
571 | /* Get the traversal index of a key. */ | 571 | /* Table traversal indexes: |
572 | static uint32_t keyindex(lua_State *L, GCtab *t, cTValue *key) | 572 | ** |
573 | ** Array key index: [0 .. t->asize-1] | ||
574 | ** Hash key index: [t->asize .. t->asize+t->hmask] | ||
575 | ** Invalid key: ~0 | ||
576 | */ | ||
577 | |||
578 | /* Get the successor traversal index of a key. */ | ||
579 | uint32_t LJ_FASTCALL lj_tab_keyindex(GCtab *t, cTValue *key) | ||
573 | { | 580 | { |
574 | TValue tmp; | 581 | TValue tmp; |
575 | if (tvisint(key)) { | 582 | if (tvisint(key)) { |
576 | int32_t k = intV(key); | 583 | int32_t k = intV(key); |
577 | if ((uint32_t)k < t->asize) | 584 | if ((uint32_t)k < t->asize) |
578 | return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */ | 585 | return (uint32_t)k + 1; |
579 | setnumV(&tmp, (lua_Number)k); | 586 | setnumV(&tmp, (lua_Number)k); |
580 | key = &tmp; | 587 | key = &tmp; |
581 | } else if (tvisnum(key)) { | 588 | } else if (tvisnum(key)) { |
582 | lua_Number nk = numV(key); | 589 | lua_Number nk = numV(key); |
583 | int32_t k = lj_num2int(nk); | 590 | int32_t k = lj_num2int(nk); |
584 | if ((uint32_t)k < t->asize && nk == (lua_Number)k) | 591 | if ((uint32_t)k < t->asize && nk == (lua_Number)k) |
585 | return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */ | 592 | return (uint32_t)k + 1; |
586 | } | 593 | } |
587 | if (!tvisnil(key)) { | 594 | if (!tvisnil(key)) { |
588 | Node *n = hashkey(t, key); | 595 | Node *n = hashkey(t, key); |
589 | do { | 596 | do { |
590 | if (lj_obj_equal(&n->key, key)) | 597 | if (lj_obj_equal(&n->key, key)) |
591 | return t->asize + (uint32_t)(n - noderef(t->node)); | 598 | return t->asize + (uint32_t)((n+1) - noderef(t->node)); |
592 | /* Hash key indexes: [t->asize..t->asize+t->nmask] */ | ||
593 | } while ((n = nextnode(n))); | 599 | } while ((n = nextnode(n))); |
594 | if (key->u32.hi == 0xfffe7fff) /* ITERN was despecialized while running. */ | 600 | if (key->u32.hi == LJ_KEYINDEX) /* Despecialized ITERN while running. */ |
595 | return key->u32.lo - 1; | 601 | return key->u32.lo; |
596 | lj_err_msg(L, LJ_ERR_NEXTIDX); | 602 | return ~0u; /* Invalid key to next. */ |
597 | return 0; /* unreachable */ | ||
598 | } | 603 | } |
599 | return ~0u; /* A nil key starts the traversal. */ | 604 | return 0; /* A nil key starts the traversal. */ |
600 | } | 605 | } |
601 | 606 | ||
602 | /* Advance to the next step in a table traversal. */ | 607 | /* Get the next key/value pair of a table traversal. */ |
603 | int lj_tab_next(lua_State *L, GCtab *t, TValue *key) | 608 | int lj_tab_next(GCtab *t, cTValue *key, TValue *o) |
604 | { | 609 | { |
605 | uint32_t i = keyindex(L, t, key); /* Find predecessor key index. */ | 610 | uint32_t idx = lj_tab_keyindex(t, key); /* Find successor index of key. */ |
606 | for (i++; i < t->asize; i++) /* First traverse the array keys. */ | 611 | /* First traverse the array part. */ |
607 | if (!tvisnil(arrayslot(t, i))) { | 612 | for (; idx < t->asize; idx++) { |
608 | setintV(key, i); | 613 | cTValue *a = arrayslot(t, idx); |
609 | copyTV(L, key+1, arrayslot(t, i)); | 614 | if (LJ_LIKELY(!tvisnil(a))) { |
615 | setintV(o, idx); | ||
616 | o[1] = *a; | ||
610 | return 1; | 617 | return 1; |
611 | } | 618 | } |
612 | for (i -= t->asize; i <= t->hmask; i++) { /* Then traverse the hash keys. */ | 619 | } |
613 | Node *n = &noderef(t->node)[i]; | 620 | idx -= t->asize; |
621 | /* Then traverse the hash part. */ | ||
622 | for (; idx <= t->hmask; idx++) { | ||
623 | Node *n = &noderef(t->node)[idx]; | ||
614 | if (!tvisnil(&n->val)) { | 624 | if (!tvisnil(&n->val)) { |
615 | copyTV(L, key, &n->key); | 625 | o[0] = n->key; |
616 | copyTV(L, key+1, &n->val); | 626 | o[1] = n->val; |
617 | return 1; | 627 | return 1; |
618 | } | 628 | } |
619 | } | 629 | } |
620 | return 0; /* End of traversal. */ | 630 | return (int32_t)idx < 0 ? -1 : 0; /* Invalid key or end of traversal. */ |
621 | } | 631 | } |
622 | 632 | ||
623 | /* -- Table length calculation -------------------------------------------- */ | 633 | /* -- Table length calculation -------------------------------------------- */ |
diff --git a/src/lj_tab.h b/src/lj_tab.h index 1efa9506..e0e81ff7 100644 --- a/src/lj_tab.h +++ b/src/lj_tab.h | |||
@@ -86,7 +86,8 @@ LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); | |||
86 | #define lj_tab_setint(L, t, key) \ | 86 | #define lj_tab_setint(L, t, key) \ |
87 | (inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_setinth(L, (t), (key))) | 87 | (inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_setinth(L, (t), (key))) |
88 | 88 | ||
89 | LJ_FUNCA int lj_tab_next(lua_State *L, GCtab *t, TValue *key); | 89 | LJ_FUNC uint32_t LJ_FASTCALL lj_tab_keyindex(GCtab *t, cTValue *key); |
90 | LJ_FUNCA int lj_tab_next(GCtab *t, cTValue *key, TValue *o); | ||
90 | LJ_FUNCA MSize LJ_FASTCALL lj_tab_len(GCtab *t); | 91 | LJ_FUNCA MSize LJ_FASTCALL lj_tab_len(GCtab *t); |
91 | #if LJ_HASJIT | 92 | #if LJ_HASJIT |
92 | LJ_FUNC MSize LJ_FASTCALL lj_tab_len_hint(GCtab *t, size_t hint); | 93 | LJ_FUNC MSize LJ_FASTCALL lj_tab_len_hint(GCtab *t, size_t hint); |
diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index 35ba0e36..0e80bf00 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc | |||
@@ -1111,24 +1111,18 @@ static void build_subroutines(BuildCtx *ctx) | |||
1111 | | checktab CARG2, ->fff_fallback | 1111 | | checktab CARG2, ->fff_fallback |
1112 | | strd CARG34, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. | 1112 | | strd CARG34, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. |
1113 | | ldr PC, [BASE, FRAME_PC] | 1113 | | ldr PC, [BASE, FRAME_PC] |
1114 | | mov CARG2, CARG1 | 1114 | | add CARG2, BASE, #8 |
1115 | | str BASE, L->base // Add frame since C call can throw. | 1115 | | sub CARG3, BASE, #8 |
1116 | | mov CARG1, L | 1116 | | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1117 | | str BASE, L->top // Dummy frame length is ok. | 1117 | | // Returns 1=found, 0=end, -1=error. |
1118 | | add CARG3, BASE, #8 | ||
1119 | | str PC, SAVE_PC | ||
1120 | | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | ||
1121 | | // Returns 0 at end of traversal. | ||
1122 | | .IOS ldr BASE, L->base | 1118 | | .IOS ldr BASE, L->base |
1123 | | cmp CRET1, #0 | 1119 | | cmp CRET1, #0 |
1124 | | mvneq CRET2, #~LJ_TNIL | 1120 | | mov RC, #(2+1)*8 |
1125 | | beq ->fff_restv // End of traversal: return nil. | 1121 | | bgt ->fff_res // Found key/value. |
1126 | | ldrd CARG12, [BASE, #8] // Copy key and value to results. | 1122 | | bmi ->fff_fallback // Invalid key. |
1127 | | ldrd CARG34, [BASE, #16] | 1123 | | // End of traversal: return nil. |
1128 | | mov RC, #(2+1)*8 | 1124 | | mvn CRET2, #~LJ_TNIL |
1129 | | strd CARG12, [BASE, #-8] | 1125 | | b ->fff_restv |
1130 | | strd CARG34, [BASE] | ||
1131 | | b ->fff_res | ||
1132 | | | 1126 | | |
1133 | |.ffunc_1 pairs | 1127 | |.ffunc_1 pairs |
1134 | | checktab CARG2, ->fff_fallback | 1128 | | checktab CARG2, ->fff_fallback |
@@ -3989,7 +3983,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3989 | | ins_next1 | 3983 | | ins_next1 |
3990 | | ins_next2 | 3984 | | ins_next2 |
3991 | | mov CARG1, #0 | 3985 | | mov CARG1, #0 |
3992 | | mvn CARG2, #0x00018000 | 3986 | | mvn CARG2, #~LJ_KEYINDEX |
3993 | | strd CARG1, [RA, #-8] // Initialize control var. | 3987 | | strd CARG1, [RA, #-8] // Initialize control var. |
3994 | |1: | 3988 | |1: |
3995 | | ins_next3 | 3989 | | ins_next3 |
diff --git a/src/vm_arm64.dasc b/src/vm_arm64.dasc index 92f89cd6..2a2e3a9a 100644 --- a/src/vm_arm64.dasc +++ b/src/vm_arm64.dasc | |||
@@ -1086,21 +1086,19 @@ static void build_subroutines(BuildCtx *ctx) | |||
1086 | |//-- Base library: iterators ------------------------------------------- | 1086 | |//-- Base library: iterators ------------------------------------------- |
1087 | | | 1087 | | |
1088 | |.ffunc_1 next | 1088 | |.ffunc_1 next |
1089 | | checktp CARG2, CARG1, LJ_TTAB, ->fff_fallback | 1089 | | checktp CARG1, LJ_TTAB, ->fff_fallback |
1090 | | str TISNIL, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. | 1090 | | str TISNIL, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. |
1091 | | ldr PC, [BASE, FRAME_PC] | 1091 | | ldr PC, [BASE, FRAME_PC] |
1092 | | stp BASE, BASE, L->base // Add frame since C call can throw. | 1092 | | add CARG2, BASE, #8 |
1093 | | mov CARG1, L | 1093 | | sub CARG3, BASE, #16 |
1094 | | add CARG3, BASE, #8 | 1094 | | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1095 | | str PC, SAVE_PC | 1095 | | // Returns 1=found, 0=end, -1=error. |
1096 | | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | 1096 | | mov RC, #(2+1)*8 |
1097 | | // Returns 0 at end of traversal. | 1097 | | tbnz CRET1w, #31, ->fff_fallback // Invalid key. |
1098 | | cbnz CRET1, ->fff_res // Found key/value. | ||
1099 | | // End of traversal: return nil. | ||
1098 | | str TISNIL, [BASE, #-16] | 1100 | | str TISNIL, [BASE, #-16] |
1099 | | cbz CRET1, ->fff_res1 // End of traversal: return nil. | 1101 | | b ->fff_res1 |
1100 | | ldp CARG1, CARG2, [BASE, #8] // Copy key and value to results. | ||
1101 | | mov RC, #(2+1)*8 | ||
1102 | | stp CARG1, CARG2, [BASE, #-16] | ||
1103 | | b ->fff_res | ||
1104 | | | 1102 | | |
1105 | |.ffunc_1 pairs | 1103 | |.ffunc_1 pairs |
1106 | | checktp TMP1, CARG1, LJ_TTAB, ->fff_fallback | 1104 | | checktp TMP1, CARG1, LJ_TTAB, ->fff_fallback |
@@ -3384,7 +3382,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
3384 | | ccmp CARG4, TISNIL, #0, eq | 3382 | | ccmp CARG4, TISNIL, #0, eq |
3385 | | ccmp TMP1w, #FF_next_N, #0, eq | 3383 | | ccmp TMP1w, #FF_next_N, #0, eq |
3386 | | bne >5 | 3384 | | bne >5 |
3387 | | mov TMP0w, #0xfffe7fff | 3385 | | mov TMP0w, #0xfffe7fff // LJ_KEYINDEX |
3388 | | lsl TMP0, TMP0, #32 | 3386 | | lsl TMP0, TMP0, #32 |
3389 | | str TMP0, [RA, #-8] // Initialize control var. | 3387 | | str TMP0, [RA, #-8] // Initialize control var. |
3390 | |1: | 3388 | |1: |
diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index 7bd86514..3b0ea4a2 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc | |||
@@ -1262,35 +1262,27 @@ static void build_subroutines(BuildCtx *ctx) | |||
1262 | |//-- Base library: iterators ------------------------------------------- | 1262 | |//-- Base library: iterators ------------------------------------------- |
1263 | | | 1263 | | |
1264 | |.ffunc next | 1264 | |.ffunc next |
1265 | | lw CARG1, HI(BASE) | 1265 | | lw CARG2, HI(BASE) |
1266 | | lw TAB:CARG2, LO(BASE) | 1266 | | lw TAB:CARG1, LO(BASE) |
1267 | | beqz NARGS8:RC, ->fff_fallback | 1267 | | beqz NARGS8:RC, ->fff_fallback |
1268 | |. addu TMP2, BASE, NARGS8:RC | 1268 | |. addu TMP2, BASE, NARGS8:RC |
1269 | | li AT, LJ_TTAB | 1269 | | li AT, LJ_TTAB |
1270 | | sw TISNIL, HI(TMP2) // Set missing 2nd arg to nil. | 1270 | | sw TISNIL, HI(TMP2) // Set missing 2nd arg to nil. |
1271 | | bne CARG1, AT, ->fff_fallback | 1271 | | bne CARG2, AT, ->fff_fallback |
1272 | |. lw PC, FRAME_PC(BASE) | 1272 | |. lw PC, FRAME_PC(BASE) |
1273 | | load_got lj_tab_next | 1273 | | load_got lj_tab_next |
1274 | | sw BASE, L->base // Add frame since C call can throw. | 1274 | | addiu CARG2, BASE, 8 |
1275 | | sw BASE, L->top // Dummy frame length is ok. | 1275 | | call_intern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1276 | | addiu CARG3, BASE, 8 | 1276 | |. addiu CARG3, BASE, -8 |
1277 | | sw PC, SAVE_PC | 1277 | | // Returns 1=found, 0=end, -1=error. |
1278 | | call_intern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | 1278 | | addiu RA, BASE, -8 |
1279 | |. move CARG1, L | 1279 | | bgtz CRET1, ->fff_res // Found key/value. |
1280 | | // Returns 0 at end of traversal. | 1280 | |. li RD, (2+1)*8 |
1281 | | beqz CRET1, ->fff_restv // End of traversal: return nil. | 1281 | | beqz CRET1, ->fff_restv // End of traversal: return nil. |
1282 | |. li SFARG1HI, LJ_TNIL | 1282 | |. li SFARG1HI, LJ_TNIL |
1283 | | lw TMP0, 8+HI(BASE) | 1283 | | lw CFUNC:RB, FRAME_FUNC(BASE) |
1284 | | lw TMP1, 8+LO(BASE) | 1284 | | b ->fff_fallback // Invalid key. |
1285 | | addiu RA, BASE, -8 | 1285 | |. li RC, 2*8 |
1286 | | lw TMP2, 16+HI(BASE) | ||
1287 | | lw TMP3, 16+LO(BASE) | ||
1288 | | sw TMP0, HI(RA) | ||
1289 | | sw TMP1, LO(RA) | ||
1290 | | sw TMP2, 8+HI(RA) | ||
1291 | | sw TMP3, 8+LO(RA) | ||
1292 | | b ->fff_res | ||
1293 | |. li RD, (2+1)*8 | ||
1294 | | | 1286 | | |
1295 | |.ffunc_1 pairs | 1287 | |.ffunc_1 pairs |
1296 | | li AT, LJ_TTAB | 1288 | | li AT, LJ_TTAB |
@@ -4611,9 +4603,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4611 | | addiu CARG2, CARG2, -FF_next_N | 4603 | | addiu CARG2, CARG2, -FF_next_N |
4612 | | or CARG2, CARG2, CARG3 | 4604 | | or CARG2, CARG2, CARG3 |
4613 | | bnez CARG2, >5 | 4605 | | bnez CARG2, >5 |
4614 | |. lui TMP1, 0xfffe | 4606 | |. lui TMP1, (LJ_KEYINDEX >> 16) |
4615 | | addu PC, TMP0, TMP2 | 4607 | | addu PC, TMP0, TMP2 |
4616 | | ori TMP1, TMP1, 0x7fff | 4608 | | ori TMP1, TMP1, (LJ_KEYINDEX & 0xffff) |
4617 | | sw r0, -8+LO(RA) // Initialize control var. | 4609 | | sw r0, -8+LO(RA) // Initialize control var. |
4618 | | sw TMP1, -8+HI(RA) | 4610 | | sw TMP1, -8+HI(RA) |
4619 | |1: | 4611 | |1: |
diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc index 05395ffd..0d28326a 100644 --- a/src/vm_mips64.dasc +++ b/src/vm_mips64.dasc | |||
@@ -1322,27 +1322,24 @@ static void build_subroutines(BuildCtx *ctx) | |||
1322 | |//-- Base library: iterators ------------------------------------------- | 1322 | |//-- Base library: iterators ------------------------------------------- |
1323 | | | 1323 | | |
1324 | |.ffunc_1 next | 1324 | |.ffunc_1 next |
1325 | | checktp CARG2, CARG1, -LJ_TTAB, ->fff_fallback | 1325 | | checktp CARG1, -LJ_TTAB, ->fff_fallback |
1326 | | daddu TMP2, BASE, NARGS8:RC | 1326 | | daddu TMP2, BASE, NARGS8:RC |
1327 | | sd TISNIL, 0(TMP2) // Set missing 2nd arg to nil. | 1327 | | sd TISNIL, 0(TMP2) // Set missing 2nd arg to nil. |
1328 | | ld PC, FRAME_PC(BASE) | ||
1329 | | load_got lj_tab_next | 1328 | | load_got lj_tab_next |
1330 | | sd BASE, L->base // Add frame since C call can throw. | 1329 | | ld PC, FRAME_PC(BASE) |
1331 | | sd BASE, L->top // Dummy frame length is ok. | 1330 | | daddiu CARG2, BASE, 8 |
1332 | | daddiu CARG3, BASE, 8 | 1331 | | call_intern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1333 | | sd PC, SAVE_PC | 1332 | |. daddiu CARG3, BASE, -16 |
1334 | | call_intern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | 1333 | | // Returns 1=found, 0=end, -1=error. |
1335 | |. move CARG1, L | 1334 | | daddiu RA, BASE, -16 |
1336 | | // Returns 0 at end of traversal. | 1335 | | bgtz CRET1, ->fff_res // Found key/value. |
1336 | |. li RD, (2+1)*8 | ||
1337 | | beqz CRET1, ->fff_restv // End of traversal: return nil. | 1337 | | beqz CRET1, ->fff_restv // End of traversal: return nil. |
1338 | |. move CARG1, TISNIL | 1338 | |. move CARG1, TISNIL |
1339 | | ld TMP0, 8(BASE) | 1339 | | ld CFUNC:RB, FRAME_FUNC(BASE) |
1340 | | daddiu RA, BASE, -16 | 1340 | | cleartp CFUNC:RB |
1341 | | ld TMP2, 16(BASE) | 1341 | | b ->fff_fallback // Invalid key. |
1342 | | sd TMP0, 0(RA) | 1342 | |. li RC, 2*8 |
1343 | | sd TMP2, 8(RA) | ||
1344 | | b ->fff_res | ||
1345 | |. li RD, (2+1)*8 | ||
1346 | | | 1343 | | |
1347 | |.ffunc_1 pairs | 1344 | |.ffunc_1 pairs |
1348 | | checktp TAB:TMP1, CARG1, -LJ_TTAB, ->fff_fallback | 1345 | | checktp TAB:TMP1, CARG1, -LJ_TTAB, ->fff_fallback |
@@ -4727,11 +4724,10 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4727 | |. addiu RC, RC, 1 | 4724 | |. addiu RC, RC, 1 |
4728 | | sd TMP2, 0(RA) | 4725 | | sd TMP2, 0(RA) |
4729 | | sd CARG1, 8(RA) | 4726 | | sd CARG1, 8(RA) |
4730 | | or TMP0, RC, CARG3 | ||
4731 | | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) | 4727 | | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) |
4732 | | decode_RD4b RD | 4728 | | decode_RD4b RD |
4733 | | daddu RD, RD, TMP3 | 4729 | | daddu RD, RD, TMP3 |
4734 | | sw TMP0, -8+LO(RA) // Update control var. | 4730 | | sw RC, -8+LO(RA) // Update control var. |
4735 | | daddu PC, PC, RD | 4731 | | daddu PC, PC, RD |
4736 | |3: | 4732 | |3: |
4737 | | ins_next | 4733 | | ins_next |
@@ -4781,9 +4777,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4781 | | daddiu TMP1, TMP1, -FF_next_N | 4777 | | daddiu TMP1, TMP1, -FF_next_N |
4782 | | or AT, AT, TMP1 | 4778 | | or AT, AT, TMP1 |
4783 | | bnez AT, >5 | 4779 | | bnez AT, >5 |
4784 | |. lui TMP1, 0xfffe | 4780 | |. lui TMP1, (LJ_KEYINDEX >> 16) |
4785 | | daddu PC, TMP0, TMP2 | 4781 | | daddu PC, TMP0, TMP2 |
4786 | | ori TMP1, TMP1, 0x7fff | 4782 | | ori TMP1, TMP1, (LJ_KEYINDEX & 0xffff) |
4787 | | dsll TMP1, TMP1, 32 | 4783 | | dsll TMP1, TMP1, 32 |
4788 | | sd TMP1, -8(RA) | 4784 | | sd TMP1, -8(RA) |
4789 | |1: | 4785 | |1: |
diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index 6aa00c5b..d4133a65 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc | |||
@@ -1559,43 +1559,24 @@ static void build_subroutines(BuildCtx *ctx) | |||
1559 | | | 1559 | | |
1560 | |//-- Base library: iterators ------------------------------------------- | 1560 | |//-- Base library: iterators ------------------------------------------- |
1561 | | | 1561 | | |
1562 | |.ffunc next | 1562 | |.ffunc_1 next |
1563 | | cmplwi NARGS8:RC, 8 | ||
1564 | | lwz CARG1, 0(BASE) | ||
1565 | | lwz TAB:CARG2, 4(BASE) | ||
1566 | | blt ->fff_fallback | ||
1567 | | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. | 1563 | | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. |
1568 | | checktab CARG1 | 1564 | | checktab CARG3 |
1569 | | lwz PC, FRAME_PC(BASE) | 1565 | | lwz PC, FRAME_PC(BASE) |
1570 | | bne ->fff_fallback | 1566 | | bne ->fff_fallback |
1571 | | stp BASE, L->base // Add frame since C call can throw. | 1567 | | la CARG2, 8(BASE) |
1572 | | mr CARG1, L | 1568 | | la CARG3, -8(BASE) |
1573 | | stp BASE, L->top // Dummy frame length is ok. | 1569 | | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1574 | | la CARG3, 8(BASE) | 1570 | | // Returns 1=found, 0=end, -1=error. |
1575 | | stw PC, SAVE_PC | 1571 | | cmpwi CRET1, 0 |
1576 | | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | ||
1577 | | // Returns 0 at end of traversal. | ||
1578 | | cmplwi CRET1, 0 | ||
1579 | | li CARG3, LJ_TNIL | ||
1580 | | beq ->fff_restv // End of traversal: return nil. | ||
1581 | | la RA, -8(BASE) | 1572 | | la RA, -8(BASE) |
1582 | |.if FPU | ||
1583 | | lfd f0, 8(BASE) // Copy key and value to results. | ||
1584 | | lfd f1, 16(BASE) | ||
1585 | | stfd f0, 0(RA) | ||
1586 | | stfd f1, 8(RA) | ||
1587 | |.else | ||
1588 | | lwz CARG1, 8(BASE) | ||
1589 | | lwz CARG2, 12(BASE) | ||
1590 | | lwz CARG3, 16(BASE) | ||
1591 | | lwz CARG4, 20(BASE) | ||
1592 | | stw CARG1, 0(RA) | ||
1593 | | stw CARG2, 4(RA) | ||
1594 | | stw CARG3, 8(RA) | ||
1595 | | stw CARG4, 12(RA) | ||
1596 | |.endif | ||
1597 | | li RD, (2+1)*8 | 1573 | | li RD, (2+1)*8 |
1598 | | b ->fff_res | 1574 | | bgt ->fff_res // Found key/value. |
1575 | | li CARG3, LJ_TNIL | ||
1576 | | beq ->fff_restv // End of traversal: return nil. | ||
1577 | | lwz CFUNC:RB, FRAME_FUNC(BASE) | ||
1578 | | li NARGS8:RC, 2*8 | ||
1579 | | b ->fff_fallback // Invalid key. | ||
1599 | | | 1580 | | |
1600 | |.ffunc_1 pairs | 1581 | |.ffunc_1 pairs |
1601 | | checktab CARG3 | 1582 | | checktab CARG3 |
@@ -5251,8 +5232,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
5251 | | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq | 5232 | | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq |
5252 | | add TMP3, PC, TMP0 | 5233 | | add TMP3, PC, TMP0 |
5253 | | bne cr0, >5 | 5234 | | bne cr0, >5 |
5254 | | lus TMP1, 0xfffe | 5235 | | lus TMP1, (LJ_KEYINDEX >> 16) |
5255 | | ori TMP1, TMP1, 0x7fff | 5236 | | ori TMP1, TMP1, (LJ_KEYINDEX & 0xffff) |
5256 | | stw ZERO, -4(RA) // Initialize control var. | 5237 | | stw ZERO, -4(RA) // Initialize control var. |
5257 | | stw TMP1, -8(RA) | 5238 | | stw TMP1, -8(RA) |
5258 | | addis PC, TMP3, -(BCBIAS_J*4 >> 16) | 5239 | | addis PC, TMP3, -(BCBIAS_J*4 >> 16) |
diff --git a/src/vm_x64.dasc b/src/vm_x64.dasc index 76ce071d..d2119bc4 100644 --- a/src/vm_x64.dasc +++ b/src/vm_x64.dasc | |||
@@ -1346,44 +1346,28 @@ static void build_subroutines(BuildCtx *ctx) | |||
1346 | |.ffunc_1 next | 1346 | |.ffunc_1 next |
1347 | | je >2 // Missing 2nd arg? | 1347 | | je >2 // Missing 2nd arg? |
1348 | |1: | 1348 | |1: |
1349 | |.if X64WIN | 1349 | | mov CARG1, [BASE] |
1350 | | mov RA, [BASE] | ||
1351 | | checktab RA, ->fff_fallback | ||
1352 | |.else | ||
1353 | | mov CARG2, [BASE] | ||
1354 | | checktab CARG2, ->fff_fallback | ||
1355 | |.endif | ||
1356 | | mov L:RB, SAVE_L | ||
1357 | | mov L:RB->base, BASE // Add frame since C call can throw. | ||
1358 | | mov L:RB->top, BASE // Dummy frame length is ok. | ||
1359 | | mov PC, [BASE-8] | 1350 | | mov PC, [BASE-8] |
1351 | | checktab CARG1, ->fff_fallback | ||
1352 | | mov RB, BASE // Save BASE. | ||
1360 | |.if X64WIN | 1353 | |.if X64WIN |
1361 | | lea CARG3, [BASE+8] | 1354 | | lea CARG3, [BASE-16] |
1362 | | mov CARG2, RA // Caveat: CARG2 == BASE. | 1355 | | lea CARG2, [BASE+8] // Caveat: CARG2 == BASE. |
1363 | | mov CARG1, L:RB | ||
1364 | |.else | 1356 | |.else |
1365 | | lea CARG3, [BASE+8] // Caveat: CARG3 == BASE. | 1357 | | lea CARG2, [BASE+8] |
1366 | | mov CARG1, L:RB | 1358 | | lea CARG3, [BASE-16] // Caveat: CARG3 == BASE. |
1367 | |.endif | 1359 | |.endif |
1368 | | mov SAVE_PC, PC // Needed for ITERN fallback. | 1360 | | call extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1369 | | call extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | 1361 | | // 1=found, 0=end, -1=error returned in eax (RD). |
1370 | | // Flag returned in eax (RD). | 1362 | | mov BASE, RB // Restore BASE. |
1371 | | mov BASE, L:RB->base | 1363 | | test RDd, RDd; jg ->fff_res2 // Found key/value. |
1372 | | test RDd, RDd; jz >3 // End of traversal? | 1364 | | js ->fff_fallback_2 // Invalid key. |
1373 | | // Copy key and value to results. | 1365 | | // End of traversal: return nil. |
1374 | | mov RB, [BASE+8] | 1366 | | mov aword [BASE-16], LJ_TNIL |
1375 | | mov RD, [BASE+16] | 1367 | | jmp ->fff_res1 |
1376 | | mov [BASE-16], RB | ||
1377 | | mov [BASE-8], RD | ||
1378 | |->fff_res2: | ||
1379 | | mov RDd, 1+2 | ||
1380 | | jmp ->fff_res | ||
1381 | |2: // Set missing 2nd arg to nil. | 1368 | |2: // Set missing 2nd arg to nil. |
1382 | | mov aword [BASE+8], LJ_TNIL | 1369 | | mov aword [BASE+8], LJ_TNIL |
1383 | | jmp <1 | 1370 | | jmp <1 |
1384 | |3: // End of traversal: return nil. | ||
1385 | | mov aword [BASE-16], LJ_TNIL | ||
1386 | | jmp ->fff_res1 | ||
1387 | | | 1371 | | |
1388 | |.ffunc_1 pairs | 1372 | |.ffunc_1 pairs |
1389 | | mov TAB:RB, [BASE] | 1373 | | mov TAB:RB, [BASE] |
@@ -1432,7 +1416,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
1432 | | // Copy array slot. | 1416 | | // Copy array slot. |
1433 | | mov RB, [RD] | 1417 | | mov RB, [RD] |
1434 | | mov [BASE-8], RB | 1418 | | mov [BASE-8], RB |
1435 | | jmp ->fff_res2 | 1419 | |->fff_res2: |
1420 | | mov RDd, 1+2 | ||
1421 | | jmp ->fff_res | ||
1436 | |2: // Check for empty hash part first. Otherwise call C function. | 1422 | |2: // Check for empty hash part first. Otherwise call C function. |
1437 | | cmp dword TAB:RB->hmask, 0; je ->fff_res0 | 1423 | | cmp dword TAB:RB->hmask, 0; je ->fff_res0 |
1438 | |.if X64WIN | 1424 | |.if X64WIN |
@@ -4125,7 +4111,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4125 | | cmp aword [BASE+RA*8-8], LJ_TNIL; jne >5 | 4111 | | cmp aword [BASE+RA*8-8], LJ_TNIL; jne >5 |
4126 | | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 | 4112 | | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 |
4127 | | branchPC RD | 4113 | | branchPC RD |
4128 | | mov64 TMPR, U64x(fffe7fff, 00000000) | 4114 | | mov64 TMPR, ((uint64_t)LJ_KEYINDEX << 32) |
4129 | | mov [BASE+RA*8-8], TMPR // Initialize control var. | 4115 | | mov [BASE+RA*8-8], TMPR // Initialize control var. |
4130 | |1: | 4116 | |1: |
4131 | | ins_next | 4117 | | ins_next |
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index 81b899fa..718cb8f0 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc | |||
@@ -1673,55 +1673,35 @@ static void build_subroutines(BuildCtx *ctx) | |||
1673 | | je >2 // Missing 2nd arg? | 1673 | | je >2 // Missing 2nd arg? |
1674 | |1: | 1674 | |1: |
1675 | | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback | 1675 | | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback |
1676 | | mov L:RB, SAVE_L | ||
1677 | | mov L:RB->base, BASE // Add frame since C call can throw. | ||
1678 | | mov L:RB->top, BASE // Dummy frame length is ok. | ||
1679 | | mov PC, [BASE-4] | 1676 | | mov PC, [BASE-4] |
1677 | | mov RB, BASE // Save BASE. | ||
1680 | |.if X64WIN | 1678 | |.if X64WIN |
1681 | | lea CARG3d, [BASE+8] | 1679 | | mov CARG1d, [BASE] |
1682 | | mov CARG2d, [BASE] // Caveat: CARG2d == BASE. | 1680 | | lea CARG3d, [BASE-8] |
1683 | | mov CARG1d, L:RB | 1681 | | lea CARG2d, [BASE+8] // Caveat: CARG2d == BASE. |
1684 | |.elif X64 | 1682 | |.elif X64 |
1685 | | mov CARG2d, [BASE] | 1683 | | mov CARG1d, [BASE] |
1686 | | lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE. | 1684 | | lea CARG2d, [BASE+8] |
1687 | | mov CARG1d, L:RB | 1685 | | lea CARG3d, [BASE-8] // Caveat: CARG3d == BASE. |
1688 | |.else | 1686 | |.else |
1689 | | mov TAB:RD, [BASE] | 1687 | | mov TAB:RD, [BASE] |
1690 | | mov ARG2, TAB:RD | 1688 | | mov ARG1, TAB:RD |
1691 | | mov ARG1, L:RB | ||
1692 | | add BASE, 8 | 1689 | | add BASE, 8 |
1690 | | mov ARG2, BASE | ||
1691 | | sub BASE, 8+8 | ||
1693 | | mov ARG3, BASE | 1692 | | mov ARG3, BASE |
1694 | |.endif | 1693 | |.endif |
1695 | | mov SAVE_PC, PC // Needed for ITERN fallback. | 1694 | | call extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) |
1696 | | call extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) | 1695 | | // 1=found, 0=end, -1=error returned in eax (RD). |
1697 | | // Flag returned in eax (RD). | 1696 | | mov BASE, RB // Restore BASE. |
1698 | | mov BASE, L:RB->base | 1697 | | test RD, RD; jg ->fff_res2 // Found key/value. |
1699 | | test RD, RD; jz >3 // End of traversal? | 1698 | | js ->fff_fallback_2 // Invalid key. |
1700 | | // Copy key and value to results. | 1699 | | // End of traversal: return nil. |
1701 | |.if X64 | 1700 | | mov dword [BASE-4], LJ_TNIL |
1702 | | mov RBa, [BASE+8] | 1701 | | jmp ->fff_res1 |
1703 | | mov RDa, [BASE+16] | ||
1704 | | mov [BASE-8], RBa | ||
1705 | | mov [BASE], RDa | ||
1706 | |.else | ||
1707 | | mov RB, [BASE+8] | ||
1708 | | mov RD, [BASE+12] | ||
1709 | | mov [BASE-8], RB | ||
1710 | | mov [BASE-4], RD | ||
1711 | | mov RB, [BASE+16] | ||
1712 | | mov RD, [BASE+20] | ||
1713 | | mov [BASE], RB | ||
1714 | | mov [BASE+4], RD | ||
1715 | |.endif | ||
1716 | |->fff_res2: | ||
1717 | | mov RD, 1+2 | ||
1718 | | jmp ->fff_res | ||
1719 | |2: // Set missing 2nd arg to nil. | 1702 | |2: // Set missing 2nd arg to nil. |
1720 | | mov dword [BASE+12], LJ_TNIL | 1703 | | mov dword [BASE+12], LJ_TNIL |
1721 | | jmp <1 | 1704 | | jmp <1 |
1722 | |3: // End of traversal: return nil. | ||
1723 | | mov dword [BASE-4], LJ_TNIL | ||
1724 | | jmp ->fff_res1 | ||
1725 | | | 1705 | | |
1726 | |.ffunc_1 pairs | 1706 | |.ffunc_1 pairs |
1727 | | mov TAB:RB, [BASE] | 1707 | | mov TAB:RB, [BASE] |
@@ -1775,7 +1755,9 @@ static void build_subroutines(BuildCtx *ctx) | |||
1775 | | mov [BASE], RB | 1755 | | mov [BASE], RB |
1776 | | mov [BASE+4], RD | 1756 | | mov [BASE+4], RD |
1777 | |.endif | 1757 | |.endif |
1778 | | jmp ->fff_res2 | 1758 | |->fff_res2: |
1759 | | mov RD, 1+2 | ||
1760 | | jmp ->fff_res | ||
1779 | |2: // Check for empty hash part first. Otherwise call C function. | 1761 | |2: // Check for empty hash part first. Otherwise call C function. |
1780 | | cmp dword TAB:RB->hmask, 0; je ->fff_res0 | 1762 | | cmp dword TAB:RB->hmask, 0; je ->fff_res0 |
1781 | | mov FCARG1, TAB:RB | 1763 | | mov FCARG1, TAB:RB |
@@ -4880,7 +4862,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
4880 | | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 | 4862 | | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 |
4881 | | branchPC RD | 4863 | | branchPC RD |
4882 | | mov dword [BASE+RA*8-8], 0 // Initialize control var. | 4864 | | mov dword [BASE+RA*8-8], 0 // Initialize control var. |
4883 | | mov dword [BASE+RA*8-4], 0xfffe7fff | 4865 | | mov dword [BASE+RA*8-4], LJ_KEYINDEX |
4884 | |1: | 4866 | |1: |
4885 | | ins_next | 4867 | | ins_next |
4886 | |5: // Despecialize bytecode if any of the checks fail. | 4868 | |5: // Despecialize bytecode if any of the checks fail. |