summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2017-12-13 14:55:33 +1100
committerdaurnimator <quae@daurnimator.com>2017-12-13 15:31:04 +1100
commit11a2421acaf2b39d19ee99933102c35e28fd13f8 (patch)
tree4abd1fa6ee063f75c634349a02702de7bc145a8b
parent3e7c102eefbaae9e6bc839b11bba79aee1c5e040 (diff)
downloadfengari-11a2421acaf2b39d19ee99933102c35e28fd13f8.tar.gz
fengari-11a2421acaf2b39d19ee99933102c35e28fd13f8.tar.bz2
fengari-11a2421acaf2b39d19ee99933102c35e28fd13f8.zip
Use Uint8Array to back strings
-rw-r--r--src/defs.js7
-rw-r--r--src/lauxlib.js6
-rw-r--r--src/lbaselib.js2
-rw-r--r--src/ldblib.js4
-rw-r--r--src/ldump.js23
-rw-r--r--src/llex.js5
-rw-r--r--src/llimits.js4
-rw-r--r--src/lobject.js9
-rw-r--r--src/loslib.js10
-rw-r--r--src/lstring.js5
-rw-r--r--src/lundump.js2
-rw-r--r--src/lutf8lib.js2
-rw-r--r--src/lvm.js29
-rw-r--r--src/lzio.js29
-rw-r--r--tests/test-suite/ltests.js23
15 files changed, 88 insertions, 72 deletions
diff --git a/src/defs.js b/src/defs.js
index 27498c6..381114b 100644
--- a/src/defs.js
+++ b/src/defs.js
@@ -131,10 +131,10 @@ class lua_Debug {
}
-const string_of = Array.of;
+const string_of = Uint8Array.of.bind(Uint8Array);
const is_luastring = function(s) {
- return Array.isArray(s);
+ return s instanceof Uint8Array;
};
/* test two lua strings for equality */
@@ -143,7 +143,7 @@ const luastring_cmp = function(a, b) {
};
const to_jsstring = function(value, from, to) {
- assert(is_luastring(value), "jsstring expects an array of bytes");
+ assert(is_luastring(value), "jsstring expects a Uint8Array");
if (to === void 0) {
to = value.length;
@@ -240,6 +240,7 @@ const to_luastring = function(str, cache) {
outU8Array[outIdx++] = 0x80 | (u & 63);
}
}
+ outU8Array = Uint8Array.from(outU8Array);
if (cache) to_luastring_cache[str] = outU8Array;
diff --git a/src/lauxlib.js b/src/lauxlib.js
index b9b7078..6acf57f 100644
--- a/src/lauxlib.js
+++ b/src/lauxlib.js
@@ -381,14 +381,14 @@ const luaL_prepbuffer = function(B) {
};
const luaL_addlstring = function(B, s, l) {
- B.b = B.b.concat(s.slice(0, l));
+ B.b = B.b.concat(Array.from(s.subarray(0, l)));
};
const luaL_addstring = luaL_addlstring;
const luaL_pushresult = function(B) {
let L = B.L;
- lua.lua_pushstring(L, B.b);
+ lua.lua_pushstring(L, Uint8Array.from(B.b));
};
const luaL_addchar = function(B, c) {
@@ -558,7 +558,7 @@ const luaL_gsub = function(L, s, p, r) {
s = s.slice(wild + p.length); /* continue after 'p' */
}
b.push(...s); /* push last suffix */
- lua.lua_pushstring(L, b);
+ lua.lua_pushstring(L, Uint8Array.from(b));
return lua.lua_tostring(L, -1);
};
diff --git a/src/lbaselib.js b/src/lbaselib.js
index 30e77fb..103a9ca 100644
--- a/src/lbaselib.js
+++ b/src/lbaselib.js
@@ -8,7 +8,7 @@ let lua_writeline;
if (typeof process === "undefined") {
let buff = [];
lua_writestring = function(s) {
- buff = buff.concat(s);
+ buff = buff.concat(Array.from(s));
};
lua_writeline = function() {
console.log(new TextDecoder("utf-8").decode(Uint8Array.from(buff)));
diff --git a/src/ldblib.js b/src/ldblib.js
index 746d3bf..df7d2ff 100644
--- a/src/ldblib.js
+++ b/src/ldblib.js
@@ -306,7 +306,7 @@ const unmakemask = function(mask, smask) {
if (mask & lua.LUA_MASKCALL) smask[i++] = "c".charCodeAt(0);
if (mask & lua.LUA_MASKRET) smask[i++] = "r".charCodeAt(0);
if (mask & lua.LUA_MASKLINE) smask[i++] = "l".charCodeAt(0);
- return smask;
+ return smask.subarray(0, i);
};
const db_sethook = function(L) {
@@ -344,7 +344,7 @@ const db_sethook = function(L) {
const db_gethook = function(L) {
let thread = getthread(L);
let L1 = thread.thread;
- let buff = [];
+ let buff = new Uint8Array(5);
let mask = lua.lua_gethookmask(L1);
let hook = lua.lua_gethook(L1);
if (hook === null) /* no hook? */
diff --git a/src/ldump.js b/src/ldump.js
index 964d6ff..7e62da3 100644
--- a/src/ldump.js
+++ b/src/ldump.js
@@ -34,31 +34,26 @@ const DumpByte = function(y, D) {
};
const DumpInt = function(x, D) {
- let dv = new DataView(new ArrayBuffer(4));
+ let ab = new ArrayBuffer(4);
+ let dv = new DataView(ab);
dv.setInt32(0, x, true);
- let t = [];
- for (let i = 0; i < 4; i++)
- t.push(dv.getUint8(i, true));
-
+ let t = new Uint8Array(ab);
DumpBlock(t, 4, D);
};
const DumpInteger = function(x, D) {
- let dv = new DataView(new ArrayBuffer(4));
+ let ab = new ArrayBuffer(4);
+ let dv = new DataView(ab);
dv.setInt32(0, x, true);
- let t = [];
- for (let i = 0; i < 4; i++)
- t.push(dv.getUint8(i, true));
+ let t = new Uint8Array(ab);
DumpBlock(t, 4, D);
};
const DumpNumber = function(x, D) {
- let dv = new DataView(new ArrayBuffer(8));
+ let ab = new ArrayBuffer(8);
+ let dv = new DataView(ab);
dv.setFloat64(0, x, true);
- let t = [];
- for (let i = 0; i < 8; i++)
- t.push(dv.getUint8(i, true));
-
+ let t = new Uint8Array(ab);
DumpBlock(t, 8, D);
};
diff --git a/src/llex.js b/src/llex.js
index 779557a..9e4bed4 100644
--- a/src/llex.js
+++ b/src/llex.js
@@ -112,6 +112,8 @@ const save = function(ls, c) {
if (b.n + 1 > b.buffer.length) {
if (b.buffer.length >= llimits.MAX_INT/2)
lexerror(ls, defs.to_luastring("lexical element too long", true), 0);
+ let newsize = b.buffer.length*2;
+ lzio.luaZ_resizebuffer(ls.L, b, newsize);
}
b.buffer[b.n++] = c < 0 ? 255 + c + 1 : c;
};
@@ -192,6 +194,7 @@ const luaX_setinput = function(L, ls, z, source, firstchar) {
ls.lastline = 1;
ls.source = source;
ls.envn = lstring.luaS_bless(L, LUA_ENV);
+ lzio.luaZ_resizebuffer(L, ls.buff, llimits.LUA_MINBUFFER); /* initialize buffer */
};
const check_next1 = function(ls, c) {
@@ -369,7 +372,7 @@ const readutf8desc = function(ls) {
};
const utf8esc = function(ls) {
- let buff = new Array(lobject.UTF8BUFFSZ);
+ let buff = new Uint8Array(lobject.UTF8BUFFSZ);
let n = lobject.luaO_utf8esc(buff, readutf8desc(ls));
for (; n > 0; n--) /* add 'buff' to string */
save(ls, buff[lobject.UTF8BUFFSZ - n]);
diff --git a/src/llimits.js b/src/llimits.js
index 21a09a0..4a76bbe 100644
--- a/src/llimits.js
+++ b/src/llimits.js
@@ -3,6 +3,10 @@
const LUAI_MAXCCALLS = 200;
module.exports.LUAI_MAXCCALLS = LUAI_MAXCCALLS;
+/* minimum size for string buffer */
+const LUA_MINBUFFER = 32;
+module.exports.LUA_MINBUFFER = LUA_MINBUFFER;
+
const luai_nummod = function(L, a, b) {
let m = a % b;
if ((m*b) < 0)
diff --git a/src/lobject.js b/src/lobject.js
index 707cdf8..18adb27 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -312,19 +312,20 @@ const luaO_chunkid = function(source, bufflen) {
out = source.slice(1);
else { /* add '...' before rest of name */
bufflen -= RETS.length;
- out = RETS.concat(source.slice(1 + l - bufflen));
+ out = Uint8Array.from(Array.from(RETS).concat(Array.from(source.subarray(1 + l - bufflen))));
}
} else { /* string; format as [string "source"] */
let nli = source.indexOf(char['\n']); /* find first new line (if any) */
- out = PRE; /* add prefix */
+ out = Array.from(PRE); /* add prefix */
bufflen -= PRE.length + RETS.length + POS.length + 1; /* save space for prefix+suffix+'\0' */
if (l < bufflen && nli === -1) { /* small one-line source? */
- out = out.concat(source, POS); /* keep it */
+ out = out.concat(Array.from(source), Array.from(POS)); /* keep it */
} else {
if (nli !== -1) l = nli; /* stop at first newline */
if (l > bufflen) l = bufflen;
- out = out.concat(source.slice(0, l), RETS, POS);
+ out = out.concat(Array.from(source.subarray(0, l)), Array.from(RETS), Array.from(POS));
}
+ out = Uint8Array.from(out);
}
return out;
};
diff --git a/src/loslib.js b/src/loslib.js
index 19dfd02..f27a7ed 100644
--- a/src/loslib.js
+++ b/src/loslib.js
@@ -73,7 +73,7 @@ const checkoption = function(L, conv, i, buff) {
if (option[o] === '|'.charCodeAt(0)) /* next block? */
oplen++; /* will check options with next length (+1) */
else if (array_cmp(conv, i, option, o, oplen)) { /* match? */
- buff.push(...conv.slice(i, i+oplen)); /* copy valid option to buffer */
+ buff.set(conv.slice(i, i+oplen)); /* copy valid option to buffer */
return i + oplen; /* return next item */
}
}
@@ -102,6 +102,8 @@ const os_date = function(L) {
lua.lua_createtable(L, 0, 9); /* 9 = number of fields */
setallfields(L, stm, utc);
} else {
+ let cc = new Uint8Array(4);
+ cc[0] = "%".charCodeAt(0);
let b = new lauxlib.luaL_Buffer();
lauxlib.luaL_buffinit(L, b);
while (i < s.length) {
@@ -109,8 +111,10 @@ const os_date = function(L) {
lauxlib.luaL_addchar(b, s[i++]);
} else {
i++; /* skip '%' */
- let cc = ["%".charCodeAt(0)];
- i = checkoption(L, s, i, cc); /* copy specifier to 'cc' */
+ i = checkoption(L, s, i, cc.subarray(1)); /* copy specifier to 'cc' */
+ let len = cc.indexOf(0);
+ if (len !== -1)
+ cc = cc.subarray(0, len);
let buff = strftime(lua.to_jsstring(cc), stm);
lauxlib.luaL_addstring(b, lua.to_luastring(buff));
}
diff --git a/src/lstring.js b/src/lstring.js
index c85e5b2..c8da56a 100644
--- a/src/lstring.js
+++ b/src/lstring.js
@@ -31,7 +31,7 @@ const luaS_eqlngstr = function(a, b) {
make sure this doesn't conflict with any of the anti-collision strategies in ltable */
const luaS_hash = function(str) {
assert(defs.is_luastring(str));
- return str.map(e => `${e}|`).join('');
+ return '|'+str.join('|');
};
const luaS_hashlongstr = function(ts) {
@@ -44,12 +44,13 @@ const luaS_hashlongstr = function(ts) {
/* variant that takes ownership of array */
const luaS_bless = function(L, str) {
+ assert(str instanceof Uint8Array);
return new TString(L, str);
};
/* makes a copy */
const luaS_new = function(L, str) {
- return luaS_bless(L, str.slice(0));
+ return luaS_bless(L, Uint8Array.from(str));
};
/* takes a js string */
diff --git a/src/lundump.js b/src/lundump.js
index ff87903..7461813 100644
--- a/src/lundump.js
+++ b/src/lundump.js
@@ -46,7 +46,7 @@ class BytecodeParser {
let u8 = new Uint8Array(size);
if(lzio.luaZ_read(this.Z, u8, 0, size) !== 0)
this.error("truncated");
- return Array.from(u8);
+ return u8;
}
readByte() {
diff --git a/src/lutf8lib.js b/src/lutf8lib.js
index 3baeeef..f581a9e 100644
--- a/src/lutf8lib.js
+++ b/src/lutf8lib.js
@@ -216,7 +216,7 @@ const funcs = {
};
/* pattern to match a single UTF-8 character */
-const UTF8PATT = [ 91, 0, 45, 127, 194, 45, 244, 93, 91, 128, 45, 191, 93, 42 ];
+const UTF8PATT = Uint8Array.of(91, 0, 45, 127, 194, 45, 244, 93, 91, 128, 45, 191, 93, 42);
const luaopen_utf8 = function(L) {
lauxlib.luaL_newlib(L, funcs);
diff --git a/src/lvm.js b/src/lvm.js
index 3cdccb9..9d97c17 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -937,6 +937,18 @@ const isemptystr = function(o) {
return o.ttisstring() && o.vslen() === 0;
};
+/* copy strings in stack from top - n up to top - 1 to buffer */
+const copy2buff = function(L, top, n, buff) {
+ let tl = 0; /* size already copied */
+ do {
+ let tv = L.stack[top-n];
+ let l = tv.vslen(); /* length of string being copied */
+ let s = tv.svalue();
+ buff.set(s, tl);
+ tl += l;
+ } while (--n > 0);
+};
+
/*
** Main operation for concatenation: concat 'total' values in the stack,
** from 'L->top - total' up to 'L->top - 1'.
@@ -955,16 +967,15 @@ const luaV_concat = function(L, total) {
lobject.setobjs2s(L, top - 2, top - 1);
} else {
/* at least two non-empty string values; get as many as possible */
- let toconcat = new Array(total);
- toconcat[total-1] = L.stack[top-1].svalue();
- for (n = 1; n < total; n++) {
- if (!tostring(L, top - n - 1)) {
- toconcat = toconcat.slice(total-n);
- break;
- }
- toconcat[total-n-1] = L.stack[top - n - 1].svalue();
+ let tl = L.stack[top-1].vslen();
+ /* collect total length and number of strings */
+ for (n = 1; n < total && tostring(L, top - n - 1); n++) {
+ let l = L.stack[top - n - 1].vslen();
+ tl += l;
}
- let ts = lstring.luaS_bless(L, Array.prototype.concat.apply([], toconcat));
+ let buff = new Uint8Array(tl);
+ copy2buff(L, top, n, buff);
+ let ts = lstring.luaS_bless(L, buff);
lobject.setsvalue2s(L, top - n, ts);
}
total -= n - 1; /* got 'n' strings to create 1 new */
diff --git a/src/lzio.js b/src/lzio.js
index 3d877aa..efd7909 100644
--- a/src/lzio.js
+++ b/src/lzio.js
@@ -11,7 +11,7 @@ class MBuffer {
}
const luaZ_buffer = function(buff) {
- return buff.buffer;
+ return buff.buffer.subarray(0, buff.n);
};
const luaZ_buffremove = function(buff, i) {
@@ -20,7 +20,13 @@ const luaZ_buffremove = function(buff, i) {
const luaZ_resetbuffer = function(buff) {
buff.n = 0;
- buff.buffer = [];
+};
+
+const luaZ_resizebuffer = function(L, buff, size) {
+ let newbuff = new Uint8Array(size);
+ if (buff.buffer)
+ newbuff.set(buff.buffer);
+ buff.buffer = newbuff;
};
class ZIO {
@@ -51,7 +57,7 @@ const luaZ_fill = function(z) {
z.off = 0;
size = buff.byteLength - buff.byteOffset;
} else {
- assert(typeof buff !== "string", "Should only load binary of array of bytes");
+ assert(buff instanceof Uint8Array, "Should only load binary of array of bytes");
z.buffer = buff;
z.off = 0;
size = buff.length;
@@ -87,11 +93,12 @@ const luaZ_read = function(z, b, b_offset, n) {
return 0;
};
-module.exports.EOZ = EOZ;
-module.exports.luaZ_buffer = luaZ_buffer;
-module.exports.luaZ_buffremove = luaZ_buffremove;
-module.exports.luaZ_fill = luaZ_fill;
-module.exports.luaZ_read = luaZ_read;
-module.exports.luaZ_resetbuffer = luaZ_resetbuffer;
-module.exports.MBuffer = MBuffer;
-module.exports.ZIO = ZIO;
+module.exports.EOZ = EOZ;
+module.exports.luaZ_buffer = luaZ_buffer;
+module.exports.luaZ_buffremove = luaZ_buffremove;
+module.exports.luaZ_fill = luaZ_fill;
+module.exports.luaZ_read = luaZ_read;
+module.exports.luaZ_resetbuffer = luaZ_resetbuffer;
+module.exports.luaZ_resizebuffer = luaZ_resizebuffer;
+module.exports.MBuffer = MBuffer;
+module.exports.ZIO = ZIO;
diff --git a/tests/test-suite/ltests.js b/tests/test-suite/ltests.js
index 8d89102..08bb603 100644
--- a/tests/test-suite/ltests.js
+++ b/tests/test-suite/ltests.js
@@ -60,8 +60,7 @@ const getstring = function(L, buff, pc) {
while (pc.script[pc.offset] !== 0 && pc.offset < pc.script.length && delimits.indexOf(pc.script[pc.offset]) < 0)
buff[i++] = pc.script[pc.offset++];
}
- buff.length = i;
- return buff;
+ return buff.subarray(0, i);
};
const getindex = function(L, L1, pc) {
@@ -100,7 +99,7 @@ const printstack = function(L) {
const ops = "+-*%^/\\&|~<>_!".split('').map(e => e.charCodeAt(0));
const runJS = function(L, L1, pc) {
- let buff = [];
+ let buff = new Uint8Array(300);
let status = 0;
if (!pc || !pc.script) return lauxlib.luaL_error(L, lua.to_luastring("attempt to runJS null script"));
for (;;) {
@@ -527,25 +526,15 @@ const udataval = function(L) {
const d2s = function(L) {
let d = lauxlib.luaL_checknumber(L, 1);
-
- let dv = new DataView(new ArrayBuffer(8));
- dv.setFloat64(0, d, true);
-
- let b = [];
- for (let i = 0; i < 8; i++)
- b.push(dv.getUint8(i, true));
-
- lua.lua_pushlstring(L, b, 8);
+ let b = new ArrayBuffer(8);
+ new DataView(b).setFloat64(0, d, true);
+ lua.lua_pushlstring(L, new Uint8Array(b), 8);
return 1;
};
const s2d = function(L) {
let b = lauxlib.luaL_checkstring(L, 1);
-
- let dv = new DataView(new ArrayBuffer(8));
- for (let i = 0; i < b.length; i++)
- dv.setUint8(i, b[i], true);
-
+ let dv = new DataView(b.buffer);
lua.lua_pushnumber(L, dv.getFloat64(0, true));
return 1;
};