aboutsummaryrefslogtreecommitdiff
path: root/src/lj_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_buf.c')
-rw-r--r--src/lj_buf.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/src/lj_buf.c b/src/lj_buf.c
index 66a096fb..889ccbca 100644
--- a/src/lj_buf.c
+++ b/src/lj_buf.c
@@ -20,12 +20,32 @@ static void buf_grow(SBuf *sb, MSize sz)
20{ 20{
21 MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz; 21 MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz;
22 char *b; 22 char *b;
23 GCSize flag;
23 if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF; 24 if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
24 while (nsz < sz) nsz += nsz; 25 while (nsz < sz) nsz += nsz;
25 b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz); 26 flag = sbufflag(sb);
27 if ((flag & SBUF_FLAG_COW)) { /* Copy-on-write semantics. */
28 lj_assertG_(G(sbufL(sb)), sb->w == sb->e, "bad SBuf COW");
29 b = (char *)lj_mem_new(sbufL(sb), nsz);
30 setsbufflag(sb, flag & ~(GCSize)SBUF_FLAG_COW);
31 setgcrefnull(sbufX(sb)->cowref);
32 memcpy(b, sb->b, osz);
33 } else {
34 b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz);
35 }
36 if ((flag & SBUF_FLAG_EXT)) {
37 sbufX(sb)->r = sbufX(sb)->r - sb->b + b; /* Adjust read pointer, too. */
38 }
39 /* Adjust buffer pointers. */
26 sb->b = b; 40 sb->b = b;
27 sb->w = b + len; 41 sb->w = b + len;
28 sb->e = b + nsz; 42 sb->e = b + nsz;
43 if ((flag & SBUF_FLAG_BORROW)) { /* Adjust borrowed buffer pointers. */
44 SBuf *bsb = mref(sbufX(sb)->bsb, SBuf);
45 bsb->b = b;
46 bsb->w = b + len;
47 bsb->e = b + nsz;
48 }
29} 49}
30 50
31LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) 51LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
@@ -39,11 +59,31 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
39 59
40LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz) 60LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
41{ 61{
42 MSize len = sbuflen(sb); 62 if (sbufisext(sb)) {
43 lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow"); 63 SBufExt *sbx = (SBufExt *)sb;
44 if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) 64 MSize len = sbufxlen(sbx);
45 lj_err_mem(sbufL(sb)); 65 if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
46 buf_grow(sb, len + sz); 66 lj_err_mem(sbufL(sbx));
67 if (len + sz > sbufsz(sbx)) { /* Must grow. */
68 buf_grow((SBuf *)sbx, len + sz);
69 } else if (sbufxslack(sbx) < (sbufsz(sbx) >> 3)) {
70 /* Also grow to avoid excessive compactions, if slack < size/8. */
71 buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */
72 return sbx->w;
73 }
74 if (sbx->r != sbx->b) { /* Compact by moving down. */
75 memmove(sbx->b, sbx->r, len);
76 sbx->r = sbx->b;
77 sbx->w = sbx->b + len;
78 lj_assertG_(G(sbufL(sbx)), len + sz <= sbufsz(sbx), "bad SBuf compact");
79 }
80 } else {
81 MSize len = sbuflen(sb);
82 lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
83 if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
84 lj_err_mem(sbufL(sb));
85 buf_grow(sb, len + sz);
86 }
47 return sb->w; 87 return sb->w;
48} 88}
49 89
@@ -58,6 +98,7 @@ void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
58 sb->w = b + n; 98 sb->w = b + n;
59 sb->e = b + (osz >> 1); 99 sb->e = b + (osz >> 1);
60 } 100 }
101 lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt");
61} 102}
62 103
63char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) 104char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)