mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
Compile string.find() for fixed string searches (no patterns).
This commit is contained in:
parent
43de451d78
commit
87b560b3e1
@ -501,7 +501,7 @@ static int str_find_aux(lua_State *L, int find)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LJLIB_CF(string_find)
|
LJLIB_CF(string_find) LJLIB_REC(.)
|
||||||
{
|
{
|
||||||
return str_find_aux(L, 1);
|
return str_find_aux(L, 1);
|
||||||
}
|
}
|
||||||
|
@ -646,6 +646,32 @@ static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd)
|
|||||||
|
|
||||||
/* -- String library fast functions --------------------------------------- */
|
/* -- String library fast functions --------------------------------------- */
|
||||||
|
|
||||||
|
/* Specialize to relative starting position for string. */
|
||||||
|
static TRef recff_string_start(jit_State *J, GCstr *s, int32_t *st, TRef tr,
|
||||||
|
TRef trlen, TRef tr0)
|
||||||
|
{
|
||||||
|
int32_t start = *st;
|
||||||
|
if (start < 0) {
|
||||||
|
emitir(IRTGI(IR_LT), tr, tr0);
|
||||||
|
tr = emitir(IRTI(IR_ADD), trlen, tr);
|
||||||
|
start = start + (int32_t)s->len;
|
||||||
|
emitir(start < 0 ? IRTGI(IR_LT) : IRTGI(IR_GE), tr, tr0);
|
||||||
|
if (start < 0) {
|
||||||
|
tr = tr0;
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
} else if (start == 0) {
|
||||||
|
emitir(IRTGI(IR_EQ), tr, tr0);
|
||||||
|
tr = tr0;
|
||||||
|
} else {
|
||||||
|
tr = emitir(IRTI(IR_ADD), tr, lj_ir_kint(J, -1));
|
||||||
|
emitir(IRTGI(IR_GE), tr, tr0);
|
||||||
|
start--;
|
||||||
|
}
|
||||||
|
*st = start;
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */
|
/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */
|
||||||
static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
|
static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
|
||||||
{
|
{
|
||||||
@ -691,29 +717,11 @@ static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
|
|||||||
} else if ((MSize)end <= str->len) {
|
} else if ((MSize)end <= str->len) {
|
||||||
emitir(IRTGI(IR_ULE), trend, trlen);
|
emitir(IRTGI(IR_ULE), trend, trlen);
|
||||||
} else {
|
} else {
|
||||||
emitir(IRTGI(IR_GT), trend, trlen);
|
emitir(IRTGI(IR_UGT), trend, trlen);
|
||||||
end = (int32_t)str->len;
|
end = (int32_t)str->len;
|
||||||
trend = trlen;
|
trend = trlen;
|
||||||
}
|
}
|
||||||
if (start < 0) {
|
trstart = recff_string_start(J, str, &start, trstart, trlen, tr0);
|
||||||
emitir(IRTGI(IR_LT), trstart, tr0);
|
|
||||||
trstart = emitir(IRTI(IR_ADD), trlen, trstart);
|
|
||||||
start = start+(int32_t)str->len;
|
|
||||||
emitir(start < 0 ? IRTGI(IR_LT) : IRTGI(IR_GE), trstart, tr0);
|
|
||||||
if (start < 0) {
|
|
||||||
trstart = tr0;
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (start == 0) {
|
|
||||||
emitir(IRTGI(IR_EQ), trstart, tr0);
|
|
||||||
trstart = tr0;
|
|
||||||
} else {
|
|
||||||
trstart = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, -1));
|
|
||||||
emitir(IRTGI(IR_GE), trstart, tr0);
|
|
||||||
start--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rd->data) { /* Return string.sub result. */
|
if (rd->data) { /* Return string.sub result. */
|
||||||
if (end - start >= 0) {
|
if (end - start >= 0) {
|
||||||
/* Also handle empty range here, to avoid extra traces. */
|
/* Also handle empty range here, to avoid extra traces. */
|
||||||
@ -723,7 +731,7 @@ static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
|
|||||||
J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
|
J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
|
||||||
} else { /* Range underflow: return empty string. */
|
} else { /* Range underflow: return empty string. */
|
||||||
emitir(IRTGI(IR_LT), trend, trstart);
|
emitir(IRTGI(IR_LT), trend, trstart);
|
||||||
J->base[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0));
|
J->base[0] = lj_ir_kstr(J, &J2G(J)->strempty);
|
||||||
}
|
}
|
||||||
} else { /* Return string.byte result(s). */
|
} else { /* Return string.byte result(s). */
|
||||||
ptrdiff_t i, len = end - start;
|
ptrdiff_t i, len = end - start;
|
||||||
@ -802,6 +810,64 @@ static void LJ_FASTCALL recff_string_op(jit_State *J, RecordFFData *rd)
|
|||||||
J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
|
J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd)
|
||||||
|
{
|
||||||
|
TRef trstr = lj_ir_tostr(J, J->base[0]);
|
||||||
|
TRef trpat = lj_ir_tostr(J, J->base[1]);
|
||||||
|
TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN);
|
||||||
|
TRef tr0 = lj_ir_kint(J, 0);
|
||||||
|
TRef trstart;
|
||||||
|
GCstr *str = argv2str(J, &rd->argv[0]);
|
||||||
|
GCstr *pat = argv2str(J, &rd->argv[1]);
|
||||||
|
int32_t start;
|
||||||
|
J->needsnap = 1;
|
||||||
|
if (tref_isnil(J->base[2])) {
|
||||||
|
trstart = lj_ir_kint(J, 1);
|
||||||
|
start = 1;
|
||||||
|
} else {
|
||||||
|
trstart = lj_opt_narrow_toint(J, J->base[2]);
|
||||||
|
start = argv2int(J, &rd->argv[2]);
|
||||||
|
}
|
||||||
|
trstart = recff_string_start(J, str, &start, trstart, trlen, tr0);
|
||||||
|
if ((MSize)start <= str->len) {
|
||||||
|
emitir(IRTGI(IR_ULE), trstart, trlen);
|
||||||
|
} else {
|
||||||
|
emitir(IRTGI(IR_UGT), trstart, trlen);
|
||||||
|
#if LJ_52
|
||||||
|
J->base[0] = TREF_NIL;
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
trstart = trlen;
|
||||||
|
start = str->len;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* Fixed arg or no pattern matching chars? (Specialized to pattern string.) */
|
||||||
|
if ((J->base[2] && tref_istruecond(J->base[3])) ||
|
||||||
|
(emitir(IRTG(IR_EQ, IRT_STR), trpat, lj_ir_kstr(J, pat)),
|
||||||
|
!lj_str_haspattern(pat))) { /* Search for fixed string. */
|
||||||
|
TRef trsptr = emitir(IRT(IR_STRREF, IRT_P32), trstr, trstart);
|
||||||
|
TRef trpptr = emitir(IRT(IR_STRREF, IRT_P32), trpat, tr0);
|
||||||
|
TRef trslen = emitir(IRTI(IR_SUB), trlen, trstart);
|
||||||
|
TRef trplen = emitir(IRTI(IR_FLOAD), trpat, IRFL_STR_LEN);
|
||||||
|
TRef tr = lj_ir_call(J, IRCALL_lj_str_find, trsptr, trpptr, trslen, trplen);
|
||||||
|
TRef trp0 = lj_ir_kkptr(J, NULL);
|
||||||
|
if (lj_str_find(strdata(str)+(MSize)start, strdata(pat),
|
||||||
|
str->len-(MSize)start, pat->len)) {
|
||||||
|
TRef pos;
|
||||||
|
emitir(IRTG(IR_NE, IRT_P32), tr, trp0);
|
||||||
|
pos = emitir(IRTI(IR_SUB), tr, emitir(IRT(IR_STRREF, IRT_P32), trstr, tr0));
|
||||||
|
J->base[0] = emitir(IRTI(IR_ADD), pos, lj_ir_kint(J, 1));
|
||||||
|
J->base[1] = emitir(IRTI(IR_ADD), pos, trplen);
|
||||||
|
rd->nres = 2;
|
||||||
|
} else {
|
||||||
|
emitir(IRTG(IR_EQ, IRT_P32), tr, trp0);
|
||||||
|
J->base[0] = TREF_NIL;
|
||||||
|
}
|
||||||
|
} else { /* Search for pattern. */
|
||||||
|
recff_nyiu(J);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Table library fast functions ---------------------------------------- */
|
/* -- Table library fast functions ---------------------------------------- */
|
||||||
|
|
||||||
static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)
|
static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)
|
||||||
|
@ -101,6 +101,7 @@ typedef struct CCallInfo {
|
|||||||
/* Function definitions for CALL* instructions. */
|
/* Function definitions for CALL* instructions. */
|
||||||
#define IRCALLDEF(_) \
|
#define IRCALLDEF(_) \
|
||||||
_(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \
|
_(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \
|
||||||
|
_(ANY, lj_str_find, 4, N, P32, 0) \
|
||||||
_(ANY, lj_str_new, 3, S, STR, CCI_L) \
|
_(ANY, lj_str_new, 3, S, STR, CCI_L) \
|
||||||
_(ANY, lj_strscan_num, 2, FN, INT, 0) \
|
_(ANY, lj_strscan_num, 2, FN, INT, 0) \
|
||||||
_(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \
|
_(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \
|
||||||
|
Loading…
Reference in New Issue
Block a user