Refactor string.reverse(), string.lower(), string.upper().

master
Mike Pall 2013-04-26 00:31:10 +02:00
parent eeb204cd87
commit 61cb25b0ca
10 changed files with 137 additions and 216 deletions

View File

@ -96,10 +96,10 @@ lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
lj_state.h lj_frame.h lj_bc.h lj_jit.h lj_ir.h
lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_func.h lj_str.h lj_tab.h lj_meta.h lj_debug.h \
lj_state.h lj_frame.h lj_bc.h lj_ff.h lj_ffdef.h lj_jit.h lj_ir.h \
lj_ccallback.h lj_ctype.h lj_gc.h lj_trace.h lj_dispatch.h lj_traceerr.h \
lj_vm.h luajit.h
lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_func.h lj_tab.h \
lj_meta.h lj_debug.h lj_state.h lj_frame.h lj_bc.h lj_ff.h lj_ffdef.h \
lj_jit.h lj_ir.h lj_ccallback.h lj_ctype.h lj_trace.h lj_dispatch.h \
lj_traceerr.h lj_vm.h luajit.h
lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \
lj_errmsg.h lj_debug.h lj_str.h lj_func.h lj_state.h lj_frame.h lj_bc.h \
lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \

View File

@ -135,8 +135,7 @@ LJLIB_ASM(string_rep)
LJLIB_ASM(string_reverse)
{
GCstr *s = lj_lib_checkstr(L, 1);
lj_buf_tmp(L, s->len);
lj_lib_checkstr(L, 1);
return FFH_RETRY;
}
LJLIB_ASM_(string_lower)

View File

@ -34,7 +34,7 @@ LJ_NOINLINE void LJ_FASTCALL lj_buf_grow(SBuf *sb, char *en)
char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
{
SBuf *sb = &G(L)->tmpbuf;
setmref(sb->L, L);
setsbufL(sb, L);
return lj_buf_need(sb, sz);
}
@ -95,12 +95,59 @@ SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o)
setsbufP(sb, lj_str_bufnum(lj_buf_more(sb, LJ_STR_NUMBUF), o));
return sb;
}
#endif
SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s)
{
MSize len = s->len;
char *p = lj_buf_more(sb, len), *e = p+len;
const char *q = strdata(s)+len-1;
while (p < e)
*p++ = *q--;
setsbufP(sb, p);
return sb;
}
SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s)
{
MSize len = s->len;
char *p = lj_buf_more(sb, len), *e = p+len;
const char *q = strdata(s);
for (; p < e; p++, q++) {
uint32_t c = *(unsigned char *)q;
#if LJ_TARGET_PPC
*p = c + ((c >= 'A' && c <= 'Z') << 5);
#else
if (c >= 'A' && c <= 'Z') c += 0x20;
*p = c;
#endif
}
setsbufP(sb, p);
return sb;
}
SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
{
MSize len = s->len;
char *p = lj_buf_more(sb, len), *e = p+len;
const char *q = strdata(s);
for (; p < e; p++, q++) {
uint32_t c = *(unsigned char *)q;
#if LJ_TARGET_PPC
*p = c - ((c >= 'a' && c <= 'z') << 5);
#else
if (c >= 'a' && c <= 'z') c -= 0x20;
*p = c;
#endif
}
setsbufP(sb, p);
return sb;
}
GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
{
return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb));
}
#endif
uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp)
{

View File

@ -31,8 +31,11 @@ LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s);
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c);
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k);
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o);
LJ_FUNC GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb);
#endif
LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s);
LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s);
LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s);
LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb);
LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp);
LJ_FUNC char * LJ_FASTCALL lj_buf_wuleb128(char *p, uint32_t v);

View File

@ -8,6 +8,7 @@
#include "lj_obj.h"
#include "lj_err.h"
#include "lj_buf.h"
#include "lj_func.h"
#include "lj_str.h"
#include "lj_tab.h"

View File

@ -37,7 +37,8 @@
_(lj_meta_tset) _(lj_state_growstack) _(lj_str_fromnum) _(lj_str_fromnumber) \
_(lj_str_new) _(lj_tab_dup) _(lj_tab_get) _(lj_tab_getinth) _(lj_tab_len) \
_(lj_tab_new) _(lj_tab_newkey) _(lj_tab_next) _(lj_tab_reasize) \
_(lj_tab_setinth) JITGOTDEF(_) FFIGOTDEF(_)
_(lj_tab_setinth) _(lj_buf_putstr_reverse) _(lj_buf_putstr_lower) \
_(lj_buf_putstr_upper) _(lj_buf_tostr) JITGOTDEF(_) FFIGOTDEF(_)
enum {
#define GOTENUM(name) LJ_GOT_##name,

View File

@ -99,6 +99,7 @@
|.type NODE, Node
|.type NARGS8, int
|.type TRACE, GCtrace
|.type SBUF, SBuf
|
|//-----------------------------------------------------------------------
|
@ -1743,6 +1744,7 @@ static void build_subroutines(BuildCtx *ctx)
| mov CARG1, L
| str PC, SAVE_PC
| bl extern lj_str_new // (lua_State *L, char *str, size_t l)
|->fff_resstr:
| // Returns GCstr *.
| ldr BASE, L->base
| mvn CARG2, #~LJ_TSTR
@ -1813,56 +1815,28 @@ static void build_subroutines(BuildCtx *ctx)
| bge <1
| b ->fff_newstr
|
|.ffunc string_reverse
|.macro ffstring_op, name
| .ffunc string_ .. name
| ffgccheck
| ldrd CARG12, [BASE]
| ldr CARG3, [BASE, #4]
| cmp NARGS8:RC, #8
| ldr STR:CARG2, [BASE]
| blo ->fff_fallback
| checkstr CARG2, ->fff_fallback
| ldr CARG3, STR:CARG1->len
| ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
| ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
| mov CARG4, CARG3
| add CARG1, STR:CARG1, #sizeof(GCstr)
| add INS, CARG2, CARG3
| cmp RB, INS
| blo ->fff_fallback
|1: // Reverse string copy.
| ldrb RB, [CARG1], #1
| subs CARG4, CARG4, #1
| blt ->fff_newstr
| strb RB, [CARG2, CARG4]
| b <1
|
|.macro ffstring_case, name, lo
| .ffunc name
| ffgccheck
| ldrd CARG12, [BASE]
| cmp NARGS8:RC, #8
| blo ->fff_fallback
| checkstr CARG2, ->fff_fallback
| ldr CARG3, STR:CARG1->len
| ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
| ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
| mov CARG4, #0
| add CARG1, STR:CARG1, #sizeof(GCstr)
| add INS, CARG2, CARG3
| cmp RB, INS
| blo ->fff_fallback
|1: // ASCII case conversion.
| ldrb RB, [CARG1, CARG4]
| cmp CARG4, CARG3
| bhs ->fff_newstr
| sub RC, RB, #lo
| cmp RC, #26
| eorlo RB, RB, #0x20
| strb RB, [CARG2, CARG4]
| add CARG4, CARG4, #1
| b <1
| sub SBUF:CARG1, DISPATCH, #-DISPATCH_GL(tmpbuf)
| checkstr CARG3, ->fff_fallback
| ldr CARG4, SBUF:CARG1->b
| str BASE, L->base
| str PC, SAVE_PC
| str L, SBUF:CARG1->L
| str CARG4, SBUF:CARG1->p
| bl extern lj_buf_putstr_ .. name
| bl extern lj_buf_tostr
| b ->fff_resstr
|.endmacro
|
|ffstring_case string_lower, 65
|ffstring_case string_upper, 97
|ffstring_op reverse
|ffstring_op lower
|ffstring_op upper
|
|//-- Bit library --------------------------------------------------------
|

View File

@ -138,6 +138,7 @@
|.type NODE, Node
|.type NARGS8, int
|.type TRACE, GCtrace
|.type SBUF, SBuf
|
|//-----------------------------------------------------------------------
|
@ -1668,6 +1669,7 @@ static void build_subroutines(BuildCtx *ctx)
|. move CARG1, L
| // Returns GCstr *.
| lw BASE, L->base
|->fff_resstr:
| move CARG1, CRET1
| b ->fff_restv
|. li CARG3, LJ_TSTR
@ -1756,63 +1758,32 @@ static void build_subroutines(BuildCtx *ctx)
| b ->fff_newstr
|. nop
|
|.ffunc string_reverse
|.macro ffstring_op, name
| .ffunc string_ .. name
| ffgccheck
| lw CARG3, HI(BASE)
| lw STR:CARG1, LO(BASE)
| lw STR:CARG2, LO(BASE)
| beqz NARGS8:RC, ->fff_fallback
|. li AT, LJ_TSTR
| bne CARG3, AT, ->fff_fallback
|. lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
| lw CARG3, STR:CARG1->len
| lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
| addiu CARG1, STR:CARG1, #STR
| addu CARG4, CARG2, CARG3
| sltu AT, TMP1, CARG4
| bnez AT, ->fff_fallback
|. addu TMP3, CARG1, CARG3
|1: // Reverse string copy.
| lbu TMP1, 0(CARG1)
| sltu AT, CARG1, TMP3
| beqz AT, ->fff_newstr
|. addiu CARG1, CARG1, 1
| addiu CARG4, CARG4, -1
| b <1
| sb TMP1, 0(CARG4)
|
|.macro ffstring_case, name, lo
| .ffunc name
| ffgccheck
| lw CARG3, HI(BASE)
| lw STR:CARG1, LO(BASE)
| beqz NARGS8:RC, ->fff_fallback
|. li AT, LJ_TSTR
| bne CARG3, AT, ->fff_fallback
|. lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
| lw CARG3, STR:CARG1->len
| lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
| addiu CARG1, STR:CARG1, #STR
| addu TMP3, CARG2, CARG3
| sltu AT, TMP1, TMP3
| bnez AT, ->fff_fallback
|. addu TMP3, CARG1, CARG3
| move CARG4, CARG2
|1: // ASCII case conversion.
| lbu TMP1, 0(CARG1)
| sltu AT, CARG1, TMP3
| beqz AT, ->fff_newstr
|. addiu TMP0, TMP1, -lo
| xori TMP2, TMP1, 0x20
| sltiu AT, TMP0, 26
| movn TMP1, TMP2, AT
| addiu CARG1, CARG1, 1
| sb TMP1, 0(CARG4)
| b <1
|. addiu CARG4, CARG4, 1
|. addiu SBUF:CARG1, DISPATCH, DISPATCH_GL(tmpbuf)
| load_got lj_buf_putstr_ .. name
| lw TMP0, SBUF:CARG1->b
| sw L, SBUF:CARG1->L
| sw BASE, L->base
| sw TMP0, SBUF:CARG1->p
| call_intern extern lj_buf_putstr_ .. name
|. sw PC, SAVE_PC
| load_got lj_buf_tostr
| call_intern lj_buf_tostr
|. move SBUF:CARG1, SBUF:CRET1
| b ->fff_resstr
|. lw BASE, L->base
|.endmacro
|
|ffstring_case string_lower, 65
|ffstring_case string_upper, 97
|ffstring_op reverse
|ffstring_op lower
|ffstring_op upper
|
|//-- Bit library --------------------------------------------------------
|

View File

@ -293,6 +293,7 @@
|.type NODE, Node
|.type NARGS8, int
|.type TRACE, GCtrace
|.type SBUF, SBuf
|
|//-----------------------------------------------------------------------
|
@ -2103,6 +2104,7 @@ static void build_subroutines(BuildCtx *ctx)
| stp BASE, L->base
| stw PC, SAVE_PC
| bl extern lj_str_new // (lua_State *L, char *str, size_t l)
|->fff_resstr:
| // Returns GCstr *.
| lp BASE, L->base
| li CARG3, LJ_TSTR
@ -2223,66 +2225,29 @@ static void build_subroutines(BuildCtx *ctx)
| li CARG3, LJ_TSTR
| b ->fff_restv
|
|.ffunc string_reverse
|.macro ffstring_op, name
| .ffunc string_ .. name
| ffgccheck
| cmplwi NARGS8:RC, 8
| lwz CARG3, 0(BASE)
| lwz STR:CARG1, 4(BASE)
| lwz STR:CARG2, 4(BASE)
| blt ->fff_fallback
| checkstr CARG3
| lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
| lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
| la SBUF:CARG1, DISPATCH_GL(tmpbuf)(DISPATCH)
| bne ->fff_fallback
| lwz CARG3, STR:CARG1->len
| la CARG1, #STR(STR:CARG1)
| li TMP2, 0
| add TMP3, CARG2, CARG3
| cmplw TMP1, TMP3
| subi TMP3, CARG3, 1
| blt ->fff_fallback
|1: // Reverse string copy.
| cmpwi TMP3, 0
| lbzx TMP1, CARG1, TMP2
| blty ->fff_newstr
| stbx TMP1, CARG2, TMP3
| subi TMP3, TMP3, 1
| addi TMP2, TMP2, 1
| b <1
|
|.macro ffstring_case, name, lo
| .ffunc name
| ffgccheck
| cmplwi NARGS8:RC, 8
| lwz CARG3, 0(BASE)
| lwz STR:CARG1, 4(BASE)
| blt ->fff_fallback
| checkstr CARG3
| lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
| lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
| bne ->fff_fallback
| lwz CARG3, STR:CARG1->len
| la CARG1, #STR(STR:CARG1)
| li TMP2, 0
| add TMP3, CARG2, CARG3
| cmplw TMP1, TMP3
| blt ->fff_fallback
|1: // ASCII case conversion.
| cmplw TMP2, CARG3
| lbzx TMP1, CARG1, TMP2
| bgey ->fff_newstr
| subi TMP0, TMP1, lo
| xori TMP3, TMP1, 0x20
| addic TMP0, TMP0, -26
| subfe TMP3, TMP3, TMP3
| rlwinm TMP3, TMP3, 0, 26, 26 // x &= 0x20.
| xor TMP1, TMP1, TMP3
| stbx TMP1, CARG2, TMP2
| addi TMP2, TMP2, 1
| b <1
| lwz TMP0, SBUF:CARG1->b
| stw L, SBUF:CARG1->L
| stp BASE, L->base
| stw PC, SAVE_PC
| stw TMP0, SBUF:CARG1->p
| bl extern lj_buf_putstr_ .. name
| bl extern lj_buf_tostr
| b ->fff_resstr
|.endmacro
|
|ffstring_case string_lower, 65
|ffstring_case string_upper, 97
|ffstring_op reverse
|ffstring_op lower
|ffstring_op upper
|
|//-- Bit library --------------------------------------------------------
|

View File

@ -115,6 +115,7 @@
|.type NODE, Node
|.type NARGS, int
|.type TRACE, GCtrace
|.type SBUF, SBuf
|
|// Stack layout while in interpreter. Must match with lj_frame.h.
|//-----------------------------------------------------------------------
@ -2258,6 +2259,7 @@ static void build_subroutines(BuildCtx *ctx)
|.endif
| mov SAVE_PC, PC
| call extern lj_str_new // (lua_State *L, char *str, size_t l)
|->fff_resstr:
| // GCstr * returned in eax (RD).
| mov BASE, L:RB->base
| mov PC, [BASE-4]
@ -2373,69 +2375,27 @@ static void build_subroutines(BuildCtx *ctx)
| mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
| jmp ->fff_newstr
|
|.ffunc_1 string_reverse
|.macro ffstring_op, name
| .ffunc_1 string_ .. name
| ffgccheck
| cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback
| mov STR:RB, [BASE]
| mov RC, STR:RB->len
| test RC, RC
| jz ->fff_emptystr // Zero length string?
| mov TMP2, PC // Need another temp register.
| mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
| lea RA, [PC+RC]
| cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RA; jb ->fff_fallback_1
| add RB, #STR
|.if X64
| mov TMP3, RC
|.else
| mov ARG3, RC
|.endif
|1:
| movzx RA, byte [RB]
| add RB, 1
| sub RC, 1
| mov [PC+RC], RAL
| jnz <1
| mov RD, PC
| mov PC, TMP2
| jmp ->fff_newstr
|
|.macro ffstring_case, name, lo, hi
| .ffunc_1 name
| ffgccheck
| cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback
| mov TMP2, PC // Need another temp register.
| mov STR:RB, [BASE]
| mov RC, STR:RB->len
| mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
| lea RA, [PC+RC]
| cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RA; jb ->fff_fallback_1
| add RB, #STR
|.if X64
| mov TMP3, RC
|.else
| mov ARG3, RC
|.endif
| jmp >3
|1: // ASCII case conversion. Yes, this is suboptimal code (do you care?).
| movzx RA, byte [RB+RC]
| cmp RA, lo
| jb >2
| cmp RA, hi
| ja >2
| xor RA, 0x20
|2:
| mov [PC+RC], RAL
|3:
| sub RC, 1
| jns <1
| mov RD, PC
| mov PC, TMP2
| jmp ->fff_newstr
| mov L:RB, SAVE_L
| lea SBUF:FCARG1, [DISPATCH+DISPATCH_GL(tmpbuf)]
| mov L:RB->base, BASE
| mov STR:FCARG2, [BASE] // Caveat: FCARG2 == BASE
| mov RC, SBUF:FCARG1->b
| mov SBUF:FCARG1->L, L:RB
| mov SBUF:FCARG1->p, RC
| mov SAVE_PC, PC
| call extern lj_buf_putstr_ .. name
| mov FCARG1, eax
| call extern lj_buf_tostr
| jmp ->fff_resstr
|.endmacro
|
|ffstring_case string_lower, 0x41, 0x5a
|ffstring_case string_upper, 0x61, 0x7a
|ffstring_op reverse
|ffstring_op lower
|ffstring_op upper
|
|//-- Bit library --------------------------------------------------------
|