/* -- String library fast functions --------------------------------------- */
-static void LJ_FASTCALL recff_string_len(jit_State *J, RecordFFData *rd)
+/* 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)
{
- J->base[0] = emitir(IRTI(IR_FLOAD), lj_ir_tostr(J, J->base[0]), IRFL_STR_LEN);
- UNUSED(rd);
+ 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));
++ tr = emitir(IRTGI(IR_ADDOV), 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). */
if (rd->data) { /* Return string.sub result. */
if (end - start >= 0) {
/* Also handle empty range here, to avoid extra traces. */
- TRef trptr, trslen = emitir(IRTI(IR_SUB), trend, trstart);
+ TRef trptr, trslen = emitir(IRTGI(IR_SUBOV), trend, trstart);
emitir(IRTGI(IR_GE), trslen, tr0);
- trptr = emitir(IRT(IR_STRREF, IRT_P32), trstr, trstart);
+ trptr = emitir(IRT(IR_STRREF, IRT_PGC), trstr, trstart);
J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
} else { /* Range underflow: return empty string. */
emitir(IRTGI(IR_LT), trend, trstart);