]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
Refactor string.rep().
authorMike Pall <mike>
Fri, 26 Apr 2013 17:57:25 +0000 (19:57 +0200)
committerMike Pall <mike>
Fri, 26 Apr 2013 17:57:25 +0000 (19:57 +0200)
src/lib_string.c
src/lj_buf.c
src/lj_buf.h
src/lj_dispatch.h
src/vm_arm.dasc
src/vm_mips.dasc
src/vm_ppc.dasc
src/vm_x86.dasc

index cd67347822a2febddc7e5625ffe19e146b0dbcb8..598cd93e8571749a39ee5c3b419cafef10caa22c 100644 (file)
@@ -85,53 +85,23 @@ LJLIB_ASM(string_sub)               LJLIB_REC(string_range 1)
   return FFH_RETRY;
 }
 
-LJLIB_ASM(string_rep)
+LJLIB_CF(string_rep)
 {
   GCstr *s = lj_lib_checkstr(L, 1);
-  int32_t k = lj_lib_checkint(L, 2);
+  int32_t rep = lj_lib_checkint(L, 2);
   GCstr *sep = lj_lib_optstr(L, 3);
-  int32_t len = (int32_t)s->len;
-  global_State *g = G(L);
-  int64_t tlen;
-  if (k <= 0) {
-  empty:
-    setstrV(L, L->base-1, &g->strempty);
-    return FFH_RES(1);
-  }
-  if (sep) {
-    tlen = (int64_t)len + sep->len;
-    if (tlen > LJ_MAX_STR)
-      lj_err_caller(L, LJ_ERR_STROV);
-    tlen *= k;
-    if (tlen > LJ_MAX_STR)
-      lj_err_caller(L, LJ_ERR_STROV);
-  } else {
-    tlen = (int64_t)k * len;
-    if (tlen > LJ_MAX_STR)
-      lj_err_caller(L, LJ_ERR_STROV);
-  }
-  if (tlen == 0) {
-    goto empty;
-  } else {
-    char *buf = lj_buf_tmp(L, (MSize)tlen), *p = buf;
-    const char *src = strdata(s);
-    if (sep) {
-      tlen -= sep->len;  /* Ignore trailing separator. */
-      if (k > 1) {  /* Paste one string and one separator. */
-       int32_t i;
-       i = 0; while (i < len) *p++ = src[i++];
-       src = strdata(sep); len = sep->len;
-       i = 0; while (i < len) *p++ = src[i++];
-       src = buf; len += s->len; k--;  /* Now copy that k-1 times. */
-      }
-    }
-    do {
-      int32_t i = 0;
-      do { *p++ = src[i++]; } while (i < len);
-    } while (--k > 0);
-    setstrV(L, L->base-1, lj_str_new(L, buf, (size_t)tlen));
+  SBuf *sb = lj_buf_tmp_(L);
+  if (sep && rep > 1) {
+    GCstr *s2 = lj_buf_cat2str(L, sep, s);
+    lj_buf_reset(sb);
+    lj_buf_putstr(sb, s);
+    s = s2;
+    rep--;
   }
-  return FFH_RES(1);
+  sb = lj_buf_putstr_rep(sb, s, rep);
+  setstrV(L, L->top-1, lj_buf_str(L, sb));
+  lj_gc_check(L);
+  return 1;
 }
 
 LJLIB_ASM(string_reverse)  LJLIB_REC(string_op IRCALL_lj_buf_putstr_reverse)
index 3526a6e51804ed37c8830e50c7507f2562e72a67..55a885a954b483ca5bc835d1a6ed23fd1c454340 100644 (file)
@@ -144,6 +144,30 @@ SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
   return sb;
 }
 
+SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep)
+{
+  MSize len = s->len;
+  if (rep > 0 && len) {
+    uint64_t tlen = (uint64_t)rep * len;
+    char *p;
+    if (LJ_UNLIKELY(tlen > LJ_MAX_STR))
+      lj_err_mem(sbufL(sb));
+    p = lj_buf_more(sb, (MSize)tlen);
+    if (len == 1) {  /* Optimize a common case. */
+      uint32_t c = strdata(s)[0];
+      do { *p++ = c; } while (--rep > 0);
+    } else {
+      const char *e = strdata(s) + len;
+      do {
+       const char *q = strdata(s);
+       do { *p++ = *q++; } while (q < e);
+      } while (--rep > 0);
+    }
+    setsbufP(sb, p);
+  }
+  return sb;
+}
+
 GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
 {
   return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb));
index 92a6055a2d571177e071655b2ddb30804ea94b79..4d764938143bd6caf35965f78182cb24b97ab97b 100644 (file)
@@ -35,6 +35,7 @@ LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o);
 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_FUNC SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep);
 LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb);
 LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2);
 LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp);
index e744e3f8ea8222b735c6144e0901e500c94f6444..1ca293294df0d5cba941ed6a9f0b963b7350b933 100644 (file)
@@ -61,7 +61,7 @@ typedef uint16_t HotCount;
 #define HOTCOUNT_CALL          1
 
 /* This solves a circular dependency problem -- bump as needed. Sigh. */
-#define GG_NUM_ASMFF   58
+#define GG_NUM_ASMFF   57
 
 #define GG_LEN_DDISP   (BC__MAX + GG_NUM_ASMFF)
 #define GG_LEN_SDISP   BC_FUNCF
index 5c149bc4eb61fabc97a583e3b56c0cfc629f73b6..0c542e1e4bcc3acf4849d90e48f136eabddb15b6 100644 (file)
@@ -1782,33 +1782,6 @@ static void build_subroutines(BuildCtx *ctx)
   |  mvn CARG2, #~LJ_TSTR
   |  b ->fff_restv
   |
-  |.ffunc string_rep                   // Only handle the 1-char case inline.
-  |  ffgccheck
-  |  ldrd CARG12, [BASE]
-  |   ldrd CARG34, [BASE, #8]
-  |    cmp NARGS8:RC, #16
-  |    bne ->fff_fallback              // Exactly 2 arguments
-  |  checktp CARG2, LJ_TSTR
-  |   checktpeq CARG4, LJ_TISNUM
-  |   bne ->fff_fallback
-  |  subs CARG4, CARG3, #1
-  |   ldr CARG2, STR:CARG1->len
-  |  blt ->fff_emptystr                        // Count <= 0?
-  |   cmp CARG2, #1
-  |   blo ->fff_emptystr               // Zero-length string?
-  |   bne ->fff_fallback               // Fallback for > 1-char strings.
-  |  ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
-  |   ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
-  |   ldr CARG1, STR:CARG1[1]
-  |  add INS, CARG2, CARG3
-  |  cmp RB, INS
-  |  blo ->fff_fallback
-  |1:  // Fill buffer with char.
-  |   strb CARG1, [CARG2, CARG4]
-  |  subs CARG4, CARG4, #1
-  |  bge <1
-  |  b ->fff_newstr
-  |
   |.macro ffstring_op, name
   |  .ffunc string_ .. name
   |  ffgccheck
index 962e92903a58cb894fcdc996a69b7f56eb2747ff..9ab68981c574505bb3270d13c9fe6ed33d60e739 100644 (file)
@@ -1716,41 +1716,6 @@ static void build_subroutines(BuildCtx *ctx)
   |  b ->fff_restv
   |.  li CARG3, LJ_TSTR
   |
-  |.ffunc string_rep                   // Only handle the 1-char case inline.
-  |  ffgccheck
-  |  lw TMP0, HI(BASE)
-  |   addiu AT, NARGS8:RC, -16         // Exactly 2 arguments.
-  |  lw CARG4, 8+HI(BASE)
-  |   lw STR:CARG1, LO(BASE)
-  |  addiu TMP0, TMP0, -LJ_TSTR
-  |   ldc1 f0, 8(BASE)
-  |  or AT, AT, TMP0
-  |  bnez AT, ->fff_fallback
-  |.  sltiu AT, CARG4, LJ_TISNUM
-  |   trunc.w.d f0, f0
-  |  beqz AT, ->fff_fallback
-  |.  lw TMP0, STR:CARG1->len
-  |   mfc1 CARG3, f0
-  |  lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
-  |   lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
-  |  li AT, 1
-  |   blez CARG3, ->fff_emptystr       // Count <= 0?
-  |.   sltu AT, AT, TMP0
-  |  beqz TMP0, ->fff_emptystr         // Zero length string?
-  |.  addu TMP3, CARG2, CARG3
-  |  sltu TMP0, TMP1, TMP3
-  |  or AT, AT, TMP0
-  |  bnez AT, ->fff_fallback           // Fallback for > 1-char strings.
-  |.  lbu TMP0, STR:CARG1[1]
-  |  addu TMP2, CARG2, CARG3
-  |1:  // Fill buffer with char. Yes, this is suboptimal code (do you care?).
-  |  addiu TMP2, TMP2, -1
-  |  sltu AT, CARG2, TMP2
-  |  bnez AT, <1
-  |.  sb TMP0, 0(TMP2)
-  |  b ->fff_newstr
-  |.  nop
-  |
   |.macro ffstring_op, name
   |  .ffunc string_ .. name
   |  ffgccheck
index 19211825aaa4986866be920be725ce3676b93b9b..733eeb8f2259a594e256d77448e2e6b0e2f8f874 100644 (file)
@@ -2177,49 +2177,6 @@ static void build_subroutines(BuildCtx *ctx)
   |  addi TMP1, TMP1, 1                        // start = 1 + (start ? start+len : 0)
   |  b <3
   |
-  |.ffunc string_rep                   // Only handle the 1-char case inline.
-  |  ffgccheck
-  |  cmplwi NARGS8:RC, 16
-  |   lwz TMP0, 0(BASE)
-  |    lwz STR:CARG1, 4(BASE)
-  |   lwz CARG4, 8(BASE)
-  |.if DUALNUM
-  |    lwz CARG3, 12(BASE)
-  |.else
-  |    lfd FARG2, 8(BASE)
-  |.endif
-  |  bne ->fff_fallback                        // Exactly 2 arguments.
-  |  checkstr TMP0; bne ->fff_fallback
-  |.if DUALNUM
-  |  checknum CARG4; bne ->fff_fallback
-  |.else
-  |  checknum CARG4; bge ->fff_fallback
-  |    toint CARG3, FARG2
-  |.endif
-  |   lwz TMP0, STR:CARG1->len
-  |  cmpwi CARG3, 0
-  |   lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
-  |   lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
-  |  ble >2                            // Count <= 0? (or non-int)
-  |   cmplwi TMP0, 1
-  |   add TMP3, CARG2, CARG3
-  |  subi TMP2, CARG3, 1
-  |   blt >2                           // Zero length string?
-  |  cmplw cr1, TMP1, TMP3
-  |   bne ->fff_fallback               // Fallback for > 1-char strings.
-  |   lbz TMP0, STR:CARG1[1]
-  |  blt cr1, ->fff_fallback
-  |1:  // Fill buffer with char. Yes, this is suboptimal code (do you care?).
-  |  cmplwi TMP2, 0
-  |   stbx TMP0, CARG2, TMP2
-  |   subi TMP2, TMP2, 1
-  |  bne <1
-  |  b ->fff_newstr
-  |2:  // Return empty string.
-  |  la STR:CARG1, DISPATCH_GL(strempty)(DISPATCH)
-  |  li CARG3, LJ_TSTR
-  |  b ->fff_restv
-  |
   |.macro ffstring_op, name
   |  .ffunc string_ .. name
   |  ffgccheck
index 3f2959be8a1a75b960df1ff72a1fd7fc2e9e24ec..b7c5393f7d840cb9905a2c934941d16f7a67220b 100644 (file)
@@ -2331,41 +2331,6 @@ static void build_subroutines(BuildCtx *ctx)
   |  xor RC, RC                                // Zero length. Any ptr in RB is ok.
   |  jmp <4
   |
-  |.ffunc string_rep                   // Only handle the 1-char case inline.
-  |  ffgccheck
-  |  cmp NARGS:RD, 2+1; jne ->fff_fallback     // Exactly 2 arguments.
-  |  cmp dword [BASE+4], LJ_TSTR;  jne ->fff_fallback
-  |  cmp dword [BASE+12], LJ_TISNUM
-  |  mov STR:RB, [BASE]
-  |.if DUALNUM
-  |  jne ->fff_fallback
-  |  mov RC, dword [BASE+8]
-  |.else
-  |  jae ->fff_fallback
-  |  cvttsd2si RC, qword [BASE+8]
-  |.endif
-  |  test RC, RC
-  |  jle ->fff_emptystr                        // Count <= 0? (or non-int)
-  |  cmp dword STR:RB->len, 1
-  |  jb ->fff_emptystr                 // Zero length string?
-  |  jne ->fff_fallback_2              // Fallback for > 1-char strings.
-  |  movzx RA, byte STR:RB[1]
-  |  mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
-  |  add RB, RC
-  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RB;  jb ->fff_fallback_2
-  |.if X64
-  |  mov TMP3, RC
-  |.else
-  |  mov ARG3, RC
-  |.endif
-  |1:  // Fill buffer with char.
-  |  sub RB, 1
-  |  sub RC, 1
-  |  mov [RB], RAL
-  |  jnz <1
-  |  mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
-  |  jmp ->fff_newstr
-  |
   |.macro ffstring_op, name
   |  .ffunc_1 string_ .. name
   |  ffgccheck