From 3cd41fbb080396624a0d27a7ab88bc13c2803a23 Mon Sep 17 00:00:00 2001 From: Rerumu Date: Wed, 17 Nov 2021 00:36:25 -0500 Subject: [PATCH] Refactor Luau runtime --- runtime/luau.lua | 345 ++++++++++++++++++++++++++--------------------- 1 file changed, 192 insertions(+), 153 deletions(-) diff --git a/runtime/luau.lua b/runtime/luau.lua index 70fcafe..8376054 100644 --- a/runtime/luau.lua +++ b/runtime/luau.lua @@ -1,188 +1,227 @@ -local div = {} +local module = {} -local le = {} -local lt = {} -local ge = {} -local gt = {} - -local band = {} -local bor = {} -local bxor = {} -local bnot = {} - -local shl = {} -local shr = {} - -local extend = {} -local wrap = {} - -local load = {} -local store = {} - --- Helper functions local function no_op(x) return x end -local function unsign_i32(x) - if x < 0 then x = x + 0x100000000 end +do + local div = {} - return x -end + module.div = div -local function unsign_i64(x) - if x < 0 then x = x + 0x10000000000000000 end + function div.i32(lhs, rhs) + if rhs == 0 then error('division by zero') end - return x -end - -local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 end - -local function merge_u64(hi, lo) return hi * 0x100000000 + lo end - -local function black_mask_byte(value, offset) - local mask = bit32.lshift(0xFF, offset * 8) - - return bit32.band(value, bit32.bnot(mask)) -end - -local function load_byte(memory, addr) - local offset = addr % 4 - local value = memory.data[(addr - offset) / 4] - - return bit.band(bit.rshift(value, offset * 8), 0xFF) -end - -local function store_byte(memory, addr, value) - local offset = addr % 4 - local adjust = (addr - offset) / 4 - local lhs = bit32.lshift(value, offset * 8) - local rhs = black_mask_byte(memory.data[adjust] or 0, offset) - - memory.data[adjust] = bit32.bor(lhs, rhs) -end - --- Runtime functions -local function grow_page_num(memory, num) - local old = memory.min - local new = old + num - - if memory.max and new > memory.max then - return -1 - else - memory.min = new - - return old + return math.floor(lhs / rhs) end end -function div.i32(lhs, rhs) - if rhs == 0 then error('division by zero') end +do + local le = {} + local lt = {} + local ge = {} + local gt = {} - return math.floor(lhs / rhs) + module.le = le + module.lt = lt + module.ge = ge + module.gt = gt + + local function unsign_i32(x) + if x < 0 then x = x + 0x100000000 end + + return x + end + + local function unsign_i64(x) + if x < 0 then x = x + 0x10000000000000000 end + + return x + end + + function ge.u32(lhs, rhs) return unsign_i32(lhs) >= unsign_i32(rhs) and 1 or 0 end + function ge.u64(lhs, rhs) return unsign_i64(lhs) >= unsign_i64(rhs) and 1 or 0 end + function gt.u32(lhs, rhs) return unsign_i32(lhs) > unsign_i32(rhs) and 1 or 0 end + function gt.u64(lhs, rhs) return unsign_i64(lhs) > unsign_i64(rhs) and 1 or 0 end + function le.u32(lhs, rhs) return unsign_i32(lhs) <= unsign_i32(rhs) and 1 or 0 end + function le.u64(lhs, rhs) return unsign_i64(lhs) <= unsign_i64(rhs) and 1 or 0 end + function lt.u32(lhs, rhs) return unsign_i32(lhs) < unsign_i32(rhs) and 1 or 0 end + function lt.u64(lhs, rhs) return unsign_i64(lhs) < unsign_i64(rhs) and 1 or 0 end end -function le.u32(lhs, rhs) return unsign_i32(lhs) <= unsign_i32(rhs) and 1 or 0 end +do + local band = {} + local bor = {} + local bxor = {} + local bnot = {} -function lt.u32(lhs, rhs) return unsign_i32(lhs) < unsign_i32(rhs) and 1 or 0 end + module.band = band + module.bor = bor + module.bxor = bxor + module.bnot = bnot -function ge.u32(lhs, rhs) return unsign_i32(lhs) >= unsign_i32(rhs) and 1 or 0 end + band.i32 = bit32.band + band.i64 = bit32.band + bnot.i32 = bit32.bnot + bnot.i64 = bit32.bnot + bor.i32 = bit32.bor + bor.i64 = bit32.bor + bxor.i32 = bit32.bxor + bxor.i64 = bit32.bxor +end -function gt.u32(lhs, rhs) return unsign_i32(lhs) > unsign_i32(rhs) and 1 or 0 end +do + local shl = {} + local shr = {} -function le.u64(lhs, rhs) return unsign_i64(lhs) <= unsign_i64(rhs) and 1 or 0 end + module.shl = shl + module.shr = shr -function lt.u64(lhs, rhs) return unsign_i64(lhs) < unsign_i64(rhs) and 1 or 0 end + shl.i32 = bit32.lshift + shl.i64 = bit32.lshift + shl.u32 = bit32.lshift + shl.u64 = bit32.lshift + shr.i32 = bit32.rshift + shr.i64 = bit32.rshift + shr.u32 = bit32.rshift + shr.u64 = bit32.rshift +end -function ge.u64(lhs, rhs) return unsign_i64(lhs) >= unsign_i64(rhs) and 1 or 0 end +do + local extend = {} + local wrap = {} -function gt.u64(lhs, rhs) return unsign_i64(lhs) > unsign_i64(rhs) and 1 or 0 end + module.extend = extend + module.wrap = wrap -band.i32 = bit32.band -bor.i32 = bit32.bor -bxor.i32 = bit32.bxor -bnot.i32 = bit32.bnot -band.i64 = bit32.band -bor.i64 = bit32.bor -bxor.i64 = bit32.bxor -bnot.i64 = bit32.bnot + extend.i32_u64 = no_op -shl.u32 = bit32.lshift -shr.u32 = bit32.rshift -shl.i32 = bit32.lshift -shr.i32 = bit32.rshift -shl.u64 = bit32.lshift -shr.u64 = bit32.rshift -shl.i64 = bit32.lshift -shr.i64 = bit32.rshift + function wrap.i64_i32(i) return i % 2 ^ 32 end +end -extend.i32_u64 = no_op +do + local load = {} + local store = {} -function wrap.i64_i32(i) return i % 2 ^ 32 end + module.load = load + module.store = store -function load.i32(memory, addr) - if addr % 4 == 0 then - -- aligned read - return memory.data[addr / 4] or 0 - else - -- unaligned read - local b1 = load_byte(memory, addr) - local b2 = bit32.lshift(load_byte(memory, addr + 1), 8) - local b3 = bit32.lshift(load_byte(memory, addr + 2), 16) - local b4 = bit32.lshift(load_byte(memory, addr + 3), 24) + local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 end - return bit32.bor(b1, b2, b3, b4) + local function merge_u64(hi, lo) return hi * 0x100000000 + lo end + + local function black_mask_byte(value, offset) + local mask = bit32.lshift(0xFF, offset * 8) + + return bit32.band(value, bit32.bnot(mask)) + end + + local function load_byte(memory, addr) + local offset = addr % 4 + local value = memory.data[(addr - offset) / 4] + + return bit.band(bit.rshift(value, offset * 8), 0xFF) + end + + local function store_byte(memory, addr, value) + local offset = addr % 4 + local adjust = (addr - offset) / 4 + local lhs = bit32.lshift(bit32.band(value, 0xFF), offset * 8) + local rhs = black_mask_byte(memory.data[adjust] or 0, offset) + + memory.data[adjust] = bit32.bor(lhs, rhs) + end + + load.i32_u8 = load_byte + + function load.i32(memory, addr) + if addr % 4 == 0 then + -- aligned read + return memory.data[addr / 4] or 0 + else + -- unaligned read + local b1 = load_byte(memory, addr) + local b2 = bit32.lshift(load_byte(memory, addr + 1), 8) + local b3 = bit32.lshift(load_byte(memory, addr + 2), 16) + local b4 = bit32.lshift(load_byte(memory, addr + 3), 24) + + return bit32.bor(b1, b2, b3, b4) + end + end + + function load.i64(memory, addr) + local hi = load.i32(memory, addr + 4) + local lo = load.i32(memory, addr) + + return merge_u64(hi, lo) + end + + store.i32_n8 = store_byte + + function store.i32(memory, addr, value) + if addr % 4 == 0 then + -- aligned write + memory.data[addr / 4] = value + else + -- unaligned write + store_byte(memory, addr, value) + store_byte(memory, addr + 1, bit32.rshift(value, 8)) + store_byte(memory, addr + 2, bit32.rshift(value, 16)) + store_byte(memory, addr + 3, bit32.rshift(value, 24)) + end + end + + function store.i64(memory, addr, value) + local hi, lo = rip_u64(value) + + store.i32(memory, addr, lo) + store.i32(memory, addr + 4, hi) end end -function load.i32_u8(memory, addr) - local value = load.i32(memory, addr) +do + local memory = {} - return bit32.band(value, 0xFF) -end + module.memory = memory -function load.i64(memory, addr) - local hi = load.i32(memory, addr + 4) - local lo = load.i32(memory, addr) + function memory.new(min, max) return {min = min, max = max, data = {}} end - return merge_u64(hi, lo) -end + function memory.init(memory, offset, data) + local store_i8 = module.memory.store.i32_n8 + local store_i32 = module.memory.store.i32 -function store.i32(memory, addr, value) - if addr % 4 == 0 then - -- aligned write - memory.data[addr / 4] = value - else - -- unaligned write - store_byte(memory, addr, value) - store_byte(memory, addr + 1, bit32.rshift(value, 8)) - store_byte(memory, addr + 2, bit32.rshift(value, 16)) - store_byte(memory, addr + 3, bit32.rshift(value, 24)) + local len = #data + local rem = len % 4 + + if len >= 4 then + for i = 1, len, 4 do + local v = string.unpack(' memory.max then + return -1 + else + memory.min = new + + return old + end end end -function store.i32_n8(memory, addr, value) store_byte(memory, addr, bit32.band(value, 0xFF)) end - -function store.i64(memory, addr, value) - local hi, lo = rip_u64(value) - - store.i32(memory, addr, lo) - store.i32(memory, addr + 4, hi) -end - -return { - grow_page_num = grow_page_num, - div = div, - le = le, - lt = lt, - ge = ge, - gt = gt, - band = band, - bor = bor, - bxor = bxor, - bnot = bnot, - shl = shl, - shr = shr, - extend = extend, - wrap = wrap, - load = load, - store = store, -} +return module