├── README ├── bench ├── PARAM_arm.txt ├── PARAM_mips.txt ├── PARAM_ppc.txt ├── PARAM_x86.txt ├── SUMCOL_1.txt ├── TEST_md5sum.txt ├── array3d.lua ├── binary-trees.lua ├── chameneos.lua ├── coroutine-ring.lua ├── euler14-bit.lua ├── fannkuch.lua ├── fasta.lua ├── k-nucleotide.lua ├── life.lua ├── mandelbrot-bit.lua ├── mandelbrot.lua ├── md5.lua ├── meteor.lua ├── nbody.lua ├── nsieve-bit-fp.lua ├── nsieve-bit.lua ├── nsieve.lua ├── partialsums.lua ├── pidigits-nogmp.lua ├── ray.lua ├── recursive-ack.lua ├── recursive-fib.lua ├── revcomp.lua ├── scimark-2010-12-20.lua ├── scimark-fft.lua ├── scimark-lu.lua ├── scimark-sor.lua ├── scimark-sparse.lua ├── scimark_lib.lua ├── series.lua ├── spectral-norm.lua └── sum-file.lua └── test ├── README.md ├── bc ├── constov.lua └── index ├── common ├── expect_error.lua ├── ffi_util.inc └── test_runner_canary.lua ├── computations.lua ├── index ├── lang ├── andor.lua ├── assignment.lua ├── compare.lua ├── compare_nan.lua ├── concat.lua ├── constant │ ├── index │ ├── number.lua │ └── table.lua ├── coroutine.lua ├── for.lua ├── gc.lua ├── goto.lua ├── index ├── length.lua ├── meta │ ├── arith.lua │ ├── arith_jit.lua │ ├── call.lua │ ├── cat.lua │ ├── comp.lua │ ├── comp_jit.lua │ ├── debuginfo.lua │ ├── eq.lua │ ├── eq_jit.lua │ ├── framegap.lua │ ├── index │ ├── index.lua │ ├── len.lua │ ├── newindex.lua │ └── nomm.lua ├── modulo.lua ├── self.lua ├── table.lua ├── tail_recursion.lua ├── upvalue │ ├── closure.lua │ └── index └── vararg_jit.lua ├── lib ├── base │ ├── assert.lua │ ├── error.lua │ ├── getfenv.lua │ ├── getsetmetatable.lua │ ├── index │ ├── ipairs.lua │ ├── next.lua │ ├── pairs.lua │ ├── pcall_jit.lua │ ├── select.lua │ ├── tonumber_tostring.lua │ └── xpcall_jit.lua ├── bit.lua ├── contents.lua ├── coroutine │ ├── index │ └── yield.lua ├── ffi │ ├── bit64.lua │ ├── cdata_var.lua │ ├── copy_fill.lua │ ├── err.lua │ ├── ffi_arith_ptr.lua │ ├── ffi_bitfield.lua │ ├── ffi_call.lua │ ├── ffi_callback.lua │ ├── ffi_const.lua │ ├── ffi_convert.lua │ ├── ffi_enum.lua │ ├── ffi_gcstep_recursive.lua │ ├── ffi_jit_arith.lua │ ├── ffi_jit_call.lua │ ├── ffi_jit_conv.lua │ ├── ffi_lex_number.lua │ ├── ffi_metatype.lua │ ├── ffi_new.lua │ ├── ffi_parse_array.lua │ ├── ffi_parse_basic.lua │ ├── ffi_parse_cdef.lua │ ├── ffi_parse_struct.lua │ ├── ffi_tabov.lua │ ├── index │ ├── istype.lua │ ├── jit_array.lua │ ├── jit_complex.lua │ ├── jit_misc.lua │ ├── jit_struct.lua │ ├── meta_tostring.lua │ ├── redir.lua │ └── type_punning.lua ├── index ├── math │ ├── abs.lua │ ├── constants.lua │ ├── index │ └── random.lua ├── string │ ├── byte.lua │ ├── char.lua │ ├── dump.lua │ ├── format │ │ ├── index │ │ └── num.lua │ ├── index │ ├── len.lua │ ├── lower_upper.lua │ ├── metatable.lua │ ├── multiple_functions.lua │ ├── rep.lua │ ├── reverse.lua │ └── sub.lua └── table │ ├── concat.lua │ ├── index │ ├── insert.lua │ ├── misc.lua │ ├── new.lua │ ├── pack.lua │ ├── remove.lua │ └── sort.lua ├── misc ├── alias_alloc.lua ├── api_call.lua ├── catch_wrap.lua ├── coro_traceback.lua ├── coro_yield.lua ├── debug_gc.lua ├── dualnum.lua ├── for_dir.lua ├── fori_coerce.lua ├── gc_rechain.lua ├── gc_trace.lua ├── gcstep.lua ├── hook_active.lua ├── hook_line.lua ├── hook_norecord.lua ├── hook_record.lua ├── hook_top.lua ├── jit_flush.lua ├── lightud.lua ├── loop_unroll.lua ├── parse_comp.lua ├── parse_esc.lua ├── parse_misc.lua ├── phi_conv.lua ├── recurse_deep.lua ├── recurse_tail.lua ├── stack_gc.lua ├── stack_purge.lua ├── stackov.lua ├── stackovc.lua ├── tcall_base.lua ├── tcall_loop.lua ├── tonumber_scan.lua ├── uclo.lua ├── unordered_jit.lua ├── wbarrier.lua ├── wbarrier_jit.lua └── wbarrier_obar.lua ├── opt ├── dse │ ├── array.lua │ ├── field.lua │ └── index ├── fold │ ├── index │ └── kfold.lua ├── fuse.lua ├── fwd │ ├── hrefk_rollback.lua │ ├── index │ ├── tnew_tdup.lua │ └── upval.lua ├── index ├── loop │ ├── index │ └── unroll.lua └── sink │ ├── alloc.lua │ ├── ffi.lua │ ├── ffi_nosink.lua │ ├── index │ └── nosink.lua ├── src ├── cpptest.cpp └── ctest.c ├── sysdep ├── catch_cpp.lua ├── ffi_include_gtk.lua ├── ffi_include_std.lua ├── ffi_lib_c.lua └── ffi_lib_z.lua ├── test.lua ├── trace ├── exit_frame.lua ├── exit_growstack.lua ├── exit_jfuncf.lua ├── gc64_slot_revival.lua ├── index ├── phi │ ├── copyspill.lua │ ├── index │ ├── ref.lua │ └── rotate.lua ├── snap.lua └── stitch.lua └── unportable ├── ffi_arith_int64.lua └── math_special.lua /README: -------------------------------------------------------------------------------- 1 | ******************************************** 2 | ** THIS IS NOT THE TEST SUITE FOR LUAJIT! ** 3 | ******************************************** 4 | 5 | In fact it doesn't even have the steps to build it or run it, 6 | so please don't complain. 7 | 8 | This repo is a place to collect and cleanup tests for LuaJIT. 9 | They should eventually be merged into the main LuaJIT repo. 10 | 11 | It's definitely not in the best state and needs a serious 12 | cleanup effort. Sorry. 13 | 14 | 15 | Many issues need to be resolved before the merge can be performed: 16 | 17 | - Choose a portable test runner 18 | Requirement: very few dependencies, possibly Lua/Shell only 19 | 20 | - Minimal test runner library, wherever assert() is not enough 21 | 22 | - Debugging test failures is a lot simpler, when individual tests can still 23 | be run from the LuaJIT command line without any big dependencies 24 | 25 | - Define consistent grouping of all tests 26 | 27 | - Define consistent naming of all tests 28 | 29 | - Split everything into a lot of tiny tests 30 | 31 | - Reduce time taken to run the test suite 32 | Separate tiers, parallelized testing 33 | 34 | - Some tests can only run under certain configurations (e.g. FFI) 35 | 36 | - Some tests need a clean slate to give reproducible results 37 | Most others should be run from the same state for performance resons 38 | 39 | - Hard to check that the JIT compiler actually generates the intended code 40 | Maybe use a test matching variant of the jit.dump module 41 | 42 | - Portability concerns 43 | 44 | - Avoiding undefined behavior in tests or ignoring it 45 | 46 | - Matrix of architectures + configuration options that need testing 47 | 48 | - Merge tests from other sources, e.g. the various Lua test suites. 49 | 50 | - Tests should go into the LuaJIT git repo, but in separate tarballs 51 | for the releases 52 | 53 | 54 | There are some benchmarks, too: 55 | 56 | - Some of the benchmarks can be used as tests (with low scaling) 57 | by checksumming their output and comparing against known good results 58 | 59 | - Most benchmarks need different scalings to be useful for comparison 60 | on all architectures 61 | 62 | 63 | Note from Mike Pall: 64 | 65 | I've removed all tests of undeterminable origin or that weren't explicitly 66 | contributed with the intention of being part of a public test suite. 67 | 68 | I hereby put all Lua/LuaJIT tests and benchmarks that I wrote under the 69 | public domain. I've removed any copyright headers. 70 | 71 | If I've forgotten an attribution or you want your contributed test to be 72 | removed, please open an issue. 73 | 74 | There are some benchmarks that bear other copyrights, probably public 75 | domain, BSD or MIT licensed. If the status cannot be determined, they 76 | need to be replaced or removed before merging with the LuaJIT repo. 77 | 78 | -------------------------------------------------------------------------------- /bench/PARAM_arm.txt: -------------------------------------------------------------------------------- 1 | array3d 200 2 | binary-trees 13 3 | chameneos 1e6 4 | coroutine-ring 3e6 5 | euler14-bit 5e6 6 | fannkuch 10 7 | fasta 2e6 8 | k-nucleotide 5e5 FASTA_500000 9 | life 10 | mandelbrot 2000 11 | mandelbrot-bit 2000 12 | md5 5000 13 | nbody 1e6 14 | nsieve 9 15 | nsieve-bit 9 16 | nsieve-bit-fp 9 17 | partialsums 2e6 18 | pidigits-nogmp 2000 19 | ray 4 20 | recursive-ack 9 21 | recursive-fib 37 22 | revcomp 1e6 FASTA_1000000 23 | scimark-fft 2000 24 | scimark-lu 300 25 | scimark-sor 5000 26 | scimark-sparse 5e3 27 | series 1500 28 | spectral-norm 1000 29 | sum-file 1000 SUMCOL_1000 30 | -------------------------------------------------------------------------------- /bench/PARAM_mips.txt: -------------------------------------------------------------------------------- 1 | array3d 50 2 | binary-trees 10 3 | chameneos 5e4 4 | coroutine-ring 2e5 5 | euler14-bit 2e4 6 | fannkuch 8 7 | fasta 2e4 8 | k-nucleotide 1e4 FASTA_10000 9 | life 10 | mandelbrot 150 11 | mandelbrot-bit 150 12 | md5 10 13 | nbody 1e4 14 | nsieve 4 15 | nsieve-bit 4 16 | nsieve-bit-fp 2 17 | partialsums 5e4 18 | pidigits-nogmp 150 19 | ray 2 20 | recursive-ack 7 21 | recursive-fib 29 22 | revcomp 5e4 FASTA_50000 23 | scimark-fft 20 24 | scimark-lu 3 25 | scimark-sor 40 26 | scimark-sparse 100 27 | series 50 28 | spectral-norm 100 29 | sum-file 100 SUMCOL_100 30 | -------------------------------------------------------------------------------- /bench/PARAM_ppc.txt: -------------------------------------------------------------------------------- 1 | array3d 200 2 | binary-trees 13 3 | chameneos 1e6 4 | coroutine-ring 4e6 5 | euler14-bit 1e6 6 | fannkuch 9 7 | fasta 5e5 8 | k-nucleotide 1e5 FASTA_100000 9 | life 10 | mandelbrot 800 11 | mandelbrot-bit 800 12 | md5 500 13 | nbody 1e5 14 | nsieve 8 15 | nsieve-bit 8 16 | nsieve-bit-fp 8 17 | partialsums 5e5 18 | pidigits-nogmp 800 19 | ray 5 20 | recursive-ack 9 21 | recursive-fib 34 22 | revcomp 1e6 FASTA_1000000 23 | scimark-fft 500 24 | scimark-lu 100 25 | scimark-sor 1000 26 | scimark-sparse 3000 27 | series 1000 28 | spectral-norm 200 29 | sum-file 1000 SUMCOL_1000 30 | -------------------------------------------------------------------------------- /bench/PARAM_x86.txt: -------------------------------------------------------------------------------- 1 | array3d 300 2 | binary-trees 16 3 | chameneos 1e7 4 | coroutine-ring 2e7 5 | euler14-bit 2e7 6 | fannkuch 11 7 | fasta 25e6 8 | k-nucleotide 5e6 FASTA_5000000 9 | life 10 | mandelbrot 5000 11 | mandelbrot-bit 5000 12 | md5 20000 13 | nbody 5e6 14 | nsieve 12 15 | nsieve-bit 12 16 | nsieve-bit-fp 12 17 | partialsums 1e7 18 | pidigits-nogmp 5000 19 | ray 9 20 | recursive-ack 10 21 | recursive-fib 40 22 | revcomp 5e6 FASTA_5000000 23 | scimark-fft 50000 24 | scimark-lu 5000 25 | scimark-sor 50000 26 | scimark-sparse 15e4 27 | series 10000 28 | spectral-norm 3000 29 | sum-file 5000 SUMCOL_5000 30 | -------------------------------------------------------------------------------- /bench/TEST_md5sum.txt: -------------------------------------------------------------------------------- 1 | binarytrees 10 7202f4e13df7abc5ad8c07f05fe9d644 2 | chameneos 1e5 a629ce12f63050c6656bce175258cf8f 3 | cheapconcr 1000 d29799d1e263810a4db7bbf43ca66499 4 | cheapconcw 1000 d29799d1e263810a4db7bbf43ca66499 5 | fannkuch 8 51e5e372cbc5471ea8940b20ad782319 6 | fasta 1e5 78cd327de6f0a5667da0aa9349888279 7 | knucleotide x 88efb24c1fed533959ed84bb32c88142 = 0 and x < self.nx, "x outside PA") 4 | assert(y >= 0 and y < self.ny, "y outside PA") 5 | assert(z >= 0 and z < self.nz, "z outside PA") 6 | local pos = (z*self.ny + y)*self.nx + x 7 | local image = self.image 8 | if self.packed then 9 | local maxv = self.max_voltage 10 | if p > maxv then self.max_voltage = p*2.0 end 11 | local oldp = image[pos] or 0.0 -- Works with uninitialized table, too 12 | if oldp > maxv then p = p + maxv*2.0 end 13 | image[pos] = p 14 | else 15 | image[pos] = p 16 | end 17 | self.changed = true 18 | self.changed_recently = true 19 | end 20 | 21 | local function array_points(self) 22 | local y, z = 0, 0 23 | return function(self, x) 24 | x = x + 1 25 | if x >= self.nx then 26 | x = 0 27 | y = y + 1 28 | if y >= self.ny then 29 | y = 0 30 | z = z + 1 31 | if z >= self.nz then 32 | return nil, nil, nil 33 | end 34 | end 35 | end 36 | return x, y, z 37 | end, self, 0 38 | end 39 | 40 | local function array_new(nx, ny, nz, packed) 41 | return { 42 | nx = nx, ny = ny, nz = nz, 43 | packed = packed, max_voltage = 0.0, 44 | changed = false, changed_recently = false, 45 | image = {}, -- Preferably use a fixed-type, pre-sized array here. 46 | set = array_set, 47 | points = array_points, 48 | } 49 | end 50 | 51 | local dim = tonumber(arg and arg[1]) or 300 -- Array dimension dim^3 52 | local packed = arg and arg[2] == "packed" -- Packed image or flat 53 | local arr = array_new(dim, dim, dim, packed) 54 | 55 | for x,y,z in arr:points() do 56 | arr:set(x, y, z, x*x) 57 | end 58 | assert(arr.image[dim^3-1] == (dim-1)^2) 59 | 60 | -------------------------------------------------------------------------------- /bench/binary-trees.lua: -------------------------------------------------------------------------------- 1 | 2 | local function BottomUpTree(item, depth) 3 | if depth > 0 then 4 | local i = item + item 5 | depth = depth - 1 6 | local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) 7 | return { item, left, right } 8 | else 9 | return { item } 10 | end 11 | end 12 | 13 | local function ItemCheck(tree) 14 | if tree[2] then 15 | return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) 16 | else 17 | return tree[1] 18 | end 19 | end 20 | 21 | local N = tonumber(arg and arg[1]) or 0 22 | local mindepth = 4 23 | local maxdepth = mindepth + 2 24 | if maxdepth < N then maxdepth = N end 25 | 26 | do 27 | local stretchdepth = maxdepth + 1 28 | local stretchtree = BottomUpTree(0, stretchdepth) 29 | io.write(string.format("stretch tree of depth %d\t check: %d\n", 30 | stretchdepth, ItemCheck(stretchtree))) 31 | end 32 | 33 | local longlivedtree = BottomUpTree(0, maxdepth) 34 | 35 | for depth=mindepth,maxdepth,2 do 36 | local iterations = 2 ^ (maxdepth - depth + mindepth) 37 | local check = 0 38 | for i=1,iterations do 39 | check = check + ItemCheck(BottomUpTree(1, depth)) + 40 | ItemCheck(BottomUpTree(-1, depth)) 41 | end 42 | io.write(string.format("%d\t trees of depth %d\t check: %d\n", 43 | iterations*2, depth, check)) 44 | end 45 | 46 | io.write(string.format("long lived tree of depth %d\t check: %d\n", 47 | maxdepth, ItemCheck(longlivedtree))) 48 | -------------------------------------------------------------------------------- /bench/chameneos.lua: -------------------------------------------------------------------------------- 1 | 2 | local co = coroutine 3 | local create, resume, yield = co.create, co.resume, co.yield 4 | 5 | local N = tonumber(arg and arg[1]) or 10 6 | local first, second 7 | 8 | -- Meet another creature. 9 | local function meet(me) 10 | while second do yield() end -- Wait until meeting place clears. 11 | local other = first 12 | if other then -- Hey, I found a new friend! 13 | first = nil 14 | second = me 15 | else -- Sniff, nobody here (yet). 16 | local n = N - 1 17 | if n < 0 then return end -- Uh oh, the mall is closed. 18 | N = n 19 | first = me 20 | repeat yield(); other = second until other -- Wait for another creature. 21 | second = nil 22 | yield() -- Be nice and let others meet up. 23 | end 24 | return other 25 | end 26 | 27 | -- Create a very social creature. 28 | local function creature(color) 29 | return create(function() 30 | local me = color 31 | for met=0,1000000000 do 32 | local other = meet(me) 33 | if not other then return met end 34 | if me ~= other then 35 | if me == "blue" then me = other == "red" and "yellow" or "red" 36 | elseif me == "red" then me = other == "blue" and "yellow" or "blue" 37 | else me = other == "blue" and "red" or "blue" end 38 | end 39 | end 40 | end) 41 | end 42 | 43 | -- Trivial round-robin scheduler. 44 | local function schedule(threads) 45 | local resume = resume 46 | local nthreads, meetings = #threads, 0 47 | repeat 48 | for i=1,nthreads do 49 | local thr = threads[i] 50 | if not thr then return meetings end 51 | local ok, met = resume(thr) 52 | if met then 53 | meetings = meetings + met 54 | threads[i] = nil 55 | end 56 | end 57 | until false 58 | end 59 | 60 | -- A bunch of colorful creatures. 61 | local threads = { 62 | creature("blue"), 63 | creature("red"), 64 | creature("yellow"), 65 | creature("blue"), 66 | } 67 | 68 | io.write(schedule(threads), "\n") 69 | -------------------------------------------------------------------------------- /bench/coroutine-ring.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://shootout.alioth.debian.org/ 3 | -- contributed by Sam Roberts 4 | -- reviewed by Bruno Massa 5 | 6 | local n = tonumber(arg and arg[1]) or 2e7 7 | 8 | -- fixed size pool 9 | local poolsize = 503 10 | local threads = {} 11 | 12 | -- cache these to avoid global environment lookups 13 | local create = coroutine.create 14 | local resume = coroutine.resume 15 | local yield = coroutine.yield 16 | 17 | local id = 1 18 | local token = 0 19 | local ok 20 | 21 | local body = function(token) 22 | while true do 23 | token = yield(token + 1) 24 | end 25 | end 26 | 27 | -- create all threads 28 | for id = 1, poolsize do 29 | threads[id] = create(body) 30 | end 31 | 32 | -- send the token 33 | repeat 34 | if id == poolsize then 35 | id = 1 36 | else 37 | id = id + 1 38 | end 39 | ok, token = resume(threads[id], token) 40 | until token == n 41 | 42 | io.write(id, "\n") 43 | -------------------------------------------------------------------------------- /bench/euler14-bit.lua: -------------------------------------------------------------------------------- 1 | 2 | local bit = require("bit") 3 | local bnot, bor, band = bit.bnot, bit.bor, bit.band 4 | local shl, shr = bit.lshift, bit.rshift 5 | 6 | local N = tonumber(arg and arg[1]) or 10000000 7 | local cache, m, n = { 1 }, 1, 1 8 | if arg and arg[2] then cache = nil end 9 | for i=2,N do 10 | local j = i 11 | for len=1,1000000000 do 12 | j = bor(band(shr(j,1), band(j,1)-1), band(shl(j,1)+j+1, bnot(band(j,1)-1))) 13 | if cache then 14 | local x = cache[j]; if x then j = x+len; break end 15 | elseif j == 1 then 16 | j = len+1; break 17 | end 18 | end 19 | if cache then cache[i] = j end 20 | if j > m then m, n = j, i end 21 | end 22 | io.write("Found ", n, " (chain length: ", m, ")\n") 23 | -------------------------------------------------------------------------------- /bench/fannkuch.lua: -------------------------------------------------------------------------------- 1 | 2 | local function fannkuch(n) 3 | local p, q, s, odd, check, maxflips = {}, {}, {}, true, 0, 0 4 | for i=1,n do p[i] = i; q[i] = i; s[i] = i end 5 | repeat 6 | -- Print max. 30 permutations. 7 | if check < 30 then 8 | if not p[n] then return maxflips end -- Catch n = 0, 1, 2. 9 | io.write(unpack(p)); io.write("\n") 10 | check = check + 1 11 | end 12 | -- Copy and flip. 13 | local q1 = p[1] -- Cache 1st element. 14 | if p[n] ~= n and q1 ~= 1 then -- Avoid useless work. 15 | for i=2,n do q[i] = p[i] end -- Work on a copy. 16 | local flips = 1 -- Flip ... 17 | while true do 18 | local qq = q[q1] 19 | if qq == 1 then -- ... until 1st element is 1. 20 | if flips > maxflips then maxflips = flips end -- New maximum? 21 | break 22 | end 23 | q[q1] = q1 24 | if q1 >= 4 then 25 | local i, j = 2, q1 - 1 26 | repeat q[i], q[j] = q[j], q[i]; i = i + 1; j = j - 1; until i >= j 27 | end 28 | q1 = qq 29 | flips=flips+1 30 | end 31 | end 32 | -- Permute. 33 | if odd then 34 | p[2], p[1] = p[1], p[2]; odd = false -- Rotate 1<-2. 35 | else 36 | p[2], p[3] = p[3], p[2]; odd = true -- Rotate 1<-2 and 1<-2<-3. 37 | for i=3,n do 38 | local sx = s[i] 39 | if sx ~= 1 then s[i] = sx-1; break end 40 | if i == n then return maxflips end -- Out of permutations. 41 | s[i] = i 42 | -- Rotate 1<-...<-i+1. 43 | local t=p[1]; for j=i+1,1,-1 do p[j],t=t,p[j] end 44 | end 45 | end 46 | until false 47 | end 48 | 49 | local n = tonumber(arg and arg[1]) or 1 50 | io.write("Pfannkuchen(", n, ") = ", fannkuch(n), "\n") 51 | -------------------------------------------------------------------------------- /bench/fasta.lua: -------------------------------------------------------------------------------- 1 | 2 | local Last = 42 3 | local function random(max) 4 | local y = (Last * 3877 + 29573) % 139968 5 | Last = y 6 | return (max * y) / 139968 7 | end 8 | 9 | local function make_repeat_fasta(id, desc, s, n) 10 | local write, sub = io.write, string.sub 11 | write(">", id, " ", desc, "\n") 12 | local p, sn, s2 = 1, #s, s..s 13 | for i=60,n,60 do 14 | write(sub(s2, p, p + 59), "\n") 15 | p = p + 60; if p > sn then p = p - sn end 16 | end 17 | local tail = n % 60 18 | if tail > 0 then write(sub(s2, p, p + tail-1), "\n") end 19 | end 20 | 21 | local function make_random_fasta(id, desc, bs, n) 22 | io.write(">", id, " ", desc, "\n") 23 | loadstring([=[ 24 | local write, char, unpack, n, random = io.write, string.char, unpack, ... 25 | local buf, p = {}, 1 26 | for i=60,n,60 do 27 | for j=p,p+59 do ]=]..bs..[=[ end 28 | buf[p+60] = 10; p = p + 61 29 | if p >= 2048 then write(char(unpack(buf, 1, p-1))); p = 1 end 30 | end 31 | local tail = n % 60 32 | if tail > 0 then 33 | for j=p,p+tail-1 do ]=]..bs..[=[ end 34 | p = p + tail; buf[p] = 10; p = p + 1 35 | end 36 | write(char(unpack(buf, 1, p-1))) 37 | ]=], desc)(n, random) 38 | end 39 | 40 | local function bisect(c, p, lo, hi) 41 | local n = hi - lo 42 | if n == 0 then return "buf[j] = "..c[hi].."\n" end 43 | local mid = math.floor(n / 2) 44 | return "if r < "..p[lo+mid].." then\n"..bisect(c, p, lo, lo+mid).. 45 | "else\n"..bisect(c, p, lo+mid+1, hi).."end\n" 46 | end 47 | 48 | local function make_bisect(tab) 49 | local c, p, sum = {}, {}, 0 50 | for i,row in ipairs(tab) do 51 | c[i] = string.byte(row[1]) 52 | sum = sum + row[2] 53 | p[i] = sum 54 | end 55 | return "local r = random(1)\n"..bisect(c, p, 1, #tab) 56 | end 57 | 58 | local alu = 59 | "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG".. 60 | "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA".. 61 | "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT".. 62 | "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA".. 63 | "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG".. 64 | "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC".. 65 | "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA" 66 | 67 | local iub = make_bisect{ 68 | { "a", 0.27 }, 69 | { "c", 0.12 }, 70 | { "g", 0.12 }, 71 | { "t", 0.27 }, 72 | { "B", 0.02 }, 73 | { "D", 0.02 }, 74 | { "H", 0.02 }, 75 | { "K", 0.02 }, 76 | { "M", 0.02 }, 77 | { "N", 0.02 }, 78 | { "R", 0.02 }, 79 | { "S", 0.02 }, 80 | { "V", 0.02 }, 81 | { "W", 0.02 }, 82 | { "Y", 0.02 }, 83 | } 84 | 85 | local homosapiens = make_bisect{ 86 | { "a", 0.3029549426680 }, 87 | { "c", 0.1979883004921 }, 88 | { "g", 0.1975473066391 }, 89 | { "t", 0.3015094502008 }, 90 | } 91 | 92 | local N = tonumber(arg and arg[1]) or 1000 93 | make_repeat_fasta('ONE', 'Homo sapiens alu', alu, N*2) 94 | make_random_fasta('TWO', 'IUB ambiguity codes', iub, N*3) 95 | make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, N*5) 96 | -------------------------------------------------------------------------------- /bench/k-nucleotide.lua: -------------------------------------------------------------------------------- 1 | 2 | local function kfrequency(seq, freq, k, frame) 3 | local sub = string.sub 4 | local k1 = k - 1 5 | for i=frame,#seq-k1,k do 6 | local c = sub(seq, i, i+k1) 7 | freq[c] = (freq[c] or 0) + 1 8 | end 9 | end 10 | 11 | local function count(seq, frag) 12 | local k = #frag 13 | local freq = {} 14 | for frame=1,k do kfrequency(seq, freq, k, frame) end 15 | io.write(freq[frag] or 0, "\t", frag, "\n") 16 | end 17 | 18 | local function frequency(seq, k) 19 | local freq = {} 20 | for frame=1,k do kfrequency(seq, freq, k, frame) end 21 | local sfreq, sn, sum = {}, 1, 0 22 | for c,v in pairs(freq) do sfreq[sn] = c; sn = sn + 1; sum = sum + v end 23 | table.sort(sfreq, function(a, b) 24 | local fa, fb = freq[a], freq[b] 25 | return fa == fb and a > b or fa > fb 26 | end) 27 | for _,c in ipairs(sfreq) do 28 | io.write(string.format("%s %0.3f\n", c, (freq[c]*100)/sum)) 29 | end 30 | io.write("\n") 31 | end 32 | 33 | local function readseq() 34 | local sub = string.sub 35 | for line in io.lines() do 36 | if sub(line, 1, 1) == ">" and sub(line, 2, 6) == "THREE" then break end 37 | end 38 | local lines, ln = {}, 0 39 | for line in io.lines() do 40 | local c = sub(line, 1, 1) 41 | if c == ">" then 42 | break 43 | elseif c ~= ";" then 44 | ln = ln + 1 45 | lines[ln] = line 46 | end 47 | end 48 | return string.upper(table.concat(lines, "", 1, ln)) 49 | end 50 | 51 | local seq = readseq() 52 | frequency(seq, 1) 53 | frequency(seq, 2) 54 | count(seq, "GGT") 55 | count(seq, "GGTA") 56 | count(seq, "GGTATT") 57 | count(seq, "GGTATTTTAATT") 58 | count(seq, "GGTATTTTAATTTATAGT") 59 | -------------------------------------------------------------------------------- /bench/life.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuaJIT/LuaJIT-test-cleanup/014708bceb70550a3ab8d539cff14d9085ca9cb8/bench/life.lua -------------------------------------------------------------------------------- /bench/mandelbrot-bit.lua: -------------------------------------------------------------------------------- 1 | 2 | local bit = require("bit") 3 | local bor, band = bit.bor, bit.band 4 | local shl, shr, rol = bit.lshift, bit.rshift, bit.rol 5 | local write, char, unpack = io.write, string.char, unpack 6 | local N = tonumber(arg and arg[1]) or 100 7 | local M, buf = 2/N, {} 8 | write("P4\n", N, " ", N, "\n") 9 | for y=0,N-1 do 10 | local Ci, b, p = y*M-1, -16777216, 0 11 | local Ciq = Ci*Ci 12 | for x=0,N-1,2 do 13 | local Cr, Cr2 = x*M-1.5, (x+1)*M-1.5 14 | local Zr, Zi, Zrq, Ziq = Cr, Ci, Cr*Cr, Ciq 15 | local Zr2, Zi2, Zrq2, Ziq2 = Cr2, Ci, Cr2*Cr2, Ciq 16 | b = rol(b, 2) 17 | for i=1,49 do 18 | Zi = Zr*Zi*2 + Ci; Zi2 = Zr2*Zi2*2 + Ci 19 | Zr = Zrq-Ziq + Cr; Zr2 = Zrq2-Ziq2 + Cr2 20 | Ziq = Zi*Zi; Ziq2 = Zi2*Zi2 21 | Zrq = Zr*Zr; Zrq2 = Zr2*Zr2 22 | if band(b, 2) ~= 0 and Zrq+Ziq > 4.0 then b = band(b, -3) end 23 | if band(b, 1) ~= 0 and Zrq2+Ziq2 > 4.0 then b = band(b, -2) end 24 | if band(b, 3) == 0 then break end 25 | end 26 | if b >= 0 then p = p + 1; buf[p] = b; b = -16777216; end 27 | end 28 | if b ~= -16777216 then 29 | if band(N, 1) ~= 0 then b = shr(b, 1) end 30 | p = p + 1; buf[p] = shl(b, 8-band(N, 7)) 31 | end 32 | write(char(unpack(buf, 1, p))) 33 | end 34 | -------------------------------------------------------------------------------- /bench/mandelbrot.lua: -------------------------------------------------------------------------------- 1 | 2 | local write, char, unpack = io.write, string.char, unpack 3 | local N = tonumber(arg and arg[1]) or 100 4 | local M, ba, bb, buf = 2/N, 2^(N%8+1)-1, 2^(8-N%8), {} 5 | write("P4\n", N, " ", N, "\n") 6 | for y=0,N-1 do 7 | local Ci, b, p = y*M-1, 1, 0 8 | for x=0,N-1 do 9 | local Cr = x*M-1.5 10 | local Zr, Zi, Zrq, Ziq = Cr, Ci, Cr*Cr, Ci*Ci 11 | b = b + b 12 | for i=1,49 do 13 | Zi = Zr*Zi*2 + Ci 14 | Zr = Zrq-Ziq + Cr 15 | Ziq = Zi*Zi 16 | Zrq = Zr*Zr 17 | if Zrq+Ziq > 4.0 then b = b + 1; break; end 18 | end 19 | if b >= 256 then p = p + 1; buf[p] = 511 - b; b = 1; end 20 | end 21 | if b ~= 1 then p = p + 1; buf[p] = (ba-b)*bb; end 22 | write(char(unpack(buf, 1, p))) 23 | end 24 | -------------------------------------------------------------------------------- /bench/nsieve-bit-fp.lua: -------------------------------------------------------------------------------- 1 | 2 | local floor, ceil = math.floor, math.ceil 3 | 4 | local precision = 50 -- Maximum precision of lua_Number (minus safety margin). 5 | local onebits = (2^precision)-1 6 | 7 | local function nsieve(p, m) 8 | local cm = ceil(m/precision) 9 | do local onebits = onebits; for i=0,cm do p[i] = onebits end end 10 | local count, idx, bit = 0, 2, 2 11 | for i=2,m do 12 | local r = p[idx] / bit 13 | if r - floor(r) >= 0.5 then -- Bit set? 14 | local kidx, kbit = idx, bit 15 | for k=i+i,m,i do 16 | kidx = kidx + i 17 | while kidx >= cm do kidx = kidx - cm; kbit = kbit + kbit end 18 | local x = p[kidx] 19 | local r = x / kbit 20 | if r - floor(r) >= 0.5 then p[kidx] = x - kbit*0.5 end -- Clear bit. 21 | end 22 | count = count + 1 23 | end 24 | idx = idx + 1 25 | if idx >= cm then idx = 0; bit = bit + bit end 26 | end 27 | return count 28 | end 29 | 30 | local N = tonumber(arg and arg[1]) or 1 31 | if N < 2 then N = 2 end 32 | local primes = {} 33 | 34 | for i=0,2 do 35 | local m = (2^(N-i))*10000 36 | io.write(string.format("Primes up to %8d %8d\n", m, nsieve(primes, m))) 37 | end 38 | -------------------------------------------------------------------------------- /bench/nsieve-bit.lua: -------------------------------------------------------------------------------- 1 | 2 | local bit = require("bit") 3 | local band, bxor, rshift, rol = bit.band, bit.bxor, bit.rshift, bit.rol 4 | 5 | local function nsieve(p, m) 6 | local count = 0 7 | for i=0,rshift(m, 5) do p[i] = -1 end 8 | for i=2,m do 9 | if band(rshift(p[rshift(i, 5)], i), 1) ~= 0 then 10 | count = count + 1 11 | for j=i+i,m,i do 12 | local jx = rshift(j, 5) 13 | p[jx] = band(p[jx], rol(-2, j)) 14 | end 15 | end 16 | end 17 | return count 18 | end 19 | 20 | local N = tonumber(arg and arg[1]) or 1 21 | if N < 2 then N = 2 end 22 | local primes = {} 23 | 24 | for i=0,2 do 25 | local m = (2^(N-i))*10000 26 | io.write(string.format("Primes up to %8d %8d\n", m, nsieve(primes, m))) 27 | end 28 | -------------------------------------------------------------------------------- /bench/nsieve.lua: -------------------------------------------------------------------------------- 1 | 2 | local function nsieve(p, m) 3 | for i=2,m do p[i] = true end 4 | local count = 0 5 | for i=2,m do 6 | if p[i] then 7 | for k=i+i,m,i do p[k] = false end 8 | count = count + 1 9 | end 10 | end 11 | return count 12 | end 13 | 14 | local N = tonumber(arg and arg[1]) or 1 15 | if N < 2 then N = 2 end 16 | local primes = {} 17 | 18 | for i=0,2 do 19 | local m = (2^(N-i))*10000 20 | io.write(string.format("Primes up to %8d %8d\n", m, nsieve(primes, m))) 21 | end 22 | -------------------------------------------------------------------------------- /bench/partialsums.lua: -------------------------------------------------------------------------------- 1 | 2 | local n = tonumber(arg[1]) 3 | local function pr(fmt, x) io.write(string.format(fmt, x)) end 4 | 5 | local a1, a2, a3, a4, a5, a6, a7, a8, a9, alt = 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 6 | local sqrt, sin, cos = math.sqrt, math.sin, math.cos 7 | for k=1,n do 8 | local k2, sk, ck = k*k, sin(k), cos(k) 9 | local k3 = k2*k 10 | a1 = a1 + (2/3)^k 11 | a2 = a2 + 1/sqrt(k) 12 | a3 = a3 + 1/(k2+k) 13 | a4 = a4 + 1/(k3*sk*sk) 14 | a5 = a5 + 1/(k3*ck*ck) 15 | a6 = a6 + 1/k 16 | a7 = a7 + 1/k2 17 | a8 = a8 + alt/k 18 | a9 = a9 + alt/(k+k-1) 19 | alt = -alt 20 | end 21 | pr("%.9f\t(2/3)^k\n", a1) 22 | pr("%.9f\tk^-0.5\n", a2) 23 | pr("%.9f\t1/k(k+1)\n", a3) 24 | pr("%.9f\tFlint Hills\n", a4) 25 | pr("%.9f\tCookson Hills\n", a5) 26 | pr("%.9f\tHarmonic\n", a6) 27 | pr("%.9f\tRiemann Zeta\n", a7) 28 | pr("%.9f\tAlternating Harmonic\n", a8) 29 | pr("%.9f\tGregory\n", a9) 30 | -------------------------------------------------------------------------------- /bench/recursive-ack.lua: -------------------------------------------------------------------------------- 1 | local function Ack(m, n) 2 | if m == 0 then return n+1 end 3 | if n == 0 then return Ack(m-1, 1) end 4 | return Ack(m-1, (Ack(m, n-1))) -- The parentheses are deliberate. 5 | end 6 | 7 | local N = tonumber(arg and arg[1]) or 10 8 | io.write("Ack(3,", N ,"): ", Ack(3,N), "\n") 9 | -------------------------------------------------------------------------------- /bench/recursive-fib.lua: -------------------------------------------------------------------------------- 1 | local function fib(n) 2 | if n < 2 then return 1 end 3 | return fib(n-2) + fib(n-1) 4 | end 5 | 6 | local n = tonumber(arg[1]) or 10 7 | io.write(string.format("Fib(%d): %d\n", n, fib(n))) 8 | -------------------------------------------------------------------------------- /bench/revcomp.lua: -------------------------------------------------------------------------------- 1 | 2 | local sub = string.sub 3 | iubc = setmetatable({ 4 | A="T", C="G", B="V", D="H", K="M", R="Y", 5 | a="T", c="G", b="V", d="H", k="M", r="Y", 6 | T="A", G="C", V="B", H="D", M="K", Y="R", U="A", 7 | t="A", g="C", v="B", h="D", m="K", y="R", u="A", 8 | N="N", S="S", W="W", n="N", s="S", w="W", 9 | }, { __index = function(t, s) 10 | local r = t[sub(s, 2)]..t[sub(s, 1, 1)]; t[s] = r; return r end }) 11 | 12 | local wcode = [=[ 13 | return function(t, n) 14 | if n == 1 then return end 15 | local iubc, sub, write = iubc, string.sub, io.write 16 | local s = table.concat(t, "", 1, n-1) 17 | for i=#s-59,1,-60 do 18 | write(]=] 19 | for i=59,3,-4 do wcode = wcode.."iubc[sub(s, i+"..(i-3)..", i+"..i..")], " end 20 | wcode = wcode..[=["\n") 21 | end 22 | local r = #s % 60 23 | if r ~= 0 then 24 | for i=r,1,-4 do write(iubc[sub(s, i-3 < 1 and 1 or i-3, i)]) end 25 | write("\n") 26 | end 27 | end 28 | ]=] 29 | local writerev = loadstring(wcode)() 30 | 31 | local t, n = {}, 1 32 | for line in io.lines() do 33 | local c = sub(line, 1, 1) 34 | if c == ">" then writerev(t, n); io.write(line, "\n"); n = 1 35 | elseif c ~= ";" then t[n] = line; n = n + 1 end 36 | end 37 | writerev(t, n) 38 | -------------------------------------------------------------------------------- /bench/scimark-fft.lua: -------------------------------------------------------------------------------- 1 | require("scimark_lib").FFT(1024)(tonumber(arg and arg[1]) or 50000) 2 | -------------------------------------------------------------------------------- /bench/scimark-lu.lua: -------------------------------------------------------------------------------- 1 | require("scimark_lib").LU(100)(tonumber(arg and arg[1]) or 5000) 2 | -------------------------------------------------------------------------------- /bench/scimark-sor.lua: -------------------------------------------------------------------------------- 1 | require("scimark_lib").SOR(100)(tonumber(arg and arg[1]) or 50000) 2 | -------------------------------------------------------------------------------- /bench/scimark-sparse.lua: -------------------------------------------------------------------------------- 1 | require("scimark_lib").SPARSE(1000, 5000)(tonumber(arg and arg[1]) or 150000) 2 | -------------------------------------------------------------------------------- /bench/series.lua: -------------------------------------------------------------------------------- 1 | 2 | local function integrate(x0, x1, nsteps, omegan, f) 3 | local x, dx = x0, (x1-x0)/nsteps 4 | local rvalue = ((x0+1)^x0 * f(omegan*x0)) / 2 5 | for i=3,nsteps do 6 | x = x + dx 7 | rvalue = rvalue + (x+1)^x * f(omegan*x) 8 | end 9 | return (rvalue + ((x1+1)^x1 * f(omegan*x1)) / 2) * dx 10 | end 11 | 12 | local function series(n) 13 | local sin, cos = math.sin, math.cos 14 | local omega = math.pi 15 | local t = {} 16 | 17 | t[1] = integrate(0, 2, 1000, 0, function() return 1 end) / 2 18 | t[2] = 0 19 | 20 | for i=2,n do 21 | t[2*i-1] = integrate(0, 2, 1000, omega*i, cos) 22 | t[2*i] = integrate(0, 2, 1000, omega*i, sin) 23 | end 24 | 25 | return t 26 | end 27 | 28 | local n = tonumber(arg and arg[1]) or 10000 29 | local tm = os.clock() 30 | local t = series(n) 31 | tm = os.clock() - tm 32 | assert(math.abs(t[1]-2.87295) < 0.00001) 33 | io.write(string.format("size %d, %.2f s, %.1f iterations/s\n", 34 | n, tm, (2*n-1)/tm)) 35 | -------------------------------------------------------------------------------- /bench/spectral-norm.lua: -------------------------------------------------------------------------------- 1 | 2 | local function A(i, j) 3 | local ij = i+j-1 4 | return 1.0 / (ij * (ij-1) * 0.5 + i) 5 | end 6 | 7 | local function Av(x, y, N) 8 | for i=1,N do 9 | local a = 0 10 | for j=1,N do a = a + x[j] * A(i, j) end 11 | y[i] = a 12 | end 13 | end 14 | 15 | local function Atv(x, y, N) 16 | for i=1,N do 17 | local a = 0 18 | for j=1,N do a = a + x[j] * A(j, i) end 19 | y[i] = a 20 | end 21 | end 22 | 23 | local function AtAv(x, y, t, N) 24 | Av(x, t, N) 25 | Atv(t, y, N) 26 | end 27 | 28 | local N = tonumber(arg and arg[1]) or 100 29 | local u, v, t = {}, {}, {} 30 | for i=1,N do u[i] = 1 end 31 | 32 | for i=1,10 do AtAv(u, v, t, N) AtAv(v, u, t, N) end 33 | 34 | local vBv, vv = 0, 0 35 | for i=1,N do 36 | local ui, vi = u[i], v[i] 37 | vBv = vBv + ui*vi 38 | vv = vv + vi*vi 39 | end 40 | io.write(string.format("%0.9f\n", math.sqrt(vBv / vv))) 41 | -------------------------------------------------------------------------------- /bench/sum-file.lua: -------------------------------------------------------------------------------- 1 | 2 | local sum = 0 3 | for line in io.lines() do 4 | sum = sum + line 5 | end 6 | io.write(sum, "\n") 7 | -------------------------------------------------------------------------------- /test/bc/constov.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- float 3 | local t = { "local x\n" } 4 | for i=2,65537 do t[i] = "x="..i..".5\n" end 5 | assert(loadstring(table.concat(t)) ~= nil) 6 | t[65538] = "x=65538.5" 7 | assert(loadstring(table.concat(t)) == nil) 8 | end 9 | 10 | do --- int 11 | local t = { "local x\n" } 12 | for i=2,65537 do t[i] = "x='"..i.."'\n" end 13 | assert(loadstring(table.concat(t)) ~= nil) 14 | t[65538] = "x='65538'" 15 | assert(loadstring(table.concat(t)) == nil) 16 | end 17 | -------------------------------------------------------------------------------- /test/bc/index: -------------------------------------------------------------------------------- 1 | constov.lua +slow 2 | -------------------------------------------------------------------------------- /test/common/expect_error.lua: -------------------------------------------------------------------------------- 1 | return function(f, msg) 2 | local ok, err = pcall(f) 3 | if ok then error("error check unexpectedly succeeded", 2) end 4 | if msg then 5 | if type(err) ~= "string" then 6 | error("error check failed with "..tostring(err), 2) 7 | end 8 | local line, err2 = string.match(err, ":(%d*): (.*)") 9 | if err2 ~= msg then 10 | if err2:gsub(" got no value", " got nil") == msg then 11 | return 12 | end 13 | error("error check failed with "..err, 2) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/common/ffi_util.inc: -------------------------------------------------------------------------------- 1 | -- This should be turned into a proper module and not use globals. 2 | -- Or combined into a generiv test utility module. With FFI 3 | -- functionality turned off, if the FFI module is not built-in. 4 | 5 | local ffi = require("ffi") 6 | 7 | function checkfail(t, f) 8 | f = f or ffi.typeof 9 | for i=1,1e9 do 10 | local tp = t[i] 11 | if not tp then break end 12 | assert(pcall(f, tp) == false, tp) 13 | end 14 | end 15 | 16 | function checktypes(t) 17 | for i=1,1e9,3 do 18 | local tp = t[i+2] 19 | if not tp then break end 20 | local id = ffi.typeof(tp) 21 | assert(ffi.sizeof(id) == t[i], tp) 22 | assert(ffi.alignof(id) == t[i+1], tp) 23 | end 24 | end 25 | 26 | function fails(f, ...) 27 | if pcall(f, ...) ~= false then error("failure expected", 2) end 28 | end 29 | 30 | local incroot = os.getenv("INCROOT") or "/usr/include" 31 | local cdefs = os.getenv("CDEFS") or "" 32 | 33 | function include(name) 34 | local flags = ffi.abi("32bit") and "-m32" or "-m64" 35 | if string.sub(name, 1, 1) ~= "/" then name = incroot.."/"..name end 36 | local fp = assert(io.popen("cc -E -P "..flags.." "..cdefs.." "..name)) 37 | local s = fp:read("*a") 38 | fp:close() 39 | ffi.cdef(s) 40 | end 41 | 42 | -------------------------------------------------------------------------------- /test/common/test_runner_canary.lua: -------------------------------------------------------------------------------- 1 | return "canary is alive" 2 | -------------------------------------------------------------------------------- /test/computations.lua: -------------------------------------------------------------------------------- 1 | do --- ack 2 | local function Ack(m, n) 3 | if m == 0 then return n+1 end 4 | if n == 0 then return Ack(m-1, 1) end 5 | return Ack(m-1, (Ack(m, n-1))) -- The parentheses are deliberate. 6 | end 7 | 8 | assert(Ack(3,5) == 253) 9 | end 10 | 11 | do --- ack notail 12 | local function Ack(m, n) 13 | if m == 0 then return n+1 end 14 | if n == 0 then return Ack(m-1, 1) end 15 | return (Ack(m-1, (Ack(m, n-1)))) -- The parentheses are deliberate. 16 | end 17 | 18 | assert(Ack(3,5) == 253) 19 | end 20 | 21 | do --- fac 22 | local function fac(n) 23 | local x = 1 24 | for i=2,n do 25 | x = x * i 26 | end 27 | return x 28 | end 29 | 30 | assert(fac(10) == 3628800) 31 | end 32 | 33 | do --- ffib 34 | local function ffib(n) 35 | if n <= 2 then return n,1 end 36 | if n % 2 == 1 then 37 | local a,b = ffib((n-1)/2) 38 | local aa = a*a 39 | return aa+a*(b+b), aa+b*b 40 | else 41 | local a,b = ffib(n/2-1) 42 | local ab = a+b 43 | return ab*ab+a*a, (ab+b)*a 44 | end 45 | end 46 | 47 | local function fib(n) 48 | return (ffib(n)) 49 | end 50 | 51 | assert(fib(40) == 165580141) 52 | assert(fib(39) == 102334155) 53 | assert(fib(77) == 8944394323791464) 54 | end 55 | 56 | do --- fib 57 | local function fib(n) 58 | if n < 2 then return 1 end 59 | return fib(n-2) + fib(n-1) 60 | end 61 | 62 | assert(fib(27) == 317811) 63 | end 64 | 65 | do --- nsieve 66 | local function nsieve(m) 67 | local isPrime = {} 68 | for i=2,m do isPrime[i] = true end 69 | local count = 0 70 | for i=2,m do 71 | if isPrime[i] then 72 | for k=i+i,m,i do isPrime[k] = false end 73 | count = count + 1 74 | end 75 | end 76 | return count 77 | end 78 | 79 | assert(nsieve(100) == 25) 80 | assert(nsieve(12345) == 1474) 81 | end 82 | 83 | do --- recsum 84 | local function sum(n) 85 | if n == 1 then return 1 end 86 | return n + sum(n-1) 87 | end 88 | 89 | for i=1, 100 do 90 | assert(sum(i) == i*(i+1)/2) 91 | end 92 | end 93 | 94 | do --- recsump 95 | local abs = math.abs 96 | local function sum(n) 97 | if n == 1 then return 1 end 98 | return abs(n + sum(n-1)) 99 | end 100 | 101 | for i=1, 100 do 102 | assert(sum(i) == i*(i+1)/2) 103 | end 104 | end 105 | 106 | do --- tak 107 | local function tak(x, y, z) 108 | if y >= x then return z end 109 | return tak(tak(x-1, y, z), tak(y-1, z, x), (tak(z-1, x, y))) 110 | end 111 | 112 | assert(tak(21, 14, 7) == 14) 113 | end 114 | -------------------------------------------------------------------------------- /test/index: -------------------------------------------------------------------------------- 1 | lang 2 | lib 3 | bc +luajit>=2 4 | computations.lua 5 | trace +jit 6 | opt +jit 7 | -------------------------------------------------------------------------------- /test/lang/andor.lua: -------------------------------------------------------------------------------- 1 | do --- smoke 2 | local x = ((1 or false) and true) or false 3 | assert(x == true) 4 | end 5 | 6 | do --- allcases 7 | local basiccases = { 8 | {"nil", nil}, 9 | {"false", false}, 10 | {"true", true}, 11 | {"10", 10}, 12 | } 13 | 14 | local mem = {basiccases} -- for memoization 15 | 16 | local function allcases (n) 17 | if mem[n] then return mem[n] end 18 | local res = {} 19 | -- include all smaller cases 20 | for _, v in ipairs(allcases(n - 1)) do 21 | res[#res + 1] = v 22 | end 23 | for i = 1, n - 1 do 24 | for _, v1 in ipairs(allcases(i)) do 25 | for _, v2 in ipairs(allcases(n - i)) do 26 | res[#res + 1] = { 27 | "(" .. v1[1] .. " and " .. v2[1] .. ")", 28 | v1[2] and v2[2] 29 | } 30 | res[#res + 1] = { 31 | "(" .. v1[1] .. " or " .. v2[1] .. ")", 32 | v1[2] or v2[2] 33 | } 34 | end 35 | end 36 | end 37 | mem[n] = res -- memoize 38 | return res 39 | end 40 | 41 | for _, v in pairs(allcases(4)) do 42 | local res = (loadstring or load)("return " .. v[1])() 43 | if res ~= v[2] then 44 | error(string.format("bad conditional eval\n%s\nexpected: %s\ngot: %s", 45 | v[1], tostring(v[2]), tostring(res))) 46 | end 47 | end 48 | end 49 | 50 | do --- tracefib 51 | -- 0001 KSHORT 1 2 52 | -- 0002 ISGE 0 1 53 | -- 0003 JMP 1 => 0006 54 | -- 0004 KSHORT 1 1 55 | -- 0005 JMP 1 => 0013 56 | -- ^^^ must be 2 57 | -- fix in jmp_patchtestreg 58 | local function fib(n) return (n < 2) and 1 or fib(n-1)+fib(n-2) end 59 | assert(fib(5) == 8) 60 | assert(fib(10) == 89) 61 | end 62 | -------------------------------------------------------------------------------- /test/lang/assignment.lua: -------------------------------------------------------------------------------- 1 | local assert = assert 2 | 3 | do --- local 4 | local a, b, c 5 | a, b, c = 0, 1 6 | assert(a == 0) 7 | assert(b == 1) 8 | assert(c == nil) 9 | a, b = a+1, b+1, a+b 10 | assert(a == 1) 11 | assert(b == 2) 12 | a, b, c = 0 13 | assert(a == 0) 14 | assert(b == nil) 15 | assert(c == nil) 16 | end 17 | 18 | do --- global !private_G 19 | a, b, c = 0, 1 20 | assert(a == 0) 21 | assert(b == 1) 22 | assert(c == nil) 23 | a, b = a+1, b+1, a+b 24 | assert(a == 1) 25 | assert(b == 2) 26 | a, b, c = 0 27 | assert(a == 0) 28 | assert(b == nil) 29 | assert(c == nil) 30 | end 31 | 32 | do --- local lhs in key on lhs 33 | local a = {} 34 | local i = 3 35 | i, a[i] = i+1, 20 36 | assert(i == 4) 37 | assert(a[3] == 20) 38 | end 39 | 40 | do --- global lhs in key on lhs !private_G 41 | a = {} 42 | i = 3 43 | i, a[i] = i+1, 20 44 | assert(i == 4) 45 | assert(a[3] == 20) 46 | end 47 | -------------------------------------------------------------------------------- /test/lang/compare_nan.lua: -------------------------------------------------------------------------------- 1 | 2 | local function check(a, b) 3 | if a ~= b then 4 | error("check failed with "..tostring(a).." ~= "..tostring(b), 2) 5 | end 6 | end 7 | 8 | local nan, one = 0/0, 1 9 | 10 | do --- nan nan 11 | check(nannan, false) 14 | check(nan>=nan, false) 15 | check(nan==nan, false) 16 | check(nan~=nan, true) 17 | end 18 | 19 | do --- nan one 20 | check(nanone, false) 23 | check(nan>=one, false) 24 | check(nan==one, false) 25 | check(nan~=one, true) 26 | end 27 | 28 | do --- one nan 29 | check(onenan, false) 32 | check(one>=nan, false) 33 | check(one==nan, false) 34 | check(one~=nan, true) 35 | end 36 | 37 | do --- nan 1 38 | check(nan<1, false) 39 | check(nan<=1, false) 40 | check(nan>1, false) 41 | check(nan>=1, false) 42 | check(nan==1, false) 43 | check(nan~=1, true) 44 | end 45 | 46 | do --- 1 nan 47 | check(1nan, false) 50 | check(1>=nan, false) 51 | check(1==nan, false) 52 | check(1~=nan, true) 53 | end 54 | 55 | do --- not nan nan 56 | check(not (nannan), true) 59 | check(not (nan>=nan), true) 60 | check(not (nan==nan), true) 61 | check(not (nan~=nan), false) 62 | end 63 | 64 | do --- not nan one 65 | check(not (nanone), true) 68 | check(not (nan>=one), true) 69 | check(not (nan==one), true) 70 | check(not (nan~=one), false) 71 | end 72 | 73 | do --- not one nan 74 | check(not (onenan), true) 77 | check(not (one>=nan), true) 78 | check(not (one==nan), true) 79 | check(not (one~=nan), false) 80 | end 81 | 82 | do --- not nan 1 83 | check(not (nan<1), true) 84 | check(not (nan<=1), true) 85 | check(not (nan>1), true) 86 | check(not (nan>=1), true) 87 | check(not (nan==1), true) 88 | check(not (nan~=1), false) 89 | end 90 | 91 | do --- not 1 nan 92 | check(not (1nan), true) 95 | check(not (1>=nan), true) 96 | check(not (1==nan), true) 97 | check(not (1~=nan), false) 98 | end 99 | 100 | -------------------------------------------------------------------------------- /test/lang/concat.lua: -------------------------------------------------------------------------------- 1 | do --- Constant folding 2 | local y 3 | for i=1,100 do y = "a".."b" end 4 | assert(y == "ab") 5 | for i=1,100 do y = "ab"..(1).."cd"..(1.5) end 6 | assert(y == "ab1cd1.5") 7 | end 8 | 9 | do --- Fuse conversions to strings 10 | local y 11 | local x = "a" 12 | for i=1,100 do y = x..i end 13 | assert(y == "a100") 14 | x = "a" 15 | for i=1.5,100.5 do y = x..i end 16 | assert(y == "a100.5") 17 | end 18 | 19 | do --- Fuse string construction 20 | local y 21 | local x = "abc" 22 | for i=1,100 do y = "x"..string.sub(x, 2) end 23 | assert(y == "xbc") 24 | end 25 | 26 | do --- CSE, sink 27 | local y 28 | local x = "a" 29 | for i=1,100 do y = x.."b" end 30 | assert(y == "ab") 31 | end 32 | 33 | do --- CSE, two buffers in parallel, no sink 34 | local y, z 35 | local x1, x2 = "xx", "yy" 36 | for i=1,100 do y = x1.."a"..x1; z = x1.."a"..x2 end 37 | assert(y == "xxaxx") 38 | assert(z == "xxayy") 39 | x1 = "xx" 40 | for i=1,100 do y = x1.."a"..x1; z = x1.."b"..x1 end 41 | assert(y == "xxaxx") 42 | assert(z == "xxbxx") 43 | end 44 | 45 | do --- Append, CSE 46 | local y, z 47 | local x = "a" 48 | for i=1,100 do 49 | y = x.."b" 50 | y = y.."c" 51 | end 52 | assert(y == "abc") 53 | x = "a" 54 | for i=1,100 do 55 | y = x.."b" 56 | z = y.."c" 57 | end 58 | assert(y == "ab") 59 | assert(z == "abc") 60 | x = "a" 61 | for i=1,100 do 62 | y = x.."b" 63 | z = y..i 64 | end 65 | assert(y == "ab") 66 | assert(z == "ab100") 67 | end 68 | 69 | do --- Append, FOLD 70 | local a, b = "x" 71 | for i=1,100 do b = (a.."y").."" end 72 | assert(b == "xy") 73 | end 74 | 75 | do --- Append to buffer, sink 76 | local x = "a" 77 | for i=1,100 do x = x.."b" end 78 | assert(x == "a"..string.rep("b", 100)) 79 | x = "a" 80 | for i=1,100 do x = x.."bc" end 81 | assert(x == "a"..string.rep("bc", 100)) 82 | end 83 | 84 | do --- Append to two buffers in parallel, no append, no sink 85 | local y, z = "xx", "yy" 86 | for i=1,100 do y = y.."a"; z = z.."b" end 87 | assert(y == "xx"..string.rep("a", 100)) 88 | assert(z == "yy"..string.rep("b", 100)) 89 | end 90 | 91 | do --- Sink into side-exit 92 | local x = "a" 93 | local z 94 | for i=1,200 do 95 | local y = x.."b" 96 | if i > 100 then 97 | z = y..i 98 | end 99 | end 100 | assert(z == "ab200") 101 | end 102 | 103 | do --- Very long strings 104 | for i, s in ipairs{"a", "bc", "def"} do 105 | for n = 1, 20 do 106 | s = s .. s 107 | end 108 | assert(#s == 2^20*i) 109 | assert(s:sub(1, 6) == s:sub(7, 12)) 110 | assert(s:sub(1, 6) == s:sub(-6, -1)) 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /test/lang/constant/index: -------------------------------------------------------------------------------- 1 | number.lua 2 | table.lua 3 | -------------------------------------------------------------------------------- /test/lang/constant/number.lua: -------------------------------------------------------------------------------- 1 | do --- exp 2 | assert(1e5 == 100000) 3 | assert(1e+5 == 100000) 4 | assert(1e-5 == 0.00001) 5 | end 6 | 7 | do --- hex exp +hexfloat !lex 8 | assert(0xe+9 == 23) 9 | assert(0xep9 == 7168) 10 | assert(0xep+9 == 7168) 11 | assert(0xep-9 == 0.02734375) 12 | end 13 | -------------------------------------------------------------------------------- /test/lang/constant/table.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- tnew 3 | local a = nil 4 | local b = {} 5 | local t = {[true] = a, [false] = b or 1} 6 | assert(t[true] == nil) 7 | assert(t[false] == b) 8 | end 9 | 10 | do --- tdup 11 | local b = {} 12 | local t = {[true] = nil, [false] = b or 1} 13 | assert(t[true] == nil) 14 | assert(t[false] == b) 15 | end 16 | -------------------------------------------------------------------------------- /test/lang/coroutine.lua: -------------------------------------------------------------------------------- 1 | do --- traceback 2 | local co = coroutine.create(function() 3 | local x = nil 4 | local y = x.x 5 | end) 6 | assert(coroutine.resume(co) == false) 7 | debug.traceback(co) 8 | end 9 | -------------------------------------------------------------------------------- /test/lang/for.lua: -------------------------------------------------------------------------------- 1 | do --- direction 2 | local a,b,c = 10,1,-1 3 | for i=1,20 do 4 | if c == -1 then 5 | a,b,c = 1,10,1 6 | else 7 | a,b,c = 10,1,-1 8 | end 9 | local x = 0 10 | for i=a,b,c do for j=1,10 do end x=x+1 end 11 | assert(x == 10) 12 | end 13 | end 14 | 15 | do --- coerce to integer at 13 16 | local n = 1 17 | local x = 0 18 | for i=1,20 do 19 | for j=n,100 do x = x + 1 end 20 | if i == 13 then n = "2" end 21 | end 22 | assert(x == 1993) 23 | end 24 | 25 | do --- coerce to integer at 10 26 | local n = 1 27 | local x = 0 28 | for i=1,20 do 29 | for j=n,100 do x = x + 1 end 30 | if i == 10 then n = "2" end 31 | end 32 | assert(x == 1990) 33 | end 34 | 35 | do --- cannot coerce to integer at 10 36 | local function f() 37 | local n = 1 38 | local x = 0 39 | for i=1,20 do 40 | for j=n,100 do x = x + 1 end 41 | if i == 10 then n = "x" end 42 | end 43 | end 44 | assert(not pcall(f)) 45 | end 46 | -------------------------------------------------------------------------------- /test/lang/gc.lua: -------------------------------------------------------------------------------- 1 | do --- rechain 2 | local k 3 | 4 | collectgarbage() 5 | 6 | local t = {} 7 | t.ac = 1 8 | 9 | t.nn = 1 10 | t.mm = 1 11 | t.nn = nil 12 | t.mm = nil 13 | 14 | k = "a".."i" 15 | t[k] = 2 16 | 17 | t.ad = 3 18 | 19 | t[k] = nil 20 | k = nil 21 | 22 | collectgarbage() 23 | 24 | k = "a".."f" 25 | t[k] = 4 26 | 27 | t.ak = 5 28 | 29 | assert(t[k] == 4) 30 | end 31 | 32 | do --- TSETM gc 33 | local function f() 34 | collectgarbage() 35 | return "a", "b" 36 | end 37 | for i = 1, 10 do 38 | local t = {f()} 39 | assert(t[1] == "a") 40 | assert(t[2] == "b") 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /test/lang/index: -------------------------------------------------------------------------------- 1 | andor.lua 2 | assignment.lua 3 | compare.lua 4 | compare_nan.lua 5 | constant 6 | for.lua 7 | length.lua 8 | modulo.lua 9 | concat.lua 10 | self.lua 11 | table.lua 12 | upvalue 13 | coroutine.lua 14 | tail_recursion.lua 15 | vararg_jit.lua 16 | gc.lua 17 | goto.lua +goto 18 | meta 19 | -------------------------------------------------------------------------------- /test/lang/length.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- length increasing and decreasing in loop 3 | local t = {} 4 | for i=1,100 do t[#t+1] = i end 5 | assert(#t == 100) 6 | for i=1,100 do t[#t] = nil end 7 | assert(#t == 0) 8 | end 9 | 10 | do --- length increasing in loop with existing element 11 | local t = {} 12 | t[90] = 999 13 | for i=1,100 do t[#t+1] = i end 14 | assert(#t > 100 and t[#t] == 100) 15 | end 16 | 17 | do --- length decreasing in loop with erased element 18 | local t = {} 19 | for i=1,100 do t[i] = i end 20 | t[10] = nil 21 | for i=1,99 do t[#t] = nil end 22 | assert(#t == 0) 23 | end 24 | -------------------------------------------------------------------------------- /test/lang/meta/arith.lua: -------------------------------------------------------------------------------- 1 | local function create(arith, v1, v2) 2 | local meta = { 3 | __add=function(a,b) return arith("add", a, b) end, 4 | __sub=function(a,b) return arith("sub", a, b) end, 5 | __mul=function(a,b) return arith("mul", a, b) end, 6 | __div=function(a,b) return arith("div", a, b) end, 7 | __mod=function(a,b) return arith("mod", a, b) end, 8 | __pow=function(a,b) return arith("pow", a, b) end, 9 | __unm=function(a,b) return arith("unm", a, b) end, 10 | } 11 | return setmetatable({v1}, meta), setmetatable({v2}, meta) 12 | end 13 | 14 | do --- op 15 | local a, b = create(function(op,a,b) return op end) 16 | assert(a+b == "add") 17 | assert(a-b == "sub") 18 | assert(a*b == "mul") 19 | assert(a/b == "div") 20 | assert(a%b == "mod") 21 | assert(a^b == "pow") 22 | assert(-a == "unm") 23 | end 24 | 25 | do --- lhs 26 | local a, b = create(function(op,a,b) return a[1] end, "foo", 42) 27 | assert(a+b == "foo") 28 | assert(a-b == "foo") 29 | assert(a*b == "foo") 30 | assert(a/b == "foo") 31 | assert(a%b == "foo") 32 | assert(a^b == "foo") 33 | assert(-a == "foo") 34 | end 35 | 36 | do --- rhs 37 | local a, b = create(function(op,a,b) return b[1] end, 42, "foo") 38 | assert(a+b == "foo") 39 | assert(a-b == "foo") 40 | assert(a*b == "foo") 41 | assert(a/b == "foo") 42 | assert(a%b == "foo") 43 | assert(a^b == "foo") 44 | assert(-a == 42) 45 | end 46 | 47 | do --- meta only lhs 48 | local a, b = create(function(op,a,b) return a[1]+b end, 39), 3 49 | assert(a+b == 42) 50 | assert(a-b == 42) 51 | assert(a*b == 42) 52 | assert(a/b == 42) 53 | assert(a%b == 42) 54 | assert(a^b == 42) 55 | end 56 | 57 | do --- meta only rhs 58 | local a, b = 39, create(function(op,a,b) return a+b[1] end, 3) 59 | assert(a+b == 42) 60 | assert(a-b == 42) 61 | assert(a*b == 42) 62 | assert(a/b == 42) 63 | assert(a%b == 42) 64 | assert(a^b == 42) 65 | end 66 | 67 | do --- defaults string, int 68 | local a, b = "39", 3 69 | assert(a+b == 42) 70 | assert(a-b == 36) 71 | assert(a*b == 117) 72 | assert(a/b == 13) 73 | assert(a%b == 0) 74 | assert(a^b == 59319) 75 | assert(-a == -39) 76 | end 77 | 78 | do --- defaults int, string 79 | local a, b = 39, "3" 80 | assert(a+b == 42) 81 | assert(a-b == 36) 82 | assert(a*b == 117) 83 | assert(a/b == 13) 84 | assert(a%b == 0) 85 | assert(a^b == 59319) 86 | assert(-a == -39) 87 | end 88 | 89 | do --- defaults string, string 90 | local a, b = "39", "3" 91 | assert(a+b == 42) 92 | assert(a-b == 36) 93 | assert(a*b == 117) 94 | assert(a/b == 13) 95 | assert(a%b == 0) 96 | assert(a^b == 59319) 97 | assert(-a == -39) 98 | end 99 | 100 | do --- defaults string, kint 101 | local a = "39" 102 | assert(a+3 == 42) 103 | assert(a-3 == 36) 104 | assert(a*3 == 117) 105 | assert(a/3 == 13) 106 | assert(a%3 == 0) 107 | assert(a^3 == 59319) 108 | end 109 | 110 | do --- defaults kint, string 111 | local b = "3" 112 | assert(39+b == 42) 113 | assert(39-b == 36) 114 | assert(39*b == 117) 115 | assert(39/b == 13) 116 | assert(39%b == 0) 117 | assert(39^b == 59319) 118 | end 119 | -------------------------------------------------------------------------------- /test/lang/meta/arith_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- assert rhs 3 | local t = {} 4 | local mt = { 5 | __add = function(a, b) assert(b == t); return a+11 end, 6 | __sub = function(a, b) assert(b == t); return a+12 end, 7 | __mul = function(a, b) assert(b == t); return a+13 end, 8 | __div = function(a, b) assert(b == t); return a+14 end, 9 | __mod = function(a, b) assert(b == t); return a+15 end, 10 | __pow = function(a, b) assert(b == t); return a+16 end, 11 | __unm = function(a, b) assert(a == t and b == t); return 17 end, 12 | } 13 | t = setmetatable(t, mt) 14 | do local x = 0; for i=1,100 do x = x + t end; assert(x == 1100); end 15 | do local x = 0; for i=1,100 do x = x - t end; assert(x == 1200); end 16 | do local x = 0; for i=1,100 do x = x * t end; assert(x == 1300); end 17 | do local x = 0; for i=1,100 do x = x / t end; assert(x == 1400); end 18 | do local x = 0; for i=1,100 do x = x % t end; assert(x == 1500); end 19 | do local x = 0; for i=1,100 do x = x ^ t end; assert(x == 1600); end 20 | do local x = 0; for i=1,100 do x = x + (-t) end; assert(x == 1700); end 21 | end 22 | 23 | do --- assert lhs 24 | local t = {} 25 | local mt = { 26 | __add = function(a, b) assert(a == t); return b+11 end, 27 | __sub = function(a, b) assert(a == t); return b+12 end, 28 | __mul = function(a, b) assert(a == t); return b+13 end, 29 | __div = function(a, b) assert(a == t); return b+14 end, 30 | __mod = function(a, b) assert(a == t); return b+15 end, 31 | __pow = function(a, b) assert(a == t); return b+16 end, 32 | } 33 | t = setmetatable(t, mt) 34 | do local x = 0; for i=1,100 do x = t + x end; assert(x == 1100); end 35 | do local x = 0; for i=1,100 do x = t - x end; assert(x == 1200); end 36 | do local x = 0; for i=1,100 do x = t * x end; assert(x == 1300); end 37 | do local x = 0; for i=1,100 do x = t / x end; assert(x == 1400); end 38 | do local x = 0; for i=1,100 do x = t % x end; assert(x == 1500); end 39 | do local x = 0; for i=1,100 do x = t ^ x end; assert(x == 1600); end 40 | end 41 | 42 | do --- assert both sides 43 | local t = {} 44 | local mt = { 45 | __add = function(a, b) assert(a == t and b == t); return 11 end, 46 | __sub = function(a, b) assert(a == t and b == t); return 12 end, 47 | __mul = function(a, b) assert(a == t and b == t); return 13 end, 48 | __div = function(a, b) assert(a == t and b == t); return 14 end, 49 | __mod = function(a, b) assert(a == t and b == t); return 15 end, 50 | __pow = function(a, b) assert(a == t and b == t); return 16 end, 51 | } 52 | t = setmetatable(t, mt) 53 | do local x = 0; for i=1,100 do x = t + t end; assert(x == 11); end 54 | do local x = 0; for i=1,100 do x = t - t end; assert(x == 12); end 55 | do local x = 0; for i=1,100 do x = t * t end; assert(x == 13); end 56 | do local x = 0; for i=1,100 do x = t / t end; assert(x == 14); end 57 | do local x = 0; for i=1,100 do x = t % t end; assert(x == 15); end 58 | do local x = 0; for i=1,100 do x = t ^ t end; assert(x == 16); end 59 | end 60 | 61 | do --- adjust no result to one result 62 | local t = {} 63 | local mt = { __add = function(a, b) end } 64 | t = setmetatable(t, mt) 65 | local x 66 | for i=1,100 do x = t+t end 67 | assert(x == nil) 68 | end 69 | -------------------------------------------------------------------------------- /test/lang/meta/call.lua: -------------------------------------------------------------------------------- 1 | 2 | local function callmeta(o, a, b) 3 | return o, a, b 4 | end 5 | 6 | local meta = { __call = callmeta } 7 | 8 | do --- table 9 | local t = setmetatable({}, meta) 10 | local o,a,b = t() 11 | assert(o == t and a == nil and b == nil) 12 | local o,a,b = t("foo") 13 | assert(o == t and a == "foo" and b == nil) 14 | local o,a,b = t("foo", "bar") 15 | assert(o == t and a == "foo" and b == "bar") 16 | end 17 | 18 | do --- userdata +lua<5.2 19 | local u = newproxy(true) 20 | getmetatable(u).__call = callmeta 21 | 22 | local o,a,b = u() 23 | assert(o == u and a == nil and b == nil) 24 | local o,a,b = u("foo") 25 | assert(o == u and a == "foo" and b == nil) 26 | local o,a,b = u("foo", "bar") 27 | assert(o == u and a == "foo" and b == "bar") 28 | end 29 | 30 | do --- number 31 | debug.setmetatable(0, meta) 32 | local o,a,b = (42)() 33 | assert(o == 42 and a == nil and b == nil) 34 | local o,a,b = (42)("foo") 35 | assert(o == 42 and a == "foo" and b == nil) 36 | local o,a,b = (42)("foo", "bar") 37 | assert(o == 42 and a == "foo" and b == "bar") 38 | debug.setmetatable(0, nil) 39 | end 40 | 41 | do --- table with changing metamethod 42 | local tc = setmetatable({}, { __call = function(o,a,b) return o end}) 43 | local ta = setmetatable({}, { __add = tc}) 44 | local o,a = ta + ta 45 | assert(o == tc and a == nil) 46 | 47 | getmetatable(tc).__call = function(o,a,b) return a end 48 | local o,a = ta + ta 49 | assert(o == ta and a == nil) 50 | end 51 | 52 | do --- jit table 53 | local t = setmetatable({}, { __call = function(t, a) return 100-a end }) 54 | for i=1,100 do assert(t(i) == 100-i) end 55 | end 56 | 57 | do --- jit table rawget as metamethod 58 | local t = setmetatable({}, { __call = rawget }) 59 | for i=1,100 do t[i] = 100-i end 60 | for i=1,100 do assert(t(i) == 100-i) end 61 | end 62 | 63 | do --- jit number 64 | debug.setmetatable(0, { __call = function(n) return 100-n end }) 65 | for i=1,100 do assert((i)() == 100-i) end 66 | debug.setmetatable(0, nil) 67 | end 68 | 69 | do --- jit newindex pcall 70 | local t = setmetatable({}, { __newindex = pcall, __call = rawset }) 71 | for i=1,100 do t[i] = 100-i end 72 | for i=1,100 do assert(t[i] == 100-i) end 73 | end 74 | 75 | do --- jit index pcall 76 | local t = setmetatable({}, { 77 | __index = pcall, __newindex = rawset, 78 | __call = function(t, i) t[i] = 100-i end, 79 | }) 80 | for i=1,100 do assert(t[i] == true and rawget(t, i) == 100-i) end 81 | end 82 | -------------------------------------------------------------------------------- /test/lang/meta/cat.lua: -------------------------------------------------------------------------------- 1 | local function create(cat, v1, v2) 2 | local meta = { __concat = cat } 3 | return setmetatable({v1}, meta), setmetatable({v2}, meta) 4 | end 5 | 6 | do --- default 7 | local a, b, c = "foo", "bar", "baz" 8 | assert(a..b == "foobar") 9 | assert(a..b..c == "foobarbaz") 10 | end 11 | 12 | do --- lhs 13 | local a, b = create(function(a, b) return a end) 14 | assert(a..b == a) 15 | assert(b..a == b) 16 | assert(a..b..b == a) 17 | assert(a..a..b == a) 18 | assert(a..b..a == a) 19 | assert(a..b..b..b..b..b..b..b == a) 20 | end 21 | 22 | do --- rhs 23 | local a, b = create(function(a, b) return b end) 24 | assert(a..b == b) 25 | assert(b..a == a) 26 | assert(a..b..b == b) 27 | assert(a..a..b == b) 28 | assert(b..b..a == a) 29 | assert(a..a..a..a..a..a..a..b == b) 30 | end 31 | 32 | do --- mixed types 33 | local a, b = create(function(a, b) 34 | return (type(a) == "string" and a or a[1]).. 35 | (type(b) == "string" and b or b[1]) 36 | end, "a", "b") 37 | assert(a..b == "ab") 38 | assert(a..b == "ab") 39 | assert(a..b..b == "abb") 40 | assert(a..b..a == "aba") 41 | assert(a..a..a..a..a..a..a..b == "aaaaaaab") 42 | assert(a..a..a.."x".."x"..a..a..b == "aaaxxaab") 43 | assert("x"..a..a..a..a..a..a..b == "xaaaaaab") 44 | assert(a..b..a..b..a.."x".."x".."x" == "ababaxxx") 45 | end 46 | 47 | do --- jit mixed types 48 | local a, b = create(function(a, b) 49 | if a ~= b then local x = gg end 50 | return (type(a) == "string" and a or a[1]).. 51 | (type(b) == "string" and b or b[1]) 52 | end, "a", "b") 53 | local y 54 | for i=1,100 do y = a..b end 55 | assert(y == "ab") 56 | for i=1,100 do y = a..b.."x" end 57 | assert(y == "abx") 58 | for i=1,100 do y = a..b.. 1 .. "z" end 59 | assert(y == "ab1z") 60 | end 61 | 62 | -------------------------------------------------------------------------------- /test/lang/meta/debuginfo.lua: -------------------------------------------------------------------------------- 1 | 2 | local what 3 | 4 | local function mm(a, b) 5 | local dbg = debug.getinfo(1) 6 | what = dbg.namewhat == "metamethod" and dbg.name or 7 | dbg.namewhat.." "..(dbg.name or "?") 8 | end 9 | 10 | local function ck(s) 11 | assert(what == s, "bad debug info for metamethod "..s) 12 | end 13 | 14 | local mt = { 15 | __index = mm, 16 | __newindex = mm, 17 | __eq = mm, 18 | __add = mm, 19 | __sub = mm, 20 | __mul = mm, 21 | __div = mm, 22 | __mod = mm, 23 | __pow = mm, 24 | __unm = mm, 25 | __len = mm, 26 | __lt = mm, 27 | __le = mm, 28 | __concat = mm, 29 | __call = mm, 30 | } 31 | 32 | do --- table metamethods +goto 33 | local t = setmetatable({}, mt) 34 | local t2 = setmetatable({}, mt) 35 | 36 | local x = t.x; ck("__index") 37 | t.x = 1; ck("__newindex") 38 | local x = t + t; ck("__add") 39 | local x = t - t; ck("__sub") 40 | local x = t * t; ck("__mul") 41 | local x = t / t; ck("__div") 42 | local x = t % t; ck("__mod") 43 | local x = t ^ t; ck("__pow") 44 | local x = -t; ck("__unm") 45 | local x = t..t; ck("__concat") 46 | local x = t(); ck("local t") 47 | 48 | local x = t == t2; ck("__eq") 49 | local x = t ~= t2; ck("__eq") 50 | local x = t < t2; ck("__lt") 51 | local x = t > t2; ck("__lt") 52 | local x = t <= t2; ck("__le") 53 | local x = t >= t2; ck("__le") 54 | end 55 | 56 | do --- userdata metamethods +luajit 57 | local u = newproxy() 58 | local u2 = newproxy() 59 | debug.setmetatable(u, mt) 60 | debug.setmetatable(u2, mt) 61 | 62 | local x = u.x; ck("__index") 63 | u.x = 1; ck("__newindex") 64 | local x = u + u; ck("__add") 65 | local x = u - u; ck("__sub") 66 | local x = u * u; ck("__mul") 67 | local x = u / u; ck("__div") 68 | local x = u % u; ck("__mod") 69 | local x = u ^ u; ck("__pow") 70 | local x = -u; ck("__unm") 71 | local x = #u; ck("__len") 72 | local x = u..u; ck("__concat") 73 | local x = u(); ck("local u") 74 | 75 | local x = u == u2; ck("__eq") 76 | local x = u ~= u2; ck("__eq") 77 | local x = u < u2; ck("__lt") 78 | local x = u > u2; ck("__lt") 79 | local x = u <= u2; ck("__le") 80 | local x = u >= u2; ck("__le") 81 | end 82 | -------------------------------------------------------------------------------- /test/lang/meta/eq.lua: -------------------------------------------------------------------------------- 1 | local function create(equal, v1, v2) 2 | local meta = { __eq = equal } 3 | return setmetatable({v1}, meta), setmetatable({v2}, meta) 4 | end 5 | 6 | do --- __eq xop 7 | local xop 8 | local a, b = create(function(a,b) xop = "eq" return "" end) 9 | assert(a==b == true and xop == "eq"); xop = nil 10 | assert(a~=b == false and xop == "eq"); xop = nil 11 | 12 | -- Different metatable, but same metamethod works, too. 13 | setmetatable(b, { __eq = getmetatable(b).__eq }) 14 | assert(a==b == true and xop == "eq"); xop = nil 15 | assert(a~=b == false and xop == "eq"); xop = nil 16 | end 17 | 18 | do --- __eq values 19 | local a, b = create(function(a,b) return a[1] == b[1] end, 1, 2) 20 | assert(a==b == false) 21 | assert(a~=b == true) 22 | 23 | b[1] = 1 24 | assert(a==b == true) 25 | assert(a~=b == false) 26 | 27 | a[1] = 2 28 | assert(a==b == false) 29 | assert(a~=b == true) 30 | end 31 | -------------------------------------------------------------------------------- /test/lang/meta/eq_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- coverage 3 | local eq = false 4 | local t, u = {}, {} 5 | local x, ax, bx 6 | local function ck(xx, a, b) 7 | if x ~= xx then error("bad x", 2) end 8 | if ax ~= a then error("bad ax", 2) end 9 | if bx ~= b then error("bad bx", 2) end 10 | end 11 | local mt = { 12 | __eq = function(a, b) ax=a; bx=b; return eq end, 13 | } 14 | t = setmetatable(t, mt) 15 | u = setmetatable(u, mt) 16 | eq = false 17 | x = 0; for i=1,100 do x = t == u and 2 or 1 end ck(1, t, u) 18 | x = 0; for i=1,100 do x = t ~= u and 2 or 1 end ck(2, t, u) 19 | x = 0; for i=1,100 do x = not (t == u) and 2 or 1 end ck(2, t, u) 20 | x = 0; for i=1,100 do x = not (t ~= u) and 2 or 1 end ck(1, t, u) 21 | eq = true 22 | x = 0; for i=1,100 do x = t == u and 2 or 1 end ck(2, t, u) 23 | x = 0; for i=1,100 do x = t ~= u and 2 or 1 end ck(1, t, u) 24 | x = 0; for i=1,100 do x = not (t == u) and 2 or 1 end ck(1, t, u) 25 | x = 0; for i=1,100 do x = not (t ~= u) and 2 or 1 end ck(2, t, u) 26 | end 27 | 28 | do --- non-constant objects +bit 29 | local bit = require("bit") 30 | local mt = { __eq = function(a, b) return true end } 31 | local tt = { [0] = setmetatable({}, mt), setmetatable({}, mt) } 32 | for i=0,100 do 33 | assert(tt[0] == tt[bit.band(i, 1)]) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/lang/meta/framegap.lua: -------------------------------------------------------------------------------- 1 | do --- untitled 2 | local t = setmetatable({}, { __add = function(a, b) 3 | if b > 200 then 4 | for j=1,10 do end 5 | return b+3 6 | elseif b > 100 then 7 | return b+2 8 | else 9 | return b+1 10 | end 11 | end }) 12 | 13 | local function f(t, i) 14 | do return t+i end 15 | -- Force large frame with unassigned slots below mm. 16 | do local a,b,c,d,e,f,g,h,i,j,k end 17 | end 18 | 19 | local x = 0 20 | for i=1,300 do 21 | x = f(t, i) 22 | end 23 | assert(x == 303) 24 | end 25 | -------------------------------------------------------------------------------- /test/lang/meta/index: -------------------------------------------------------------------------------- 1 | arith.lua 2 | arith_jit.lua 3 | call.lua 4 | cat.lua 5 | comp.lua 6 | comp_jit.lua 7 | eq.lua 8 | eq_jit.lua 9 | framegap.lua 10 | index.lua 11 | len.lua 12 | newindex.lua 13 | nomm.lua 14 | debuginfo.lua 15 | -------------------------------------------------------------------------------- /test/lang/meta/index.lua: -------------------------------------------------------------------------------- 1 | do --- table 1 2 | local t=setmetatable({}, {__index=function(t,k) 3 | return 100-k 4 | end}) 5 | 6 | for i=1,100 do assert(t[i] == 100-i) end 7 | 8 | for i=1,100 do t[i] = i end 9 | for i=1,100 do assert(t[i] == i) end 10 | 11 | for i=1,100 do t[i] = nil end 12 | for i=1,100 do assert(t[i] == 100-i) end 13 | end 14 | 15 | do --- table 2 16 | local x 17 | local t2=setmetatable({}, {__index=function(t,k) 18 | x = k 19 | end}) 20 | 21 | assert(t2[1] == nil) 22 | assert(x == 1) 23 | 24 | assert(t2.foo == nil) 25 | assert(x == "foo") 26 | end 27 | 28 | do --- userdata +lua<5.2 29 | local u = newproxy(true) 30 | getmetatable(u).__index = { foo = u, bar = 42 } 31 | 32 | local x = 0 33 | for i=1,100 do 34 | x = x + u.bar 35 | u = u.foo 36 | end 37 | assert(x == 4200) 38 | 39 | x = 0 40 | for i=1,100 do 41 | u = u.foo 42 | x = x + u.bar 43 | end 44 | assert(x == 4200) 45 | end 46 | 47 | do --- string 48 | local s = "foo" 49 | local mt = debug.getmetatable(s) 50 | debug.setmetatable(s, {__index = {s = s, len = string.len}}) 51 | local x = 0 52 | local t = {} 53 | for i=1,100 do 54 | x = x + s:len() 55 | s = s.s 56 | t[s] = t -- Hash store with same type prevents hoisting 57 | end 58 | debug.setmetatable(s, mt) 59 | assert(x == 300) 60 | end 61 | -------------------------------------------------------------------------------- /test/lang/meta/len.lua: -------------------------------------------------------------------------------- 1 | local compat52 = table.pack 2 | local mt = { __len = function(o, o2) 3 | if compat52 then 4 | assert(o2 == o) 5 | else 6 | assert(o2 == nil) 7 | end 8 | return 42 9 | end } 10 | 11 | do --- table 12 | local t = {1,2,3} 13 | assert(#t == 3) 14 | assert(#"abcdef" == 6) 15 | 16 | setmetatable(t, { __foo = function() end }) 17 | assert(#t == 3) 18 | assert(#t == 3) 19 | 20 | setmetatable(t, mt) 21 | if compat52 then 22 | assert(#t == 42) -- __len DOES work on tables. 23 | assert(rawlen(t) == 3) 24 | else 25 | assert(#t == 3) -- __len does NOT work on tables. 26 | end 27 | end 28 | 29 | do --- userdata +lua<5.2 30 | local u = newproxy(true) 31 | getmetatable(u).__len = function(o) return 42 end 32 | assert(#u == 42) 33 | local x = 0 34 | for i=1,100 do x = x + #u end 35 | assert(x == 4200) 36 | end 37 | 38 | do --- number 39 | debug.setmetatable(0, mt) 40 | assert(#1 == 42) 41 | debug.setmetatable(0, nil) 42 | end 43 | -------------------------------------------------------------------------------- /test/lang/meta/newindex.lua: -------------------------------------------------------------------------------- 1 | do --- table 1 2 | local t=setmetatable({}, {__newindex=function(t,k,v) 3 | rawset(t, k, 100-v) 4 | end}) 5 | 6 | for i=1,100 do t[i] = i end 7 | for i=1,100 do assert(t[i] == 100-i) end 8 | 9 | for i=1,100 do t[i] = i end 10 | for i=1,100 do assert(t[i] == i) end 11 | 12 | for i=1,100 do t[i] = nil end 13 | for i=1,100 do t[i] = i end 14 | for i=1,100 do assert(t[i] == 100-i) end 15 | end 16 | 17 | do --- jit gaining href 18 | local count = 0 19 | local t = setmetatable({ foo = nil }, 20 | { __newindex=function() count = count + 1 end }) 21 | for j=1,2 do 22 | for i=1,100 do t.foo = 1 end 23 | rawset(t, "foo", 1) 24 | end 25 | assert(count == 100) 26 | end 27 | 28 | do --- jit gaining aref 29 | local count = 0 30 | local t = setmetatable({ nil }, 31 | { __newindex=function() count = count + 1 end }) 32 | for j=1,2 do 33 | for i=1,100 do t[1] = 1 end 34 | rawset(t, 1, 1) 35 | end 36 | assert(count == 100) 37 | end 38 | 39 | do --- resize 40 | local grandparent = {} 41 | grandparent.__newindex = function(s,_,_) tostring(s) end 42 | 43 | local parent = {} 44 | parent.__newindex = parent 45 | parent.bar = 1 46 | setmetatable(parent, grandparent) 47 | 48 | local child = setmetatable({}, parent) 49 | child.foo = _ 50 | end 51 | 52 | do --- str 53 | local t=setmetatable({}, {__newindex=function(t,k,v) 54 | assert(v == "foo"..k) 55 | rawset(t, k, "bar"..k) 56 | end}) 57 | 58 | for i=1,100 do t[i]="foo"..i end 59 | for i=1,100 do assert(t[i] == "bar"..i) end 60 | 61 | for i=1,100 do t[i]="baz"..i end 62 | for i=1,100 do assert(t[i] == "baz"..i) end 63 | 64 | local t=setmetatable({foo=1,bar=1,baz=1},{}) 65 | t.baz=nil 66 | t.baz=2 67 | t.baz=nil 68 | t.baz=2 69 | end 70 | -------------------------------------------------------------------------------- /test/lang/meta/nomm.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- untitled 3 | local keys = {} 4 | for i=1,100 do keys[i] = "foo" end 5 | keys[95] = "__index" 6 | local function fidx(t, k) return 12345 end 7 | local mt = { foo = 1, __index = "" } 8 | local t = setmetatable({ 1 }, mt) 9 | t[1] = nil 10 | mt.__index = nil 11 | local x = nil 12 | for i=1,100 do 13 | mt[keys[i]] = fidx 14 | if t[1] then 15 | if not x then x = i end 16 | assert(t[1] == 12345) 17 | end 18 | end 19 | assert(x == 95) 20 | end 21 | 22 | -------------------------------------------------------------------------------- /test/lang/modulo.lua: -------------------------------------------------------------------------------- 1 | local assert, floor = assert, math.floor 2 | 3 | do --- integer equivalence 4 | for x=-5,5 do 5 | for y=-5,5 do 6 | if y ~= 0 then 7 | assert(x%y == x-floor(x/y)*y) 8 | end 9 | end 10 | end 11 | end 12 | 13 | do --- fractional equivalence 14 | for x=-5,5,0.25 do 15 | for y=-5,5,0.25 do 16 | if y ~= 0 then 17 | assert(x%y == x-floor(x/y)*y) 18 | end 19 | end 20 | end 21 | end 22 | 23 | do --- jit constant RHS 24 | local y = 0 25 | for x=-100,123 do 26 | y = y + x%17 27 | end 28 | assert(y == 1777) 29 | end 30 | 31 | do --- jit constant LHS, with exit 32 | local y = 0 33 | for x=-100,123 do 34 | if x ~= 0 then 35 | y = y + 85%x 36 | end 37 | end 38 | assert(y == 2059) 39 | end 40 | 41 | do --- divide by zero 42 | local x = 1%0 43 | assert(x ~= x) 44 | x = floor(0/0) 45 | assert(x ~= x) 46 | end 47 | -------------------------------------------------------------------------------- /test/lang/self.lua: -------------------------------------------------------------------------------- 1 | do --- trivial setget 2 | local t = {} 3 | 4 | function t:set(x) 5 | self.a=x 6 | end 7 | 8 | function t:get() 9 | return self.a 10 | end 11 | 12 | t:set("foo") 13 | assert(t:get() == "foo") 14 | assert(t.a == "foo") 15 | 16 | t:set(42) 17 | assert(t:get() == 42) 18 | assert(t.a == 42) 19 | end 20 | -------------------------------------------------------------------------------- /test/lang/table.lua: -------------------------------------------------------------------------------- 1 | do --- tables as keys in tables 2 | local fwd, bck = {}, {} 3 | for i = 1,100 do 4 | local v = {} 5 | fwd[i] = v 6 | bck[v] = i 7 | end 8 | for i = 1,100 do 9 | local v = fwd[i] 10 | assert(type(v) == "table") 11 | assert(bck[v] == i) 12 | end 13 | end 14 | 15 | do --- some tables as keys in tables 16 | local fwd, bck = {}, {} 17 | for i = 1,100 do 18 | local v = {} 19 | fwd[i] = v 20 | if i > 90 then 21 | bck[v] = i 22 | end 23 | end 24 | local n = 0 25 | for i = 1, 100 do 26 | local v = fwd[i] 27 | if bck[v] then 28 | n = n + 1 29 | end 30 | end 31 | assert(n == 10) 32 | end 33 | -------------------------------------------------------------------------------- /test/lang/tail_recursion.lua: -------------------------------------------------------------------------------- 1 | do --- self 2 | local tr1 3 | function tr1(n) 4 | if n <= 0 then return 0 end 5 | return tr1(n-1) 6 | end 7 | assert(tr1(200) == 0) 8 | end 9 | 10 | do --- mutual 11 | local tr1, tr2 12 | function tr1(n) 13 | if n <= 0 then return 0 end 14 | return tr2(n-1) 15 | end 16 | function tr2(n) 17 | return tr1(n) 18 | end 19 | assert(tr2(200) == 0) 20 | end 21 | -------------------------------------------------------------------------------- /test/lang/upvalue/closure.lua: -------------------------------------------------------------------------------- 1 | do --- for 2 | local z1, z2 3 | for i=1,10 do 4 | local function f() return i end 5 | if z1 then z2 = f else z1 = f end 6 | end 7 | assert(z1() == 1) 8 | assert(z2() == 10) 9 | end 10 | 11 | do --- while 12 | local z1, z2 13 | local i = 1 14 | while i <= 10 do 15 | local j = i 16 | local function f() return j end 17 | if z1 then z2 = f else z1 = f end 18 | i = i + 1 19 | end 20 | assert(z1() == 1) 21 | assert(z2() == 10) 22 | end 23 | 24 | do --- repeat 25 | local z1, z2 26 | local i = 1 27 | repeat 28 | local j = i 29 | local function f() return j end 30 | if z1 then z2 = f else z1 = f end 31 | i = i + 1 32 | until i > 10 33 | assert(z1() == 1) 34 | assert(z2() == 10) 35 | end 36 | 37 | do --- func 38 | local function ff(x) 39 | return function() return x end 40 | end 41 | local z1, z2 42 | for i=1,10 do 43 | local f = ff(i) 44 | if z1 then z2 = f else z1 = f end 45 | end 46 | assert(z1() == 1) 47 | assert(z2() == 10) 48 | end 49 | 50 | do --- recursive type change 51 | local function f1(a) 52 | if a > 0 then 53 | local b = f1(a - 1) 54 | return function() 55 | if type(b) == "function" then 56 | return a + b() 57 | end 58 | return a + b 59 | end 60 | end 61 | return a 62 | end 63 | 64 | local function f2(a) 65 | return f1(a)() 66 | end 67 | 68 | for i = 1, 41 do 69 | local r = f2(4) + f2(4) 70 | assert(r == 20) 71 | end 72 | end 73 | 74 | do --- Don't mark upvalue as immutable if written to after prototype definition 75 | local x = 1 76 | local function f() 77 | local y = 0 78 | for i=1,100 do y=y+x end 79 | return y 80 | end 81 | assert(f() == 100) 82 | x = 2 83 | assert(f() == 200) 84 | end 85 | -------------------------------------------------------------------------------- /test/lang/upvalue/index: -------------------------------------------------------------------------------- 1 | closure.lua 2 | -------------------------------------------------------------------------------- /test/lang/vararg_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- 1 3 | local function f(a, b, c, ...) 4 | assert(c == nil) 5 | assert(a == 100-b) 6 | return 100-a, 100-b 7 | end 8 | for i=1,100 do 9 | local x, y = f(i, 100-i) 10 | assert(x == 100-i) 11 | assert(y == i) 12 | end 13 | end 14 | 15 | do --- 2 16 | local function f(a, b, ...) 17 | if a > b then return b end 18 | return a 19 | end 20 | local x = 0 21 | for i=1,200 do 22 | x = x + f(i, 100, 99, 88, 77) 23 | end 24 | assert(x == 15050) 25 | end 26 | 27 | do --- 3 28 | local function f(a, b, ...) 29 | local c, d = ... 30 | if c > d then return d end 31 | return c 32 | end 33 | local x = 0 34 | for i=1,200 do 35 | x = x + f(77, 88, i, 100) 36 | end 37 | assert(x == 15050) 38 | end 39 | 40 | do --- 4 41 | local function f(a, b, ...) 42 | if a > b then end 43 | return ... 44 | end 45 | local x = 0 46 | for i=1,200 do 47 | x = x + f(i, 100, i, 100) 48 | assert(f(i, 100) == nil) 49 | assert(f(i, 100, 2) == 2) 50 | end 51 | assert(x == 20100) 52 | end 53 | 54 | do --- 5 55 | local function f(a, ...) 56 | local x, y = 0, 0 57 | for i=1,100 do 58 | local b, c = ... 59 | x = x + b 60 | y = y + c 61 | end 62 | assert(x == 200 and y == 300) 63 | end 64 | f(1, 2, 3) 65 | end 66 | 67 | do --- 6 68 | local function f(a, ...) 69 | local t = {[0]=9, 9} 70 | local v, w, x, y = 0, 0, 0, 0 71 | for i=1,100 do 72 | v, w = ... 73 | t[0] = 9; t[1] = 9; 74 | x, y = ... 75 | end 76 | assert(v == 2 and w == 3 and x == 2 and y == 3) 77 | end 78 | f(1, 2, 3) 79 | end 80 | 81 | do --- 7 82 | local function f(a, b, ...) 83 | for i=1,100 do 84 | local c, d = ... 85 | assert(a == c); 86 | assert(b == d); 87 | end 88 | end 89 | f(2, 3, 2, 3) 90 | f(2, nil, 2) 91 | f(nil, nil) 92 | f(nil) 93 | f() 94 | end 95 | 96 | -------------------------------------------------------------------------------- /test/lib/base/assert.lua: -------------------------------------------------------------------------------- 1 | do --- pass through one 2 | assert(assert(true) == true) 3 | assert(assert(3) == 3) 4 | assert(assert(1.5) == 1.5) 5 | assert(assert("x") == "x") 6 | local f = function() end 7 | assert(assert(f) == f) 8 | local t = {} 9 | assert(assert(t) == t) 10 | end 11 | 12 | do --- pass through many 13 | local b, c = assert("b", "c") 14 | assert(b == "b") 15 | assert(c == "c") 16 | local d, e, f, g = assert("d", 5, true, false) 17 | assert(d == "d") 18 | assert(e == 5) 19 | assert(f == true) 20 | assert(g == false) 21 | end 22 | 23 | do --- raise on nil 24 | local ok, err = pcall(assert, nil) 25 | assert(ok == false) 26 | assert(err == "assertion failed!") 27 | end 28 | 29 | do --- raise on false 30 | local ok, err = pcall(assert, false, "msg") 31 | assert(ok == false) 32 | assert(err == "msg") 33 | end 34 | -------------------------------------------------------------------------------- /test/lib/base/error.lua: -------------------------------------------------------------------------------- 1 | do --- no message 2 | local ok, msg = pcall(error) 3 | assert(ok == false) 4 | assert(msg == nil) 5 | end 6 | 7 | do --- level 0 8 | local ok, msg = pcall(error, "emsg", 0) 9 | assert(ok == false) 10 | assert(msg == "emsg") 11 | end 12 | 13 | do --- default level 14 | local ok, msg = pcall(error, "emsg") 15 | assert(ok == false) 16 | assert(msg == "emsg") 17 | end 18 | 19 | do --- default level in xpcall 20 | local line 21 | local ok, msg = xpcall(function() 22 | local x 23 | line = debug.getinfo(1, "l").currentline; error("emsg") 24 | end, function(m) 25 | assert(debug.getlocal(3, 1) == "x") 26 | return m .."xp" 27 | end) 28 | assert(ok == false) 29 | assert(msg:find("^.-:".. line ..": emsgxp$")) 30 | end 31 | 32 | do --- level 2 in xpcall 33 | local line 34 | local ok, msg = xpcall(function() 35 | local function f() error("emsg", 2) end 36 | line = debug.getinfo(1, "l").currentline; f() 37 | end, function(m) 38 | assert(debug.getlocal(4, 1) == "f") 39 | return m .."xp2" 40 | end) 41 | assert(ok == false) 42 | assert(msg:find("^.-:".. line ..": emsgxp2$")) 43 | end 44 | -------------------------------------------------------------------------------- /test/lib/base/getfenv.lua: -------------------------------------------------------------------------------- 1 | do --- untitled 2 | local x 3 | local function f() 4 | x = getfenv(0) 5 | end 6 | local co = coroutine.create(f) 7 | local t = {} 8 | debug.setfenv(co, t) 9 | for i=1,50 do f() f() f() end 10 | assert(x == getfenv(0)) 11 | coroutine.resume(co) 12 | assert(x == t) 13 | end 14 | -------------------------------------------------------------------------------- /test/lib/base/getsetmetatable.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- get __metatable 3 | local t = setmetatable({}, { __metatable = "foo" }) 4 | for i=1,100 do assert(getmetatable(t) == "foo") end 5 | end 6 | 7 | do --- jit smoke 8 | local mt = {} 9 | local t = setmetatable({}, mt) 10 | for i=1,100 do assert(getmetatable(t) == mt) end 11 | for i=1,100 do assert(setmetatable(t, mt) == t) end 12 | end 13 | 14 | do --- jit assorted 15 | local mt = {} 16 | local t = {} 17 | for i=1,200 do t[i] = setmetatable({}, mt) end 18 | t[150] = setmetatable({}, { __metatable = "foo" }) 19 | for i=1,200 do 20 | if not pcall(setmetatable, t[i], mt) then assert(i == 150) end 21 | end 22 | for i=1,200 do assert(getmetatable(t[i]) == mt or i == 150) end 23 | for i=1,200 do 24 | if not pcall(setmetatable, t[i], nil) then assert(i == 150) end 25 | end 26 | for i=1,200 do assert(getmetatable(t[i]) == nil or i == 150) end 27 | end 28 | 29 | do --- jit get primitive metatable 30 | local x = true 31 | for i=1,100 do x = getmetatable(i) end 32 | assert(x == nil) 33 | end 34 | -------------------------------------------------------------------------------- /test/lib/base/index: -------------------------------------------------------------------------------- 1 | assert.lua 2 | error.lua 3 | getfenv.lua +lua<5.2 4 | getsetmetatable.lua 5 | ipairs.lua 6 | next.lua 7 | pairs.lua 8 | pcall_jit.lua 9 | select.lua 10 | tonumber_tostring.lua 11 | xpcall_jit.lua +compat5.2 12 | -------------------------------------------------------------------------------- /test/lib/base/ipairs.lua: -------------------------------------------------------------------------------- 1 | do --- small integer values 2 | local t = { 4,5,6,7,8,9,10 } 3 | local n = 0 4 | for i,v in ipairs(t) do 5 | assert(v == i+3) 6 | n = n + 1 7 | end 8 | assert(n == 7) 9 | end 10 | 11 | do --- jit key=value 12 | local t = {} 13 | for i=1,100 do t[i]=i end 14 | local n = 0 15 | for i,v in ipairs(t) do 16 | assert(i == v) 17 | n = n + 1 18 | end 19 | assert(n == 100) 20 | end 21 | 22 | do --- untitled 23 | local t = {} 24 | local o = {{}, {}} 25 | for i=1,100 do 26 | local c = i.."" 27 | t[i] = c 28 | o[1][c] = i 29 | o[2][c] = i 30 | end 31 | o[1]["90"] = nil 32 | 33 | local n = 0 34 | for _, c in ipairs(t) do 35 | for i = 1, 2 do 36 | o[i][c] = o[i][c] or 1 37 | n = n + 1 38 | end 39 | end 40 | assert(n == 200) 41 | end 42 | -------------------------------------------------------------------------------- /test/lib/base/next.lua: -------------------------------------------------------------------------------- 1 | do --- _G 1 2 | local ok, err = pcall(next, _G, 1) 3 | assert(not ok) 4 | local ok, err = pcall(function() next(_G, 1) end) 5 | assert(not ok) 6 | end 7 | 8 | do --- as iterator 9 | local t = { foo = 9, bar = 10, 4, 5, 6 } 10 | local r = {} 11 | local function dummy() end 12 | local function f(next) 13 | for k,v in next,t,nil do r[#r+1] = k; if v == 5 then f(dummy) end end 14 | end 15 | f(next) 16 | assert(#r == 5) 17 | end 18 | -------------------------------------------------------------------------------- /test/lib/base/pairs.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- nometatable 3 | local t = {} 4 | for i=1,10 do t[i] = i+100 end 5 | local a, b = 0, 0 6 | for j=1,100 do for k,v in ipairs(t) do a = a + k; b = b + v end end 7 | assert(a == 5500) 8 | assert(b == 105500) 9 | a, b = 0, 0 10 | for j=1,100 do for k,v in pairs(t) do a = a + k; b = b + v end end 11 | assert(a == 5500) 12 | assert(b == 105500) 13 | end 14 | 15 | do --- empty metatable 16 | local t = setmetatable({}, {}) 17 | for i=1,10 do t[i] = i+100 end 18 | local a, b = 0, 0 19 | for j=1,100 do for k,v in ipairs(t) do a = a + k; b = b + v end end 20 | assert(a == 5500) 21 | assert(b == 105500) 22 | a, b = 0, 0 23 | for j=1,100 do for k,v in pairs(t) do a = a + k; b = b + v end end 24 | assert(a == 5500) 25 | assert(b == 105500) 26 | end 27 | 28 | do --- metamethods +compat5.2 29 | local function iter(t, i) 30 | i = i + 1 31 | if t[i] then return i, t[i]+2 end 32 | end 33 | local function itergen(t) 34 | return iter, t, 0 35 | end 36 | local t = setmetatable({}, { __pairs = itergen, __ipairs = itergen }) 37 | for i=1,10 do t[i] = i+100 end 38 | local a, b = 0, 0 39 | for j=1,100 do for k,v in ipairs(t) do a = a + k; b = b + v end end 40 | assert(a == 5500) 41 | assert(b == 107500) 42 | a, b = 0, 0 43 | for j=1,100 do for k,v in pairs(t) do a = a + k; b = b + v end end 44 | assert(a == 5500) 45 | assert(b == 107500) 46 | end 47 | 48 | do --- _G 49 | local n = 0 50 | for k,v in pairs(_G) do 51 | assert(_G[k] == v) 52 | n = n + 1 53 | end 54 | assert(n >= 35) 55 | end 56 | 57 | do --- count 58 | local function count(t) 59 | local n = 0 60 | for i,v in pairs(t) do 61 | n = n + 1 62 | end 63 | return n; 64 | end 65 | assert(count({ 4,5,6,nil,8,nil,10}) == 5) 66 | assert(count({ [0] = 3, 4,5,6,nil,8,nil,10}) == 6) 67 | assert(count({ foo=1, bar=2, baz=3 }) == 3) 68 | assert(count({ foo=1, bar=2, baz=3, boo=4 }) == 4) 69 | assert(count({ 4,5,6,nil,8,nil,10, foo=1, bar=2, baz=3 }) == 8) 70 | local t = { foo=1, bar=2, baz=3, boo=4 } 71 | t.bar = nil; t.boo = nil 72 | assert(count(t) == 2) 73 | end 74 | -------------------------------------------------------------------------------- /test/lib/base/pcall_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- square sum 3 | local function f(x) return x*x end 4 | local x = 0 5 | for i=1,100 do 6 | local ok1, ok2, ok3, y = pcall(pcall, pcall, f, i) 7 | if not ok1 or not ok2 or not ok3 then break end 8 | x = x + y 9 | end 10 | assert(x == 338350) 11 | end 12 | 13 | do --- sqrt square sum 14 | local x = 0 15 | for i=1,100 do 16 | local ok1, ok2, ok3, y = pcall(pcall, pcall, math.sqrt, i*i) 17 | if not ok1 or not ok2 or not ok3 then break end 18 | x = x + y 19 | end 20 | assert(x == 5050) 21 | end 22 | 23 | do --- sum with error 24 | local function f(x) 25 | if x >= 150 then error("test", 0) end 26 | return x end 27 | local x = 0 28 | for i=1,200 do 29 | local ok1, ok2, ok3, y = pcall(pcall, pcall, f, i) 30 | if not ok1 or not ok2 or not ok3 then 31 | assert(ok1 and ok2 and not ok3) 32 | assert(y == "test") 33 | break 34 | end 35 | x = x + y 36 | end 37 | assert(x == 11175) 38 | end 39 | 40 | do --- sum or square 41 | local function f(x) 42 | if x >= 150 then return x*x end 43 | return x 44 | end 45 | local x = 0 46 | for i=1,200 do 47 | local ok1, ok2, ok3, y = pcall(pcall, pcall, f, i) 48 | if not ok1 or not ok2 or not ok3 then break end 49 | x = x + y 50 | end 51 | assert(x == 1584100) 52 | end 53 | 54 | do --- sum or square with error 55 | local function f(x) 56 | if x >= 150 then 57 | if x >= 175 then error("test", 0) end 58 | return x*x 59 | end 60 | return x 61 | end 62 | local x = 0 63 | for i=1,200 do 64 | local ok1, ok2, ok3, y = pcall(pcall, pcall, f, i) 65 | if not ok1 or not ok2 or not ok3 then 66 | assert(ok1 and ok2 and not ok3) 67 | assert(y == "test") 68 | -- note: no break, so we get an exit to interpreter 69 | else 70 | x = x + y 71 | end 72 | end 73 | assert(x == 668575) 74 | end 75 | -------------------------------------------------------------------------------- /test/lib/base/select.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- select # 3 | -- Test whether select("#", 3, 4) returns the correct number of arguments. 4 | local x = 0 5 | for i=1,100 do 6 | x = x + select("#", 3, 4) 7 | end 8 | assert(x == 200) 9 | end 10 | 11 | do --- select modf 12 | -- Test whether select("#", func()) also works with func returning multiple values 13 | local x = 0 14 | math.frexp(3) 15 | for i=1,100 do 16 | x = x + select("#", math.modf(i)) 17 | end 18 | assert(x == 200) 19 | end 20 | 21 | do --- select 1 22 | local x = 0 23 | for i=1,100 do 24 | x = x + select(1, i) 25 | end 26 | assert(x == 5050) 27 | end 28 | 29 | do --- select 2 30 | local x, y = 0, 0 31 | for i=1,100 do 32 | local a, b = select(2, 1, i, i+10) 33 | x = x + a 34 | y = y + b 35 | end 36 | assert(x == 5050 and y == 6050) 37 | end 38 | 39 | do --- select vararg # 40 | local function f(a, ...) 41 | local x = 0 42 | for i=1,select('#', ...) do 43 | x = x + select(i, ...) 44 | end 45 | assert(x == a) 46 | end 47 | for i=1,100 do 48 | f(1, 1) 49 | f(3, 1, 2) 50 | f(15, 1, 2, 3, 4, 5) 51 | f(0) 52 | f(3200, string.byte(string.rep(" ", 100), 1, 100)) 53 | end 54 | end 55 | 56 | do --- select vararg i 57 | local function f(a, ...) 58 | local x = 0 59 | for i=1,20 do 60 | local b = select(i, ...) 61 | if b then x = x + b else x = x + 9 end 62 | end 63 | assert(x == a) 64 | end 65 | for i=1,100 do 66 | f(172, 1) 67 | f(165, 1, 2) 68 | f(150, 1, 2, 3, 4, 5) 69 | f(180) 70 | f(640, string.byte(string.rep(" ", 100), 1, 100)) 71 | end 72 | end 73 | 74 | do --- select vararg 4 75 | local function f(a, ...) 76 | local x = 0 77 | for i=1,20 do 78 | local b = select(4, ...) 79 | if b then x = x + b else x = x + 9 end 80 | end 81 | assert(x == a) 82 | end 83 | for i=1,100 do 84 | f(180, 1) 85 | f(180, 1, 2) 86 | f(80, 1, 2, 3, 4, 5) 87 | f(180) 88 | f(640, string.byte(string.rep(" ", 100), 1, 100)) 89 | end 90 | end 91 | 92 | do --- varg-select specialisation requires guard against select 93 | local select = select 94 | local exptyp = "number" 95 | local function f(...) 96 | for i = 1, 100 do 97 | assert(type((select('#', ...))) == exptyp) 98 | if i == 75 then 99 | select = function() return "" end 100 | exptyp = "string" 101 | end 102 | end 103 | end 104 | f(1) 105 | end 106 | -------------------------------------------------------------------------------- /test/lib/base/tonumber_tostring.lua: -------------------------------------------------------------------------------- 1 | 2 | do --- tonumber int 3 | local x = 0 4 | for i=1,100 do x = x + tonumber(i) end 5 | assert(x == 5050) 6 | end 7 | 8 | do --- tonumber float 9 | local x = 0 10 | for i=1.5,100.5 do x = x + tonumber(i) end 11 | assert(x == 5100) 12 | end 13 | 14 | do --- tostring int / tonumber 15 | local t = {} 16 | for i=1,100 do t[i] = tostring(i) end 17 | local x = 0 18 | for i=1,100 do assert(type(t[i]) == "string"); x = x + tonumber(t[i]) end 19 | assert(x == 5050) 20 | end 21 | 22 | do --- tostring float / tonumber 23 | local t = {} 24 | for i=1,100 do t[i] = tostring(i+0.5) end 25 | local x = 0 26 | for i=1,100 do assert(type(t[i]) == "string"); x = x + tonumber(t[i]) end 27 | assert(x == 5100) 28 | end 29 | 30 | do --- tonumber table 31 | for i=1,100 do assert(tonumber({}) == nil) end 32 | end 33 | 34 | do --- tostring int / tostring 35 | local t = {} 36 | for i=1,100 do t[i] = tostring(i) end 37 | for i=1,100 do t[i] = tostring(t[i]) end 38 | local x = 0 39 | for i=1,100 do assert(type(t[i]) == "string"); x = x + t[i] end 40 | assert(x == 5050) 41 | end 42 | 43 | do --- tostring table __tostring 44 | local mt = { __tostring = function(t) return tostring(t[1]) end } 45 | local t = {} 46 | for i=1,100 do t[i] = setmetatable({i}, mt) end 47 | for i=1,100 do t[i] = tostring(t[i]) end 48 | local x = 0 49 | for i=1,100 do assert(type(t[i]) == "string"); x = x + t[i] end 50 | assert(x == 5050) 51 | end 52 | 53 | do --- tostring table __tostring __call 54 | local r = setmetatable({}, 55 | { __call = function(x, t) return tostring(t[1]) end }) 56 | local mt = { __tostring = r } 57 | local t = {} 58 | for i=1,100 do t[i] = setmetatable({i}, mt) end 59 | for i=1,100 do t[i] = tostring(t[i]) end 60 | local x = 0 61 | for i=1,100 do assert(type(t[i]) == "string"); x = x + t[i] end 62 | assert(x == 5050) 63 | end 64 | 65 | do --- print calls overridden tostring +lua<5.2 66 | local x = false 67 | local co = coroutine.create(function() print(1) end) 68 | debug.setfenv(co, setmetatable({}, { __index = { 69 | tostring = function() x = true end }})) 70 | coroutine.resume(co) 71 | assert(x == true) 72 | end 73 | 74 | do --- tonumber base 2 75 | assert(tonumber(111, 2) == 7) 76 | end 77 | 78 | do --- __tostring must be callable 79 | local t = setmetatable({}, { __tostring = "" }) 80 | assert(pcall(function() tostring(t) end) == false) 81 | end 82 | -------------------------------------------------------------------------------- /test/lib/base/xpcall_jit.lua: -------------------------------------------------------------------------------- 1 | local function tr(err) return "tr"..err end 2 | 3 | do --- square sum 4 | local function f(x) return x*x end 5 | local x = 0 6 | for i=1,100 do 7 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 8 | if not ok1 or not ok2 or not ok3 then break end 9 | x = x + y 10 | end 11 | assert(x == 338350) 12 | end 13 | 14 | do --- sqrt square sum 15 | local x = 0 16 | for i=1,100 do 17 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, math.sqrt, tr, i*i) 18 | if not ok1 or not ok2 or not ok3 then break end 19 | x = x + y 20 | end 21 | assert(x == 5050) 22 | end 23 | 24 | do --- sum with error 25 | local function f(x) 26 | if x >= 150 then error("test", 0) end 27 | return x end 28 | local x = 0 29 | for i=1,200 do 30 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 31 | if not ok1 or not ok2 or not ok3 then 32 | assert(ok1 and ok2 and not ok3) 33 | assert(y == "trtest") 34 | break 35 | end 36 | x = x + y 37 | end 38 | assert(x == 11175) 39 | end 40 | 41 | do --- square with error 42 | local function f(x) 43 | if x >= 150 then return x*x end 44 | return x 45 | end 46 | local x = 0 47 | for i=1,200 do 48 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 49 | if not ok1 or not ok2 or not ok3 then break end 50 | x = x + y 51 | end 52 | assert(x == 1584100) 53 | end 54 | 55 | do --- sum or square with error 56 | local function f(x) 57 | if x >= 150 then 58 | if x >= 175 then error("test", 0) end 59 | return x*x 60 | end 61 | return x 62 | end 63 | local x = 0 64 | for i=1,200 do 65 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 66 | if not ok1 or not ok2 or not ok3 then 67 | assert(ok1 and ok2 and not ok3) 68 | assert(y == "trtest") 69 | -- note: no break, so we get an exit to interpreter 70 | else 71 | x = x + y 72 | end 73 | end 74 | assert(x == 668575) 75 | end 76 | 77 | do --- xpcall swap after recorder error 78 | local x = 0 79 | for i=1,100 do 80 | local ok1, ok2, ok3, err = xpcall(xpcall, tr, xpcall, tr, error, tr, "test", 0) 81 | assert(ok1 and ok2 and not ok3 and err == "trtest") 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /test/lib/bit.lua: -------------------------------------------------------------------------------- 1 | local bit = require"bit" 2 | local byte, ipairs, tostring, pcall = string.byte, ipairs, tostring, pcall 3 | 4 | local vb = { 5 | 0, 1, -1, 2, -2, 0x12345678, 0x87654321, 6 | 0x33333333, 0x77777777, 0x55aa55aa, 0xaa55aa55, 7 | 0x7fffffff, 0x80000000, 0xffffffff 8 | } 9 | 10 | local function cksum(name, s, r) 11 | local z = 0 12 | for i=1,#s do z = (z + byte(s, i)*i) % 2147483629 end 13 | if z ~= r then 14 | error("bit."..name.." test failed (got "..z..", expected "..r..")", 0) 15 | end 16 | end 17 | 18 | local function check_unop(name, r) 19 | local f = bit[name] 20 | local s = "" 21 | if pcall(f) or pcall(f, "z") or pcall(f, true) then 22 | error("bit."..name.." fails to detect argument errors", 0) 23 | end 24 | for _,x in ipairs(vb) do s = s..","..tostring(f(x)) end 25 | cksum(name, s, r) 26 | end 27 | 28 | local function check_binop(name, r) 29 | local f = bit[name] 30 | local s = "" 31 | if pcall(f) or pcall(f, "z") or pcall(f, true) then 32 | error("bit."..name.." fails to detect argument errors", 0) 33 | end 34 | for _,x in ipairs(vb) do 35 | for _2,y in ipairs(vb) do s = s..","..tostring(f(x, y)) --[[io.write(_, " ", _2, " ", x, " ", y, " ", f(x, y), "\n")]] end 36 | end 37 | cksum(name, s, r) 38 | end 39 | 40 | local function check_binop_range(name, r, yb, ye) 41 | local f = bit[name] 42 | local s = "" 43 | if pcall(f) or pcall(f, "z") or pcall(f, true) or pcall(f, 1, true) then 44 | error("bit."..name.." fails to detect argument errors", 0) 45 | end 46 | for _,x in ipairs(vb) do 47 | for y=yb,ye do s = s..","..tostring(f(x, y)) end 48 | end 49 | cksum(name, s, r) 50 | end 51 | 52 | local function check_shift(name, r) 53 | check_binop_range(name, r, 0, 31) 54 | end 55 | 56 | do --- Minimal sanity checks. 57 | assert(0x7fffffff == 2147483647, "broken hex literals") 58 | assert(0xffffffff == -1 or 0xffffffff == 2^32-1, "broken hex literals") 59 | assert(tostring(-1) == "-1", "broken tostring()") 60 | assert(tostring(0xffffffff) == "-1" or tostring(0xffffffff) == "4294967295", "broken tostring()") 61 | end 62 | 63 | do --- Basic argument processing. 64 | assert(bit.tobit(1) == 1) 65 | assert(bit.band(1) == 1) 66 | assert(bit.bxor(1,2) == 3) 67 | assert(bit.bor(1,2,4,8,16,32,64,128) == 255) 68 | end 69 | 70 | do --- unop test vectors 71 | check_unop("tobit", 277312) 72 | check_unop("bnot", 287870) 73 | check_unop("bswap", 307611) 74 | end 75 | 76 | do --- binop test vectors 77 | check_binop("band", 41206764) 78 | check_binop("bor", 51253663) 79 | check_binop("bxor", 79322427) 80 | end 81 | 82 | do --- shift test vectors 83 | check_shift("lshift", 325260344) 84 | check_shift("rshift", 139061800) 85 | check_shift("arshift", 111364720) 86 | check_shift("rol", 302401155) 87 | check_shift("ror", 302316761) 88 | end 89 | 90 | do --- tohex test vectors 91 | check_binop_range("tohex", 47880306, -8, 8) 92 | end 93 | 94 | do --- Don't propagate TOBIT narrowing across two conversions. 95 | local tobit = bit.tobit 96 | local k = 0x8000000000003 97 | for i=1,100 do assert(tobit(k % (2^32)) == 3) end 98 | end 99 | -------------------------------------------------------------------------------- /test/lib/coroutine/index: -------------------------------------------------------------------------------- 1 | yield.lua 2 | -------------------------------------------------------------------------------- /test/lib/ffi/cdata_var.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do --- byte array allocations 4 | local typ = ffi.typeof"uint8_t[?]" 5 | for i = 4, 24 do 6 | for d = -5, 5 do 7 | local sz = 2^i + d 8 | assert(ffi.sizeof(typ, sz) == sz) 9 | local mem = ffi.new(typ, sz) 10 | assert(ffi.sizeof(mem) == sz) 11 | mem[0] = 0x21 12 | mem[1] = 0x32 13 | mem[2] = 0x43 14 | mem[sz-3] = 0x54 15 | mem[sz-2] = 0x65 16 | mem[sz-1] = 0x76 17 | assert(mem[0] == 0x21) 18 | assert(mem[1] == 0x32) 19 | assert(mem[2] == 0x43) 20 | assert(mem[3] == 0) 21 | assert(mem[sz-4] == 0) 22 | assert(mem[sz-3] == 0x54) 23 | assert(mem[sz-2] == 0x65) 24 | assert(mem[sz-1] == 0x76) 25 | end 26 | end 27 | end 28 | 29 | do --- int array allocations 30 | local typ = ffi.typeof"int32_t[?]" 31 | for i = 2, 17 do 32 | for d = -2, 2 do 33 | local sz = 2^i + d 34 | assert(ffi.sizeof(typ, sz) == sz*4) 35 | local mem = ffi.new(typ, sz) 36 | assert(ffi.sizeof(mem) == sz*4) 37 | mem[0] = -3 38 | mem[sz-1] = -4 39 | assert(mem[0] == -3) 40 | if sz ~= 2 then 41 | assert(mem[1] == 0) 42 | assert(mem[sz-2] == 0) 43 | end 44 | assert(mem[sz-1] == -4) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/lib/ffi/copy_fill.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do --- misc 4 | local arr = ffi.typeof("char[11]") 5 | local a = arr() 6 | local b = arr() 7 | local c = arr() 8 | 9 | for i=0,9 do a[i] = 97+i; b[i] = 106-i end 10 | a[10] = 0; b[10] = 0; 11 | 12 | ffi.copy(c, a, 11) 13 | for i=0,9 do assert(c[i] == 97+i) end 14 | assert(ffi.string(c) == "abcdefghij") 15 | 16 | ffi.copy(c, b, 5) 17 | for i=0,4 do assert(c[i] == 106-i) end 18 | for i=5,9 do assert(c[i] == 97+i) end 19 | assert(ffi.string(c) == "jihgffghij") 20 | 21 | c[7] = 0 22 | assert(ffi.string(c) == "jihgffg") 23 | 24 | c[10] = 1 25 | ffi.copy(c, "ABCDEFGHIJ") 26 | for i=0,9 do assert(c[i] == 65+i) end 27 | assert(c[10] == 0) 28 | assert(ffi.string(c) == "ABCDEFGHIJ") 29 | 30 | ffi.copy(c, "abcdefghij", 5) 31 | assert(ffi.string(c) == "abcdeFGHIJ") 32 | 33 | ffi.fill(c, 10, 65) 34 | assert(ffi.string(c) == "AAAAAAAAAA") 35 | for i=10,0,-1 do ffi.fill(c, i, 96+i) end 36 | assert(ffi.string(c) == "abcdefghij") 37 | ffi.fill(c, 10) 38 | assert(c[0] == 0) 39 | assert(c[9] == 0) 40 | 41 | -- test length parameter to ffi.string 42 | ffi.fill(c, 10, 65) 43 | assert(ffi.string(c, 5) == "AAAAA") 44 | end 45 | 46 | do --- jit char[10] 47 | local a = ffi.new("char[10]", 64) 48 | local x 49 | for i=1,100 do a[0] = i; x = ffi.string(a, 10) end 50 | assert(x == "d@@@@@@@@@") 51 | end 52 | 53 | do --- jit char[1] 54 | local a = ffi.new("char[1]") 55 | local x, y 56 | for i=1,100 do 57 | a[0] = i 58 | x = ffi.string(a, 1) 59 | a[0] = 126 60 | y = ffi.string(a, 1) 61 | end 62 | assert(x == "d" and y == "~") 63 | end 64 | 65 | -------------------------------------------------------------------------------- /test/lib/ffi/err.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do --- error in FFI metamethod: don't print metamethod frame. 4 | local ok, err = xpcall(function() 5 | local x = (1ll).foo 6 | end, debug.traceback) 7 | assert(ok == false) 8 | assert(not string.find(err, "__index")) 9 | end 10 | 11 | do --- tailcall in regular metamethod: keep metamethod frame. 12 | local ok, err = xpcall(function() 13 | local t = setmetatable({}, {__index = function() return rawget("x") end }) 14 | local y = t[1] 15 | end, debug.traceback) 16 | assert(ok == false) 17 | assert(string.find(err, "__index")) 18 | end 19 | 20 | do --- error in FFI metamethod: set correct PC. 21 | ffi.cdef[[ 22 | typedef struct { int x; int y; } ffi_err_point; 23 | ffi_err_point ffi_err_strchr(ffi_err_point* op1, ffi_err_point* op2) asm("strchr"); 24 | ]] 25 | local point = ffi.metatype("ffi_err_point", { __add = ffi.C.ffi_err_strchr }) 26 | local function foo() 27 | local p = point{ 3, 4 } 28 | local r = p + p 29 | local r = p + 5 30 | end 31 | local ok, err = xpcall(foo, debug.traceback) 32 | local line = debug.getinfo(foo).linedefined+3 33 | assert(string.match(err, "traceback:[^:]*:"..line..":")) 34 | end 35 | 36 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_arith_ptr.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | ffi.cdef[[ 6 | typedef struct { int a,b,c; } foo1_t; 7 | void free(void *); 8 | void *malloc(size_t); 9 | struct incomplete; 10 | ]] 11 | 12 | do 13 | local a = ffi.new("int[10]") 14 | local p1 = a+0 15 | p1[0] = 1; 16 | p1[1] = 2; 17 | assert(a[0] == 1) 18 | assert(a[1] == 2) 19 | assert(a == p1) 20 | assert(not (a ~= p1)) 21 | assert(p1 <= a) 22 | assert(a <= p1) 23 | assert(not (p1 < a)) 24 | assert(not (a < p1)) 25 | assert(a ~= nil) 26 | assert(not (a == nil)) 27 | assert(p1 ~= nil) 28 | assert(not (p1 == nil)) 29 | 30 | local p2 = a+2 31 | p2[0] = 3; 32 | p2[1] = 4; 33 | assert(a[2] == 3) 34 | assert(a[3] == 4) 35 | assert(p2 - p1 == 2) 36 | assert(p1 - p2 == -2) 37 | assert(p1 ~= p2) 38 | assert(not (p1 == p2)) 39 | assert(p1 < p2) 40 | assert(p2 > p1) 41 | assert(not (p1 > p2)) 42 | assert(not (p2 < p1)) 43 | assert(p1 <= p2) 44 | assert(p2 >= p1) 45 | assert(not (p1 >= p2)) 46 | assert(not (p2 <= p1)) 47 | 48 | local p3 = a-2 49 | assert(p3[2] == 1) 50 | assert(p3[3] == 2) 51 | local p4 = a+(-3) 52 | assert(p4[5] == 3) 53 | assert(p4[6] == 4) 54 | -- bad: adding two pointers or subtracting a pointer 55 | fails(function(p1, p2) return p1 + p2 end, p1, p2) 56 | fails(function(p1) return 1 - p1 end, p1) 57 | -- bad: subtracting different pointer types 58 | fails(function(p1) return p1 - ffi.new("char[1]") end, p1) 59 | -- but different qualifiers are ok 60 | local b = ffi.cast("const int *", a+5) 61 | assert(b - a == 5) 62 | end 63 | 64 | do 65 | local p1 = ffi.cast("void *", 0) 66 | local p2 = ffi.cast("int *", 1) 67 | assert(p1 == p1) 68 | assert(p2 == p2) 69 | assert(p1 ~= p2) 70 | assert(p1 == nil) 71 | assert(p2 ~= nil) 72 | end 73 | 74 | do 75 | local f1 = ffi.C.free 76 | local f2 = ffi.C.malloc 77 | local p1 = ffi.cast("void *", f1) 78 | assert(f1 == f1) 79 | assert(f1 ~= nil) 80 | assert(f1 ~= f2) 81 | assert(p1 == f1) 82 | assert(p1 ~= f2) 83 | assert(f1 < f2 or f1 > f2) 84 | fails(function(f1) return f1 + 1 end, f1) 85 | end 86 | 87 | do 88 | local s = ffi.new("foo1_t[10]") 89 | local p1 = s+3 90 | p1.a = 1; p1.b = 2; p1.c = 3 91 | p1[1].a = 4; p1[1].b = 5; p1[1].c = 6 92 | assert(s[3].a == 1 and s[3].b == 2 and s[3].c == 3) 93 | assert(s[4].a == 4 and s[4].b == 5 and s[4].c == 6) 94 | local p2 = s+6 95 | assert(p2 - p1 == 3) 96 | assert(p1 - p2 == -3) 97 | end 98 | 99 | do 100 | local mem = ffi.new("int[1]") 101 | local p = ffi.cast("struct incomplete *", mem) 102 | fails(function(p) return p+1 end, p) 103 | local ok, err = pcall(function(p) return p[1] end, p) 104 | assert(not ok and err:match("size.*unknown")) 105 | end 106 | 107 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_const.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | ffi.cdef[[ 6 | typedef struct s_t { 7 | int v, w; 8 | } s_t; 9 | 10 | typedef const s_t cs_t; 11 | 12 | typedef enum en_t { EE } en_t; 13 | 14 | typedef struct pcs_t { 15 | int v; 16 | const int w; 17 | } pcs_t; 18 | 19 | typedef struct foo_t { 20 | static const int cc = 17; 21 | enum { CC = -37 }; 22 | int i; 23 | const int ci; 24 | int bi:8; 25 | const int cbi:8; 26 | en_t e; 27 | const en_t ce; 28 | int a[10]; 29 | const int ca[10]; 30 | const char cac[10]; 31 | s_t s; 32 | cs_t cs; 33 | pcs_t pcs1, pcs2; 34 | const struct { 35 | int ni; 36 | }; 37 | complex cx; 38 | const complex ccx; 39 | complex *cp; 40 | const complex *ccp; 41 | } foo_t; 42 | ]] 43 | 44 | do 45 | local foo_t = ffi.typeof("foo_t") 46 | local x = foo_t() 47 | 48 | -- constval 49 | assert(x.cc == 17) 50 | fails(function(x) x.cc = 1 end, x) 51 | assert(x.CC == -37) 52 | fails(function(x) x.CC = 1 end, x) 53 | 54 | -- fields 55 | x.i = 1 56 | fails(function(x) x.ci = 1 end, x) 57 | x.e = 1 58 | fails(function(x) x.ce = 1 end, x) 59 | 60 | -- bitfields 61 | x.bi = 1 62 | fails(function(x) x.cbi = 1 end, x) 63 | 64 | -- arrays 65 | do 66 | local a = ffi.new("int[10]") 67 | a[0] = 1 68 | local ca = ffi.new("const int[10]") 69 | fails(function(ca) ca[0] = 1 end, ca) 70 | end 71 | x.a[0] = 1 72 | fails(function(x) x.ca[0] = 1 end, x) 73 | fails(function(x) x.a = x.ca end, x) -- incompatible type 74 | fails(function(x) x.ca = x.a end, x) 75 | fails(function(x) x.ca = {} end, x) 76 | fails(function(x) x.cac = "abc" end, x) 77 | 78 | -- structs 79 | do 80 | local s = ffi.new("s_t") 81 | s.v = 1 82 | local cs = ffi.new("cs_t") 83 | fails(function(cs) cs.v = 1 end, cs) 84 | end 85 | x.s.v = 1 86 | fails(function(x) x.cs.v = 1 end, x) 87 | x.s = x.cs 88 | fails(function(x) x.cs = x.s end, x) 89 | fails(function(x) x.cs = {} end, x) 90 | 91 | -- pseudo-const structs 92 | x.pcs1.v = 1 93 | fails(function(x) x.pcs1.w = 1 end, x) 94 | fails(function(x) x.pcs1 = x.pcs2 end, x) 95 | fails(function(x) x.pcs1 = {} end, x) 96 | 97 | -- transparent structs 98 | local y = x.ni 99 | fails(function(x) x.ni = 1 end, x) 100 | 101 | -- complex subtype is implicitly const and doesn't inherit const attribute 102 | x.cx = 1 103 | fails(function(x) x.ccx = 1 end, x) 104 | do 105 | local cxa = ffi.new("complex[1]") 106 | local ccxa = ffi.new("const complex[1]") 107 | x.cp = cxa 108 | x.ccp = cxa 109 | fails(function(x) x.cp = ccxa end, x) 110 | x.ccp = ccxa 111 | end 112 | end 113 | 114 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_enum.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require("ffi") 3 | 4 | dofile("../common/ffi_util.inc") 5 | 6 | ffi.cdef[[ 7 | typedef enum enum_i { FOO_I = -1, II = 10 } enum_i; 8 | typedef enum enum_u { FOO_U = 1, UU = 10 } enum_u; 9 | 10 | enum_i call_ei_i(int a) asm("call_i"); 11 | enum_u call_eu_i(int a) asm("call_i"); 12 | int call_i_ei(enum_i a) asm("call_i"); 13 | int call_i_eu(enum_u a) asm("call_i"); 14 | ]] 15 | 16 | local C = ffi.load("../clib/ctest") 17 | 18 | do 19 | 20 | local t = ffi.new("enum_i[100]") 21 | for i=0,99 do t[i] = "II" end 22 | for i=0,99 do assert(t[i] == "II") end 23 | for i=0,99 do assert(t[i] >= "II") end 24 | for i=0,99 do t[i] = -10 end 25 | for i=0,99 do assert(t[i] == -10) end 26 | for i=0,99 do assert(t[i] ~= 2147483648) end 27 | for i=1,99 do assert(t[i] == t[i-1]) end 28 | assert(t[0]+1 == -9) 29 | assert(t[0] ~= "BB") 30 | fails(function() return t[0] > "BB" end) 31 | 32 | local u = ffi.new("enum_u[100]") 33 | for i=0,99 do u[i] = "UU" end 34 | for i=0,99 do assert(u[i] == "UU") end 35 | for i=0,99 do assert(u[i] >= "UU") end 36 | for i=0,99 do u[i] = 4294967296-10 end 37 | for i=0,99 do assert(u[i] == 4294967296-10) end 38 | for i=0,99 do assert(u[i] ~= -10) end 39 | for i=1,99 do assert(u[i] == u[i-1]) end 40 | assert(u[0]+1 == 4294967296-9) 41 | 42 | for i=0,99 do assert(t[i] ~= u[i]) end 43 | end 44 | 45 | do 46 | for i=0,99 do assert(C.call_ei_i(9) == "II") end 47 | for i=0,99 do assert(C.call_eu_i(9) == "UU") end 48 | for i=0,99 do assert(C.call_i_ei("II") == 11) end 49 | for i=0,99 do assert(C.call_i_eu("UU") == 11) end 50 | end 51 | 52 | do 53 | local f = ffi.cast("bool (*)(enum_i)", function(e) return e == "II" end) 54 | assert(f("II")) 55 | assert(not f(0)) 56 | end 57 | 58 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_gcstep_recursive.lua: -------------------------------------------------------------------------------- 1 | -- From Robert G. Jakabosky, 2012-03-20 2 | 3 | local N=tonumber(arg[1] or 10000) 4 | 5 | local ffi=require"ffi" 6 | 7 | ffi.cdef[[ 8 | struct Buffer { void *buf; }; 9 | typedef struct Buffer Buffer; 10 | ]] 11 | 12 | local Buffer_mt = { __index = {} } 13 | local Buffer = ffi.typeof("Buffer") 14 | 15 | -- used to track alive objects 16 | local nobj_obj_flags = {} 17 | 18 | local function obj_to_id(ptr) 19 | return tonumber(ffi.cast('uintptr_t', ffi.cast('void *', ptr))) 20 | end 21 | 22 | function obj_type_Buffer_push(val) 23 | local obj = Buffer(val) 24 | local id = obj_to_id(obj) 25 | nobj_obj_flags[id] = true 26 | return obj 27 | end 28 | 29 | local function Buffer_new(len) 30 | local buf = ffi.cast('void *', 0xdeadbeef) 31 | return obj_type_Buffer_push(buf) 32 | end 33 | 34 | function obj_type_Buffer_delete(obj) 35 | local id = obj_to_id(obj) 36 | if not nobj_obj_flags[id] then return nil end 37 | nobj_obj_flags[id] = nil 38 | return obj.buf 39 | end 40 | 41 | local getmeta = debug.getmetatable 42 | 43 | local function Buffer_close(self) 44 | local buf = obj_type_Buffer_delete(self) 45 | getmeta("Buffer_close") -- cause trace to abort 46 | if buf then 47 | self.buf = nil 48 | end 49 | end 50 | Buffer_mt.__gc = Buffer_close 51 | Buffer_mt.__index.close = Buffer_close 52 | 53 | ffi.metatype(Buffer, Buffer_mt) 54 | 55 | local cdata = {} 56 | for x=1,2 do 57 | cdata = {} 58 | for i=1,N do 59 | cdata[i] = Buffer_new(1) 60 | end 61 | for i=1,N do 62 | cdata[i]:close() 63 | end 64 | cdata = nil 65 | end 66 | 67 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_lex_number.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | local function checklex(t) 6 | for i=1,1e9,2 do 7 | local s = t[i+1] 8 | if not s then break end 9 | local s2 = assert(loadstring("return tostring("..s..")"))() 10 | if s2 ~= t[i] then 11 | print(s2) 12 | error("lexer failed for '"..s.."'", 2) 13 | end 14 | end 15 | end 16 | 17 | checklex{ 18 | "0LL", "0ll", 19 | "0LL", "0LL", 20 | "0ULL", "0ull", 21 | "0ULL", "0ULl", 22 | "18446744073709551615ULL", "18446744073709551615llu", 23 | "9223372036854775807LL", "0x7fffffffffffffffll", 24 | "9223372036854775808ULL", "0x8000000000000000ull", 25 | "1311768467463790320LL", "0x123456789abcdef0ll", 26 | "-1LL", "-1ll", 27 | "18446744073709551615ULL", "-1ull", 28 | "-9223372036854775807LL", "-0x7fffffffffffffffll", 29 | "9223372036854775808ULL", "-0x8000000000000000ull", 30 | "0+0i", "0i", 31 | "0+0i", "0I", 32 | "0+12.5i", "12.5i", 33 | "0+4660i", "0x1234i", 34 | "0+infI", "1e400i", 35 | "0-infI", "-1e400i", 36 | "0-12.5i", "-12.5i", 37 | "0-0i", "-0i", 38 | } 39 | 40 | checkfail({ 41 | "0l", 42 | "0lll", 43 | "0u", 44 | "0ul", 45 | "0ulll", 46 | "0wll", 47 | "0xll", 48 | ".0ll", 49 | "0ii", 50 | }, function(s) assert(loadstring("return "..s)) end) 51 | 52 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_new.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | local bit = require("bit") 3 | 4 | dofile("../common/ffi_util.inc") 5 | 6 | ffi.cdef([[ 7 | typedef struct { int a,b,c; } foo1_t; 8 | typedef int foo2_t[?]; 9 | void *malloc(size_t size); 10 | void free(void *ptr); 11 | ]]) 12 | 13 | do 14 | assert(ffi.sizeof("foo1_t") == 12) 15 | local cd = ffi.new("foo1_t") 16 | assert(ffi.sizeof(cd) == 12) 17 | local foo1_t = ffi.typeof("foo1_t") 18 | assert(ffi.sizeof(foo1_t) == 12) 19 | cd = foo1_t() 20 | assert(ffi.sizeof(cd) == 12) 21 | end 22 | 23 | do 24 | assert(ffi.sizeof("foo2_t", 3) == 12) 25 | local cd = ffi.new("foo2_t", 3) 26 | assert(ffi.sizeof(cd) == 12) 27 | local foo2_t = ffi.typeof("foo2_t") 28 | fails(ffi.sizeof, foo2_t) 29 | assert(ffi.sizeof(foo2_t, 3) == 12) 30 | cd = foo2_t(3) 31 | assert(ffi.sizeof(cd) == 12) 32 | end 33 | 34 | do 35 | local tpi = ffi.typeof("int") 36 | local tpb = ffi.typeof("uint8_t") 37 | local t = {} 38 | for i=1,200 do t[i] = tpi end 39 | t[100] = tpb 40 | local x = 0 41 | for i=1,200 do x = x + tonumber(ffi.new(t[i], 257)) end 42 | assert(x == 199*257 + 1) 43 | end 44 | 45 | do 46 | local oc = collectgarbage("count") 47 | for al=0,15 do 48 | local align = 2^al -- 1, 2, 4, ..., 32768 49 | local ct = ffi.typeof("struct { char __attribute__((aligned("..align.."))) a; }") 50 | for i=1,100 do 51 | local cd = ct() 52 | local addr = tonumber(ffi.cast("intptr_t", ffi.cast("void *", cd))) 53 | assert(bit.band(addr, align-1) == 0) 54 | end 55 | end 56 | local nc = collectgarbage("count") 57 | assert(nc < oc + 3000, "GC step missing for ffi.new") 58 | end 59 | 60 | do 61 | local t = {} 62 | for i=1,100 do t[i] = ffi.new("int[?]", i) end 63 | assert(ffi.sizeof(t[100]) == 400) 64 | for i=0,99 do assert(t[100][i] == 0) end 65 | end 66 | 67 | do 68 | local t = {} 69 | local ct = ffi.typeof("struct { double x; int y[?];}") 70 | for i=1,100 do t[i] = ct(i) end 71 | assert(ffi.sizeof(t[100]) == 408) 72 | for i=0,99 do assert(t[100].y[i] == 0) end 73 | end 74 | 75 | do 76 | local ct = ffi.typeof("struct __attribute__((aligned(16))) { int x; }") 77 | local y 78 | for i=1,200 do 79 | local x = ct() 80 | if i == 150 then y = x end 81 | end 82 | assert(bit.band(ffi.cast("intptr_t", ffi.cast("void *", y)), 15) == 0) 83 | end 84 | 85 | do 86 | local q 87 | local p = ffi.gc(ffi.new("int[1]"), function(x) q = x end) 88 | p = nil 89 | collectgarbage() 90 | assert(type(q) == "cdata") 91 | q = nil 92 | collectgarbage() 93 | assert(q == nil) 94 | end 95 | 96 | do 97 | local p = ffi.gc(ffi.C.malloc(2^20), ffi.C.free) 98 | p = nil 99 | collectgarbage() 100 | end 101 | 102 | do 103 | local p = ffi.gc(ffi.new("int[1]"), function(x) assert(type(x) == "cdata") end) 104 | -- test for lua_close() cleanup. 105 | end 106 | 107 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_parse_array.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | checkfail{ 6 | "int [", 7 | "int [-1]", 8 | "int [[1]]", 9 | "int [10][]", 10 | "int [10][?]", 11 | "int [][]", 12 | "int [][?]", 13 | "int [?][]", 14 | "int [?][?]", 15 | "int [0x10000][0x2000]", 16 | "int [256][256][256][256]", 17 | "int [10](void)", 18 | "int (void)[10]", 19 | "int &[10]", 20 | "union { double x; int a[?]; }", 21 | } 22 | 23 | ffi.cdef([[ 24 | typedef int foo1_t[10]; 25 | typedef foo1_t foo2_t[5]; 26 | ]]) 27 | assert(ffi.sizeof("foo1_t") == 40) 28 | assert(ffi.sizeof("foo2_t") == 200) 29 | 30 | local P = ffi.sizeof("void *") 31 | 32 | checktypes{ 33 | 10, 1, "char [10]", 34 | 4*10, 4, "int [10]", 35 | 4*10, 4, "int [10]", 36 | 4*10*5, 4, "int [10][5]", 37 | 4*10*5*3*2*7, 4, "int [10][5][3][2][7]", 38 | 4*10*5, 4, "int ([10])[5]", 39 | P*10, P, "int *[10]", 40 | P, P, "int (*)[10]", 41 | P*5, P, "int (*[5])[10]", 42 | 8*10, 4, "struct { int x; char y; } [10]", 43 | P*5*10, P, "volatile int *(* const *[5][10])(void)", 44 | nil, 4, "int []", 45 | 4*10, 8, "int __attribute__((aligned(8))) [10]", 46 | 4*10, 8, "__attribute__((aligned(8))) int [10]", 47 | 4*10, 8, "int [10] __attribute__((aligned(8)))", 48 | 97, 1, "char ['a']", 49 | 83, 1, "char ['\\123']", 50 | 79, 1, "char ['\x4F']", 51 | 5, 1, "char [sizeof(\"aa\" \"bb\")]", 52 | 80, 8, "double [10]", 53 | } 54 | 55 | do 56 | assert(ffi.sizeof("int [?]", 10) == 4*10) 57 | local id = ffi.typeof("const short [?]") 58 | assert(ffi.sizeof(id, 10) == 2*10) 59 | assert(ffi.sizeof(id, 0) == 0*10) 60 | fails(ffi.sizeof, id) 61 | assert(ffi.sizeof(id, -1) == nil) 62 | assert(ffi.sizeof(id, 0x80000000) == nil) 63 | assert(ffi.sizeof(id, 0x40000000) == nil) 64 | assert(ffi.sizeof(id, 0x3fffffff) == 2*0x3fffffff) 65 | end 66 | 67 | do 68 | assert(ffi.sizeof("struct { double x; int a[?]; }", 10) == 8+4*10) 69 | local id = ffi.typeof("struct { int x; short a[?]; }") 70 | assert(ffi.sizeof(id, 10) == 4+2*10) 71 | assert(ffi.sizeof(id, 0) == 4+0*10) 72 | fails(ffi.sizeof, id) 73 | assert(ffi.sizeof(id, -1) == nil) 74 | assert(ffi.sizeof(id, 0x80000000) == nil) 75 | assert(ffi.sizeof(id, 0x40000000) == nil) 76 | assert(ffi.sizeof(id, 0x3ffffffd) == 4+2*0x3ffffffd) 77 | end 78 | 79 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_parse_cdef.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | checkfail({ 6 | "int", 7 | "int aa1; int aa2 ", 8 | "static int x;", 9 | "static const long long x = 1;", -- NYI 10 | "static const double x = 1;", -- NYI 11 | "static const bool x = 1;", -- NYI (intentional, need true/false) 12 | "struct { static int x = 1; };", 13 | ";;static int y" 14 | }, ffi.cdef) 15 | 16 | ffi.cdef[[ 17 | static const int K_42a = 42; 18 | static const char K_42b = 42+256; 19 | static const short K_M1a = 65535; 20 | static const unsigned short K_65535a = 65535; 21 | static const int K_1b = 0xffffffff >> 31; 22 | static const int K_1c = 0xffffffffu >> 31; 23 | static const int K_M1b = (int)0xffffffff >> 31; 24 | ]] 25 | 26 | checktypes{ 27 | 42, 1, "char[K_42a]", 28 | 42, 1, "char[K_42b]", 29 | 1, 1, "char[-K_M1a]", 30 | 65535, 1, "char[K_65535a]", 31 | 1, 1, "char[K_1b]", 32 | 1, 1, "char[K_1c]", 33 | 1, 1, "char[-K_M1b]", 34 | } 35 | 36 | ffi.cdef[[ 37 | struct str1 { 38 | enum { 39 | K_99 = 99 40 | }; 41 | static const int K_55 = 55; 42 | } extk; 43 | ]] 44 | 45 | checktypes{ 46 | 99, 1, "char[K_99]", 47 | 99, 1, "char[extk.K_99]", 48 | 99, 1, "char[((struct str1)0).K_99]", 49 | 99, 1, "char[((struct str1 *)0)->K_99]", 50 | 55, 1, "char[extk.K_55]", 51 | } 52 | 53 | checkfail{ 54 | "char[K_55]", 55 | } 56 | 57 | ffi.cdef[[ 58 | extern int func1(void); 59 | extern int func2(); 60 | static int func3(); 61 | static inline int func4(int n) 62 | { 63 | int i, k = 0; 64 | float x = 1.0f; 65 | for (i = 0; i < n; i++) { 66 | k += i; 67 | } 68 | return k; 69 | } 70 | ;;; 71 | ]] 72 | 73 | ffi.cdef[[ 74 | int ext1; 75 | extern int ext2; 76 | ]] 77 | 78 | -------------------------------------------------------------------------------- /test/lib/ffi/ffi_tabov.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | local last = 0 4 | 5 | assert(pcall(function() 6 | for i=1,65536 do 7 | last = i 8 | ffi.typeof"struct {}" 9 | end 10 | end) == false) 11 | 12 | assert(last > 20000) 13 | -------------------------------------------------------------------------------- /test/lib/ffi/index: -------------------------------------------------------------------------------- 1 | bit64.lua +luajit>=2.1 2 | cdata_var.lua 3 | copy_fill.lua 4 | err.lua 5 | istype.lua 6 | jit_array.lua 7 | jit_complex.lua 8 | jit_misc.lua 9 | jit_struct.lua 10 | meta_tostring.lua 11 | redir.lua 12 | type_punning.lua 13 | -------------------------------------------------------------------------------- /test/lib/ffi/istype.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do --- 1 4 | local void_t = ffi.typeof("void") 5 | assert(ffi.istype(void_t, void_t)) 6 | assert(ffi.istype("const void", void_t)) 7 | 8 | assert(ffi.istype("void", "void") == false) -- 2nd arg is a string. 9 | assert(ffi.istype("double", 1.5) == false) -- 2nd arg is a number. 10 | end 11 | 12 | do --- 2 13 | local i8_t = ffi.typeof("int8_t") 14 | local u8_t = ffi.typeof("uint8_t") 15 | local i32_t = ffi.typeof("int32_t") 16 | assert(ffi.istype(i32_t, i32_t) == true) 17 | assert(ffi.istype("const int32_t", i32_t) == true) 18 | 19 | assert(ffi.istype("bool", u8_t) == false) 20 | assert(ffi.istype(i8_t, u8_t) == false) 21 | assert(ffi.istype(i32_t, u8_t) == false) 22 | assert(ffi.istype(u8_t, i32_t) == false) 23 | assert(ffi.istype("double", i32_t) == false) 24 | 25 | assert(ffi.istype("int64_t", ffi.typeof("long long"))) 26 | assert(ffi.istype("long long", ffi.typeof("int64_t"))) 27 | end 28 | 29 | do --- 3 30 | local ptr_t = ffi.typeof("int *") 31 | local p = ptr_t() 32 | assert(ffi.istype(ptr_t, ptr_t) == true) 33 | assert(ffi.istype(ptr_t, p) == true) 34 | assert(ffi.istype(p, ptr_t) == true) 35 | assert(ffi.istype("const int *", ptr_t) == true) 36 | assert(ffi.istype("const int * const", ptr_t) == true) 37 | assert(ffi.istype("unsigned int *", ptr_t) == true) 38 | 39 | assert(ffi.istype("char *", ptr_t) == false) 40 | assert(ffi.istype("void *", ptr_t) == false) 41 | end 42 | 43 | do --- 4 44 | ffi.cdef[[ 45 | typedef int istype_arr_t[10]; 46 | typedef const istype_arr_t istype_carr_t; 47 | typedef struct { int x; } istype_struct_t; 48 | ]] 49 | 50 | local arr_t = ffi.typeof("istype_arr_t") 51 | local carr_t = ffi.typeof("istype_carr_t") 52 | assert(ffi.istype(arr_t, arr_t) == true) 53 | assert(ffi.istype("int[10]", arr_t) == true) 54 | 55 | assert(ffi.istype("int[11]", arr_t) == false) 56 | assert(ffi.istype("int[]", arr_t) == false) 57 | assert(ffi.istype("int *", arr_t) == false) 58 | 59 | assert(ffi.istype("const int[10]", arr_t) == true) 60 | assert(ffi.istype("volatile int[10]", arr_t) == true) 61 | assert(ffi.istype(carr_t, arr_t) == true) 62 | 63 | local struct_t = ffi.typeof("istype_struct_t") 64 | local structp_t = ffi.typeof("istype_struct_t *") 65 | assert(ffi.istype(struct_t, struct_t) == true) 66 | assert(ffi.istype("const istype_struct_t", struct_t) == true) 67 | assert(ffi.istype("struct { int x; }", struct_t) == false) 68 | assert(ffi.istype(struct_t, structp_t) == true) -- struct ptr is ok for struct. 69 | assert(ffi.istype(structp_t, struct_t) == false) 70 | end 71 | 72 | do --- 5 73 | local int_t = ffi.typeof("int") 74 | local t = {} 75 | for i=1,200 do t[i] = int_t() end 76 | t[100] = ffi.new("uint8_t") 77 | local x = 0 78 | for i=1,200 do if not ffi.istype("int", t[i]) then x = x + i end end 79 | assert(x == 100) 80 | x = 0 81 | for i=1,200 do if not ffi.istype(int_t, t[i]) then x = x + i end end 82 | assert(x == 100) 83 | for i=1,200 do t[i] = int_t end 84 | t[100] = ffi.typeof("uint8_t") 85 | x = 0 86 | for i=1,200 do if not ffi.istype(t[i], int_t) then x = x + i end end 87 | assert(x == 100) 88 | end 89 | -------------------------------------------------------------------------------- /test/lib/ffi/jit_complex.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | local cx = ffi.typeof("complex") 4 | local cxf = ffi.typeof("complex float") 5 | 6 | ffi.cdef[[ 7 | typedef struct jit_complex_chain_t { 8 | struct jit_complex_chain_t *next; 9 | complex c; 10 | } jit_complex_chain_t; 11 | ]] 12 | 13 | do --- field access 14 | local c = cx(1, 2) 15 | local x 16 | for i=1,100 do 17 | x = c.re + c.im 18 | end 19 | assert(x == 3) 20 | end 21 | 22 | do --- one element circular chain, named indexing 23 | local cp = ffi.new("jit_complex_chain_t") 24 | local p = cp 25 | p.next = p 26 | p.c = cx(1, 2) 27 | local x,y = 0,0 28 | for i=1,100 do 29 | x = x + p.c.re 30 | y = y + p.c.im 31 | p = p.next 32 | end 33 | assert(x == 100) 34 | assert(y == 200) 35 | end 36 | 37 | do --- one element circular chain, array indexing 38 | local cp = ffi.new("jit_complex_chain_t") 39 | local p = cp 40 | p.next = p 41 | p.c = cx(1, 2) 42 | local x,y = 0,0 43 | for i=1,100 do 44 | x = x + p.c[0] 45 | y = y + p.c[1] 46 | p = p.next 47 | end 48 | assert(x == 100) 49 | assert(y == 200) 50 | end 51 | 52 | do --- one-arg initialiser 53 | local ca = ffi.new("complex[?]", 101) 54 | for i=1,100 do 55 | ca[i] = cx(i) -- handled as init single 56 | end 57 | local x,y = 0,0 58 | for i=1,100 do 59 | x = x + ca[i].re 60 | y = y + ca[i].im 61 | end 62 | assert(x == 5050) 63 | assert(y == 0) 64 | end 65 | 66 | do --- two-arg initialiser 67 | local ca = ffi.new("complex[?]", 101) 68 | for i=1,100 do 69 | ca[i] = cx(i, -i) 70 | end 71 | local x,y = 0,0 72 | for i=1,100 do 73 | x = x + ca[i].re 74 | y = y + ca[i].im 75 | end 76 | assert(x == 5050) 77 | assert(y == -5050) 78 | end 79 | 80 | do --- float<>double conversions 81 | local ca = ffi.new("complex[?]", 101) 82 | local caf = ffi.new("complex float[?]", 101) 83 | for i=1,100 do 84 | ca[i] = cxf(i, -i) 85 | caf[i] = cx(i, -i) 86 | end 87 | local x,y = 0,0 88 | for i=1,100 do 89 | x = x + caf[i].re + ca[i].re 90 | y = y + caf[i].im + ca[i].im 91 | end 92 | assert(x == 2*5050) 93 | assert(y == -2*5050) 94 | end 95 | 96 | do --- Complex struct field 97 | local s = ffi.new("struct { complex x;}") 98 | for i=1,100 do 99 | s.x = 12.5i 100 | end 101 | assert(s.x.re == 0) 102 | assert(s.x.im == 12.5) 103 | end 104 | 105 | do --- Index overflow for complex is ignored 106 | local c = cx(1, 2) 107 | local x 108 | for i=1e7,1e7+100 do x = c[i] end 109 | end 110 | -------------------------------------------------------------------------------- /test/lib/ffi/meta_tostring.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | ffi.cdef[[ 4 | typedef union meta_tostring_foo_t { 5 | int64_t i64; 6 | uint64_t u64; 7 | complex cd; 8 | double d[2]; 9 | complex float cf; 10 | float f[2]; 11 | } meta_tostring_foo_t; 12 | ]] 13 | 14 | do --- tostring/typeof semi-roundtrip 15 | assert(tostring(ffi.typeof("int (*(*[1][2])[3][4])[5][6]")) == 16 | "ctype") 17 | assert(tostring(ffi.typeof("int (*const)(void)")) == 18 | "ctype") 19 | assert(tostring(ffi.typeof("complex float(*(void))[2]")) == 20 | "ctype") 21 | assert(tostring(ffi.typeof("complex*")) == "ctype") 22 | end 23 | 24 | do --- assorted union fields 25 | local foo_t = ffi.typeof("meta_tostring_foo_t") 26 | local x = foo_t() 27 | 28 | assert(tostring(foo_t) == "ctype") 29 | assert(string.find(tostring(x), "^cdata: ")) 30 | 31 | x.i64 = -1; 32 | assert(tostring(x.i64) == "-1LL") 33 | assert(tostring(x.u64) == "18446744073709551615ULL") 34 | 35 | x.d[0] = 12.5 36 | x.d[1] = -753.125 37 | assert(tostring(x.cd) == "12.5-753.125i") 38 | x.d[0] = -12.5 39 | x.d[1] = 753.125 40 | assert(tostring(x.cd) == "-12.5+753.125i") 41 | x.d[0] = 0/-1 42 | x.d[1] = 0/-1 43 | assert(tostring(x.cd) == "-0-0i") 44 | x.d[0] = 1/0 45 | x.d[1] = -1/0 46 | assert(tostring(x.cd) == "inf-infI") 47 | x.d[0] = -1/0 48 | x.d[1] = 0/0 49 | assert(tostring(x.cd) == "-inf+nanI") 50 | 51 | x.f[0] = 12.5 52 | x.f[1] = -753.125 53 | assert(tostring(x.cf) == "12.5-753.125i") 54 | end 55 | 56 | -------------------------------------------------------------------------------- /test/lib/ffi/redir.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do --- function 4 | ffi.cdef[[ 5 | int redir_foo(const char *s) asm("strlen"); 6 | ]] 7 | 8 | assert(ffi.C.redir_foo("abcd") == 4) 9 | end 10 | 11 | do --- variable -windows 12 | ffi.cdef[[ 13 | int redir_bar asm("errno"); 14 | ]] 15 | 16 | ffi.C.redir_bar = 14 17 | assert(ffi.C.redir_bar == 14) 18 | ffi.C.redir_bar = 0 19 | end 20 | -------------------------------------------------------------------------------- /test/lib/index: -------------------------------------------------------------------------------- 1 | base 2 | bit.lua +bit 3 | math 4 | string 5 | table 6 | coroutine 7 | ffi +ffi 8 | contents.lua -------------------------------------------------------------------------------- /test/lib/math/abs.lua: -------------------------------------------------------------------------------- 1 | local abs = math.abs 2 | local expect_error = require"common.expect_error" 3 | 4 | do --- smoke 5 | assert(abs(-1.5) == 1.5) 6 | assert(abs("-1.5") == 1.5) 7 | end 8 | 9 | do --- argcheck 10 | expect_error(function() abs() end, 11 | "bad argument #1 to 'abs' (number expected, got no value)") 12 | expect_error(function() abs(false) end, 13 | "bad argument #1 to 'abs' (number expected, got boolean)") 14 | expect_error(function() abs("a") end, 15 | "bad argument #1 to 'abs' (number expected, got string)") 16 | end 17 | -------------------------------------------------------------------------------- /test/lib/math/constants.lua: -------------------------------------------------------------------------------- 1 | do --- pi 2 | assert(math.pi == 3.141592653589793) 3 | end 4 | 5 | do --- huge 6 | assert(math.huge > 0) 7 | assert(1/math.huge == 0) 8 | end 9 | -------------------------------------------------------------------------------- /test/lib/math/index: -------------------------------------------------------------------------------- 1 | abs.lua 2 | constants.lua 3 | random.lua 4 | -------------------------------------------------------------------------------- /test/lib/math/random.lua: -------------------------------------------------------------------------------- 1 | local random = math.random 2 | local MAX_SEED = 10 3 | 4 | do --- generally uniform in range [0, 1) 5 | local N = 100 6 | local min, max = math.min, math.max 7 | for j=1,MAX_SEED do 8 | math.randomseed(j) 9 | local lo, hi, sum = math.huge, -math.huge, 0 10 | for i=1,N do 11 | local x = random() 12 | assert(0 <= x and x < 1) 13 | sum = sum + x 14 | lo = min(lo, x) 15 | hi = max(hi, x) 16 | end 17 | assert(lo*N < 15 and (1-hi)*N < 15) 18 | assert(sum > N*0.45 and sum < N*0.55) 19 | end 20 | end 21 | 22 | do --- all in range [1, 10] 23 | math.randomseed(1) 24 | local counts = setmetatable({}, {__index = function() return 0 end}) 25 | for i = 1, 100 do 26 | local n = random(10) 27 | counts[n] = counts[n] + 1 28 | end 29 | for i = 1, 10 do 30 | assert(counts[i]) 31 | counts[i] = nil 32 | end 33 | assert(not next(counts)) 34 | end 35 | 36 | do --- all in range [-3, 11] 37 | math.randomseed(1) 38 | local seen = setmetatable({}, {__index = function() return false end}) 39 | for i = 1, 120 do 40 | seen[random(-3, 11)] = true 41 | end 42 | for i = -3, 11 do 43 | assert(seen[i]) 44 | seen[i] = nil 45 | end 46 | assert(not next(seen)) 47 | end 48 | -------------------------------------------------------------------------------- /test/lib/string/byte.lua: -------------------------------------------------------------------------------- 1 | local band, bor = bit and bit.band, bit and bit.bor 2 | local byte = string.byte 3 | 4 | do --- simple 5 | local a, b = ("foo"):byte(1) 6 | assert(type(a) == "number") 7 | assert(b == nil) 8 | local c, d = ("foo"):byte(2, 3) 9 | assert(type(c) == "number") 10 | assert(c == d) 11 | assert(c ~= a) 12 | end 13 | 14 | do --- Fixed slice [i,i+k] or overflow +bit 15 | local s = "abcdefg" 16 | local x,y,z 17 | for j=100,107 do 18 | for i=1,j do x,y,z = byte("abcdefg", band(i, 7), band(i+2, 7)) end 19 | local a,b,c = byte("abcdefg", band(j, 7), band(j+2, 7)) 20 | assert(x == a and y == b and z == c) 21 | end 22 | for j=100,107 do 23 | for i=1,j do x,y,z = byte(s, band(i, 7), band(i+2, 7)) end 24 | local a,b,c = byte(s, band(j, 7), band(j+2, 7)) 25 | assert(x == a and y == b and z == c) 26 | end 27 | end 28 | 29 | do --- Positive slice [i,len] or overflow +bit 30 | local s = "abc" 31 | local x,y,z 32 | for j=100,107 do 33 | for i=1,j do x,y,z = byte("abc", band(i, 7), -1) end 34 | local a,b,c = byte("abc", band(j, 7), -1) 35 | assert(x == a and y == b and z == c) 36 | end 37 | for j=100,107 do 38 | for i=1,j do x,y,z = byte(s, band(i, 7), -1) end 39 | local a,b,c = byte(s, band(j, 7), -1) 40 | assert(x == a and y == b and z == c) 41 | end 42 | end 43 | 44 | do --- Negative slice [-i,len] or underflow +bit 45 | local s = "abc" 46 | local x,y,z 47 | for j=-100,-107,-1 do 48 | for i=-1,j,-1 do x,y,z = byte("abc", bor(i, -8), -1) end 49 | local a,b,c = byte("abc", bor(j, -8), -1) 50 | assert(x == a and y == b and z == c) 51 | end 52 | for j=-100,-107,-1 do 53 | for i=-1,j,-1 do x,y,z = byte(s, bor(i, -8), -1) end 54 | local a,b,c = byte(s, bor(j, -8), -1) 55 | assert(x == a and y == b and z == c) 56 | end 57 | end 58 | 59 | do --- Positive slice [1,i] or overflow +bit 60 | local s = "abc" 61 | local x,y,z 62 | for j=100,107 do 63 | for i=1,j do x,y,z = byte("abc", 1, band(i, 7)) end 64 | local a,b,c = byte("abc", 1, band(j, 7)) 65 | assert(x == a and y == b and z == c) 66 | end 67 | for j=100,107 do 68 | for i=1,j do x,y,z = byte(s, 1, band(i, 7)) end 69 | local a,b,c = byte(s, 1, band(j, 7)) 70 | assert(x == a and y == b and z == c) 71 | end 72 | end 73 | 74 | do --- Negative slice [1,-i] or underflow +bit 75 | local s = "abc" 76 | local x,y,z 77 | for j=-100,-107,-1 do 78 | for i=-1,j,-1 do x,y,z = byte("abc", 1, bor(i, -8)) end 79 | local a,b,c = byte("abc", 1, bor(j, -8)) 80 | assert(x == a and y == b and z == c) 81 | end 82 | for j=-100,-107,-1 do 83 | for i=-1,j,-1 do x,y,z = byte(s, 1, bor(i, -8)) end 84 | local a,b,c = byte(s, 1, bor(j, -8)) 85 | assert(x == a and y == b and z == c) 86 | end 87 | end 88 | 89 | do --- Check for slot stack overflow 90 | local s = string.rep("x", 500) 91 | for i=1,100 do byte(s, 1, 500) end 92 | end 93 | -------------------------------------------------------------------------------- /test/lib/string/char.lua: -------------------------------------------------------------------------------- 1 | local char = string.char 2 | 3 | do --- jit one char 4 | local y 5 | for i=1,100 do y = char(65) end 6 | assert(y == "A") 7 | local x = 97 8 | for i=1,100 do y = char(x) end 9 | assert(y == "a") 10 | x = "98" 11 | for i=1,100 do y = char(x) end 12 | assert(y == "b") 13 | for i=1,100 do y = char(32+i) end 14 | assert(y == "\132") 15 | end 16 | 17 | do --- jit until out of bounds 18 | local y 19 | assert(not pcall(function() 20 | for i=1,200 do y = char(100+i) end 21 | end)) 22 | assert(y == "\255") 23 | end 24 | 25 | do --- jit five chars 26 | local y 27 | for i=1,100 do y = char(65, 66, i, 67, 68) end 28 | assert(y == "ABdCD") 29 | end 30 | -------------------------------------------------------------------------------- /test/lib/string/dump.lua: -------------------------------------------------------------------------------- 1 | local loadstring = loadstring or load 2 | 3 | do --- Must unpatch modified bytecode with ILOOP/JLOOP etc. 4 | local function foo() 5 | local t = {} 6 | for i=1,100 do t[i] = i end 7 | for a,b in ipairs(t) do end 8 | local m = 0 9 | while m < 100 do m = m + 1 end 10 | end 11 | 12 | local d1 = string.dump(foo) 13 | foo() 14 | assert(string.dump(foo) == d1) 15 | if jit then jit.off(foo) end 16 | foo() 17 | assert(string.dump(foo) == d1) 18 | local d2 = string.dump(loadstring(d1, ""), true) 19 | local d3 = string.dump(assert(loadstring(d2, "")), true) 20 | assert(d2 == d3) 21 | assert(loadstring(string.dump(assert(loadstring(d2, ""))))) 22 | end 23 | 24 | do --- roundtrip constants 25 | local function f1() return -0x80000000 end 26 | local function f2() return 0.971234567 end 27 | assert(f1() == -0x80000000) 28 | assert(loadstring(string.dump(f1), "")() == -0x80000000) 29 | assert(f2() == 0.971234567) 30 | assert(loadstring(string.dump(f2), "")() == 0.971234567) 31 | end 32 | -------------------------------------------------------------------------------- /test/lib/string/format/index: -------------------------------------------------------------------------------- 1 | num.lua 2 | -------------------------------------------------------------------------------- /test/lib/string/index: -------------------------------------------------------------------------------- 1 | metatable.lua 2 | byte.lua 3 | char.lua 4 | dump.lua 5 | format 6 | len.lua 7 | lower_upper.lua 8 | multiple_functions.lua 9 | rep.lua 10 | reverse.lua 11 | sub.lua 12 | -------------------------------------------------------------------------------- /test/lib/string/len.lua: -------------------------------------------------------------------------------- 1 | local len = string.len 2 | local expect_error = require"common.expect_error" 3 | 4 | do --- smoke 5 | assert(len("abc") == 3) 6 | assert(len(123) == 3) 7 | end 8 | 9 | do --- argcheck 10 | expect_error(function() len() end, 11 | "bad argument #1 to 'len' (string expected, got nil)") 12 | expect_error(function() len(false) end, 13 | "bad argument #1 to 'len' (string expected, got boolean)") 14 | end 15 | -------------------------------------------------------------------------------- /test/lib/string/lower_upper.lua: -------------------------------------------------------------------------------- 1 | do --- smoke 2 | assert(("abc123DEF_<>"):lower() == "abc123def_<>") 3 | assert(("abc123DEF_<>"):upper() == "ABC123DEF_<>") 4 | end 5 | 6 | do --- repeated 7 | local l = "the quick brown fox..." 8 | local u = "THE QUICK BROWN FOX..." 9 | local s = l 10 | for i = 1, 75 do 11 | s = s:upper() 12 | assert(s == u) 13 | s = s:lower() 14 | assert(s == l) 15 | end 16 | end 17 | 18 | do --- repeated with growing string 19 | local y, z 20 | local x = "aBcDe" 21 | for i=1,100 do 22 | y = string.upper(x) 23 | z = y.."fgh" 24 | end 25 | assert(y == "ABCDE") 26 | assert(z == "ABCDEfgh") 27 | end 28 | 29 | do --- misc upper 30 | local y 31 | for i=1,100 do y = string.upper("aBc9") end 32 | assert(y == "ABC9") 33 | local x = ":abCd+" 34 | for i=1,100 do y = string.upper(x) end 35 | assert(y == ":ABCD+") 36 | x = 1234 37 | for i=1,100 do y = string.upper(x) end 38 | assert(y == "1234") 39 | end 40 | 41 | do --- misc lower 42 | local y 43 | for i=1,100 do y = string.lower("aBc9") end 44 | assert(y == "abc9") 45 | local x = ":abcd+" 46 | for i=1,100 do y = string.lower(x) end 47 | assert(y == ":abcd+") 48 | x = 1234 49 | for i=1,100 do y = string.lower(x) end 50 | assert(y == "1234") 51 | end 52 | -------------------------------------------------------------------------------- /test/lib/string/metatable.lua: -------------------------------------------------------------------------------- 1 | do --- __index metamethod is string library 2 | assert(debug.getmetatable("").__index == string) 3 | end 4 | -------------------------------------------------------------------------------- /test/lib/string/multiple_functions.lua: -------------------------------------------------------------------------------- 1 | do --- string_op 2 | local t, y = {}, {} 3 | for i=1,100 do t[i] = string.char(i, 16+i, 32+i) end 4 | for i=1,100 do t[i] = string.reverse(t[i]) end 5 | assert(t[100] == "\132\116\100") 6 | for i=1,100 do t[i] = string.reverse(t[i]) end 7 | for i=1,100 do assert(t[i] == string.char(i, 16+i, 32+i)) end 8 | for i=1,100 do y[i] = string.upper(t[i]) end 9 | assert(y[65] == "AQA") 10 | assert(y[97] == "AQ\129") 11 | assert(y[100] == "DT\132") 12 | for i=1,100 do y[i] = string.lower(t[i]) end 13 | assert(y[65] == "aqa") 14 | assert(y[97] == "aq\129") 15 | assert(y[100] == "dt\132") 16 | end 17 | -------------------------------------------------------------------------------- /test/lib/string/rep.lua: -------------------------------------------------------------------------------- 1 | local rep = string.rep 2 | 3 | do --- smoke 4 | assert(("p"):rep(0) == "") 5 | assert(("a"):rep(3) == "aaa") 6 | assert(("x\0z"):rep(4) == "x\0zx\0zx\0zx\0z") 7 | end 8 | 9 | do --- versus concat 10 | local s = "" 11 | for i = 1, 75 do 12 | s = s .. "{}" 13 | assert(s == ("{}"):rep(i)) 14 | end 15 | end 16 | 17 | do --- misc 18 | local y 19 | for i=1,100 do y = rep("a", 10) end 20 | assert(y == "aaaaaaaaaa") 21 | for i=1,100 do y = rep("ab", 10) end 22 | assert(y == "abababababababababab") 23 | local x = "a" 24 | for i=1,100 do y = rep(x, 10) end 25 | assert(y == "aaaaaaaaaa") 26 | local n = 10 27 | for i=1,100 do y = rep(x, n) end 28 | assert(y == "aaaaaaaaaa") 29 | x = "ab" 30 | for i=1,100 do y = rep(x, n) end 31 | assert(y == "abababababababababab") 32 | x = 12 33 | n = "10" 34 | for i=1,100 do y = rep(x, n) end 35 | assert(y == "12121212121212121212") 36 | end 37 | 38 | do --- separator +goto 39 | local y 40 | for i=1,100 do y = rep("ab", 10, "c") end 41 | assert(y == "abcabcabcabcabcabcabcabcabcab") 42 | end 43 | 44 | do --- iterate to table 45 | local t = {} 46 | for i=1,100 do t[i] = rep("ab", i-85) end 47 | assert(t[100] == "ababababababababababababababab") 48 | end 49 | 50 | do --- iterate to table with sep +goto 51 | local t = {} 52 | for i=1,100 do t[i] = rep("ab", i-85, "c") end 53 | assert(t[85] == "") 54 | assert(t[86] == "ab") 55 | assert(t[87] == "abcab") 56 | assert(t[100] == "abcabcabcabcabcabcabcabcabcabcabcabcabcabcab") 57 | end 58 | 59 | do --- iterate and concat 60 | local y, z 61 | local x = "ab" 62 | for i=1,100 do 63 | y = rep(x, i-90) 64 | z = y.."fgh" 65 | end 66 | assert(y == "abababababababababab") 67 | assert(z == "ababababababababababfgh") 68 | end 69 | -------------------------------------------------------------------------------- /test/lib/string/reverse.lua: -------------------------------------------------------------------------------- 1 | local reverse = string.reverse 2 | 3 | do --- misc 4 | local y 5 | for i=1,100 do y = reverse("abc") end 6 | assert(y == "cba") 7 | local x = "abcd" 8 | for i=1,100 do y = reverse(x) end 9 | assert(y == "dcba") 10 | x = 1234 11 | for i=1,100 do y = reverse(x) end 12 | assert(y == "4321") 13 | end 14 | -------------------------------------------------------------------------------- /test/lib/table/concat.lua: -------------------------------------------------------------------------------- 1 | local concat, assert, pcall = table.concat, assert, pcall 2 | 3 | do --- table.concat 4 | local t = {a=1,b=2,c=3,d=4,e=5} 5 | t[1] = 4 6 | t[3] = 6 7 | local ok, err = pcall(concat, t, "", 1, 3) 8 | assert(not ok and err:match("index 2 ")) 9 | local q = {} 10 | for i=1,100 do q[i] = {9,8,7} end 11 | q[90] = t 12 | for i=1,100 do 13 | assert(pcall(concat, q[i], "", 1, 3) == (i ~= 90)) 14 | end 15 | t[2] = 5 -- index 1 - 3 in hash part 16 | q[91] = {} 17 | q[92] = {9} 18 | for i=1,100 do q[i] = concat(q[i], "x") end 19 | assert(q[90] == "4x5x6") 20 | assert(q[91] == "") 21 | assert(q[92] == "9") 22 | assert(q[93] == "9x8x7") 23 | end 24 | 25 | do --- table.concat must inhibit CSE and DSE 26 | local t = {1,2,3} 27 | local y, z 28 | for i=1,100 do 29 | y = concat(t, "x", 1, 3) 30 | t[2] = i 31 | z = concat(t, "x", 1, 3) 32 | end 33 | assert(y == "1x99x3") 34 | assert(z == "1x100x3") 35 | end 36 | 37 | do --- table.concat must inhibit CSE and DSE 2 38 | local y 39 | for i=1,100 do 40 | local t = {1,2,3} 41 | t[2] = 4 42 | y = concat(t, "x") 43 | t[2] = 9 44 | end 45 | assert(y == "1x4x3") 46 | end 47 | 48 | do --- table.concat must inhibit CSE and DSE 3 49 | local t = {[0]={}, {}, {}, {}} 50 | for i=1,30 do 51 | for j=3,0,-1 do 52 | t[j].x = t[j-1] 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /test/lib/table/index: -------------------------------------------------------------------------------- 1 | concat.lua 2 | insert.lua 3 | new.lua +table.new 4 | pack.lua +compat5.2 5 | remove.lua 6 | sort.lua 7 | -------------------------------------------------------------------------------- /test/lib/table/insert.lua: -------------------------------------------------------------------------------- 1 | local tinsert = table.insert 2 | local assert = assert 3 | 4 | do --- table.insert(t,i) 5 | local t = {} 6 | for i=1,100 do t[i] = i end 7 | for i=1,100 do tinsert(t, i) end 8 | assert(#t == 200 and t[100] == 100 and t[200] == 100) 9 | end 10 | 11 | do --- table.insert(t,i,i) 12 | local t = {} 13 | for i=1,200 do t[i] = i end 14 | for i=101,200 do tinsert(t, i, i) end 15 | assert(#t == 300 and t[101] == 101 and t[200] == 200 and t[300] == 200) 16 | end 17 | 18 | -------------------------------------------------------------------------------- /test/lib/table/misc.lua: -------------------------------------------------------------------------------- 1 | -- TODO: Organise 2 | 3 | -- ABC elim 4 | -- +opt +abc 5 | do 6 | local s, t = {}, {} 7 | for i=1,100 do t[i] = 1 end 8 | for i=1,100 do s[i] = t end 9 | s[90] = {} 10 | local n = 100 11 | for i=1,n do s[i][i] = i end 12 | end 13 | 14 | --- TSETM 15 | -- Initialize table with multiple return values 16 | do 17 | local function f(a,b,c) 18 | return a,b,c 19 | end 20 | 21 | local t 22 | 23 | t = {(f(1,2,3))} 24 | assert(t[1] == 1 and t[2] == nil and t[3] == nil) 25 | 26 | t = {f(1,2,3)} 27 | assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == nil) 28 | t = {f(1,2,3),} 29 | assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == nil) 30 | 31 | t = {f(1,2,3), f(4,5,6)} 32 | assert(t[1] == 1 and t[2] == 4 and t[3] == 5 and t[4] == 6 and t[5] == nil) 33 | 34 | t = { 35 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 36 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 37 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 38 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 39 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 40 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 41 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 42 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 43 | f(2,3,4)} 44 | assert(t[255] == 1 and t[256] == 2 and t[257] == 3 and t[258] == 4 and t[259] == nil) 45 | end 46 | 47 | --- TSETM 2 48 | -- Initialize table with function returning 2 constant return values 49 | do 50 | local function f() return 9, 10 end 51 | local t 52 | for i=1,100 do t = { 1, 2, 3, f() } end 53 | assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 9 and t[5] == 10 and 54 | t[6] == nil) 55 | end 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /test/lib/table/new.lua: -------------------------------------------------------------------------------- 1 | local tnew = require"table.new" 2 | 3 | do --- table.new 4 | local x, y 5 | for i=1,100 do 6 | x = tnew(100, 30) 7 | assert(type(x) == "table") 8 | if i == 90 then y = x end 9 | end 10 | assert(x ~= y) 11 | end 12 | -------------------------------------------------------------------------------- /test/lib/table/pack.lua: -------------------------------------------------------------------------------- 1 | do --- empty 2 | local t = table.pack() 3 | assert(type(t) == "table") 4 | assert(t.n == 0) 5 | assert(t[0] == nil) 6 | assert(t[1] == nil) 7 | end 8 | -------------------------------------------------------------------------------- /test/lib/table/remove.lua: -------------------------------------------------------------------------------- 1 | local tremove = table.remove 2 | local assert = assert 3 | 4 | do --- table.remove(t) removes correct entries 5 | local t = {} 6 | for i=1,200 do t[i] = i end 7 | for i=1,100 do tremove(t) end 8 | assert(#t == 100 and t[100] == 100) 9 | end 10 | 11 | do --- table.remove(t) returns the removed entry 12 | local t = {} 13 | for i=1,200 do t[i] = i end 14 | for i=1,100 do assert(tremove(t) == 201-i) end 15 | assert(#t == 100 and t[100] == 100) 16 | end 17 | 18 | do --- table.remove(t, 1) removes and returns the first entry 19 | local t = {} 20 | for i=1,200 do t[i] = i end 21 | for i=1,100 do assert(tremove(t, 1) == i) end 22 | assert(#t == 100 and t[100] == 200) 23 | end 24 | 25 | do --- TSETR hash part +table.new 26 | local tnew = require"table.new" 27 | local t = tnew(0, 16) 28 | for i=10,1,-1 do t[i] = i+3 end 29 | for i=10,1,-1 do assert(tremove(t) == i+3) end 30 | assert(#t == 0) 31 | end 32 | 33 | do --- TSETR write barrier +table.new 34 | local tnew = require"table.new" 35 | for _, t in ipairs{{}, tnew(0, 16)} do 36 | for i = 1, 10 do t[i] = {i} end 37 | for i = 1, 10 do 38 | collectgarbage() 39 | assert(tremove(t, 1)[1] == i) 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /test/lib/table/sort.lua: -------------------------------------------------------------------------------- 1 | -- Really a test for lua_lessthan() 2 | local N = 1000 3 | 4 | do --- numbers 5 | math.randomseed(42) 6 | local t = {} 7 | for i=1,N do t[i] = math.random(N) end 8 | table.sort(t) 9 | for i=2,N do assert(t[i-1] <= t[i]) end 10 | end 11 | 12 | do --- strings 13 | math.randomseed(42) 14 | local t = {} 15 | for i=1,N do t[i] = math.random(1, N/10).."" end 16 | table.sort(t) 17 | for i=2,N do assert(t[i-1] <= t[i]) end 18 | end 19 | 20 | do --- tables 21 | math.randomseed(42) 22 | local mt = { __lt = function(a,b) return a[1] < b[1] end } 23 | local t = {} 24 | for i=1,N do t[i] = setmetatable({ math.random(N) }, mt) end 25 | table.sort(t) 26 | for i=2,N do assert(t[i-1][1] <= t[i][1]) end 27 | end 28 | -------------------------------------------------------------------------------- /test/misc/alias_alloc.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local t = {1} 4 | local x 5 | for i=1,100 do 6 | local v = {i} 7 | t[1] = v[1] 8 | x = v[1] 9 | end 10 | assert(x == 100 and t[1] == 100) 11 | end 12 | 13 | do 14 | local t = {1} 15 | local x,y 16 | for i=1,100 do 17 | local v = {i} 18 | local w = {i+1} 19 | x = v[1] 20 | y = w[1] 21 | end 22 | assert(x == 100 and y == 101) 23 | end 24 | 25 | do 26 | local mt = {} 27 | local t = setmetatable({}, mt) 28 | local x 29 | for i=1,100 do 30 | local v = {} 31 | setmetatable(v, getmetatable(t)) 32 | assert(getmetatable(v) == mt) 33 | end 34 | end 35 | 36 | -- See also sink_alloc.lua 37 | do 38 | local x,k={1,2},{3,4} 39 | for i=1,100 do x = {x[1]+k[1], x[2]+k[2]} end 40 | assert(x[1] == 301) 41 | assert(x[2] == 402) 42 | end 43 | 44 | -- FLOAD for tab.asize/tab.array crossing NEWREF. 45 | do 46 | local t = {1} 47 | for i=1,100 do 48 | local v = {} 49 | local w = {} 50 | v[1] = t[1] 51 | w[1] = t[1] 52 | end 53 | end 54 | 55 | -------------------------------------------------------------------------------- /test/misc/api_call.lua: -------------------------------------------------------------------------------- 1 | local ctest = require("ctest") 2 | 3 | local function ret0() end 4 | local function ret1() return 1 end 5 | local function ret2() return 1,2 end 6 | local function ret3() return 1,2,3 end 7 | local function retva(...) return ... end 8 | local function ret1va(...) return 1,... end 9 | 10 | local function pack(...) 11 | return { n = select('#', ...), ... } 12 | end 13 | 14 | local function ck(res, ...) 15 | local ok = pack(...) 16 | if res.n ~= ok.n then error("nresults wrong: "..res.n.." ~= "..ok.n, 2) end 17 | for i=1,res.n do 18 | if res[i] ~= ok[i] then 19 | error("result["..i.."] wrong: "..tostring(res[i]).." ~= "..tostring(ok[i]), 2) 20 | end 21 | end 22 | end 23 | 24 | local function test_adjust_results(testfunc) 25 | 26 | local function cc(nres, f, ...) 27 | return pack(testfunc(nres, f, ...)) 28 | end 29 | 30 | ck(cc(0, ret0)) 31 | ck(cc(0, ret1)) 32 | ck(cc(0, ret2)) 33 | ck(cc(0, ret3)) 34 | ck(cc(0, retva)) 35 | 36 | ck(cc(1, ret0), nil) 37 | ck(cc(1, ret1), 1) 38 | ck(cc(1, ret2), 1) 39 | ck(cc(1, ret3), 1) 40 | ck(cc(1, retva), nil) 41 | ck(cc(1, retva, 1), 1) 42 | 43 | ck(cc(2, ret0), nil, nil) 44 | ck(cc(2, ret1), 1, nil) 45 | ck(cc(2, ret2), 1, 2) 46 | ck(cc(2, ret3), 1, 2) 47 | ck(cc(2, retva), nil, nil) 48 | ck(cc(2, retva, 1), 1, nil) 49 | ck(cc(2, retva, 1, 2), 1, 2) 50 | 51 | ck(cc(-1, ret0)) 52 | ck(cc(-1, ret1), 1) 53 | ck(cc(-1, ret2), 1, 2) 54 | ck(cc(-1, ret3), 1, 2, 3) 55 | ck(cc(-1, retva)) 56 | ck(cc(-1, retva, 1), 1) 57 | ck(cc(-1, retva, 1, 2), 1, 2) 58 | end 59 | 60 | test_adjust_results(ctest.call) 61 | test_adjust_results(ctest.pcall_err) 62 | 63 | 64 | local function gcshrink() 65 | for i=1,10 do collectgarbage() end 66 | end 67 | 68 | assert(select('#', ctest.call(2000, gcshrink)) == 2000) 69 | gcshrink() 70 | assert(select('#', ctest.call(7000, gcshrink)) == 7000) 71 | gcshrink() 72 | 73 | local function test_yield(resume, yield) 74 | local function inpcall() 75 | ck(pack(yield(6, 7)), 18, 19) 76 | end 77 | local co = coroutine.create(function(...) 78 | ck(pack(...), 11, 12) 79 | ck(pack(yield(1, 2))) 80 | ck(pack(yield()), 13, 14, 15) 81 | ck(pack(yield(3, 4, 5)), 16, 17) 82 | assert(pcall(inpcall) == true) 83 | return 8, 9 84 | end) 85 | 86 | ck(pack(resume(co, 11, 12)), true, 1, 2) 87 | ck(pack(resume(co)), true) 88 | ck(pack(resume(co, 13, 14, 15)), true, 3, 4, 5) 89 | ck(pack(resume(co, 16, 17)), true, 6, 7) 90 | ck(pack(resume(co, 18, 19)), true, 8, 9) 91 | assert(resume(co) == false) 92 | end 93 | 94 | test_yield(coroutine.resume, coroutine.yield) 95 | test_yield(ctest.resume, coroutine.yield) 96 | test_yield(coroutine.resume, ctest.yield) 97 | test_yield(ctest.resume, ctest.yield) 98 | 99 | -------------------------------------------------------------------------------- /test/misc/catch_wrap.lua: -------------------------------------------------------------------------------- 1 | 2 | local cp = require("cpptest") 3 | cp.wrapon() 4 | 5 | do 6 | local a, b = pcall(cp.catch, function() return "x" end) 7 | assert(a == true and b == "x") 8 | end 9 | 10 | do 11 | local a, b = pcall(function() cp.throw("foo") end) 12 | assert(a == false and b == "foo") 13 | end 14 | 15 | local unwind 16 | do 17 | local a, b = pcall(cp.catch, function() cp.throw("foo") end) 18 | unwind = a 19 | assert((a == false and b == "foo") or (a == true and b == "catch ...")) 20 | end 21 | 22 | do 23 | local st = cp.alloc(function() return cp.isalloc() end) 24 | assert(st == true) 25 | assert(cp.isalloc() == false) 26 | end 27 | 28 | do 29 | local a, b = pcall(cp.alloc, function() 30 | assert(cp.isalloc() == true) 31 | return "foo", cp.throw 32 | end) 33 | assert(a == false and b == "foo") 34 | assert(cp.isalloc() == false) 35 | end 36 | 37 | do 38 | local a, b = pcall(cp.alloc, function() 39 | assert(cp.isalloc() == true) 40 | return "foo", error 41 | end) 42 | assert(a == false and b == "foo") 43 | if unwind then assert(cp.isalloc() == false) end 44 | end 45 | 46 | -------------------------------------------------------------------------------- /test/misc/coro_traceback.lua: -------------------------------------------------------------------------------- 1 | 2 | local co = coroutine.create(function() 3 | local x = nil 4 | local y = x.x 5 | end) 6 | assert(coroutine.resume(co) == false) 7 | debug.traceback(co) 8 | 9 | -------------------------------------------------------------------------------- /test/misc/coro_yield.lua: -------------------------------------------------------------------------------- 1 | local create = coroutine.create 2 | local wrap = coroutine.wrap 3 | local resume = coroutine.resume 4 | local yield = coroutine.yield 5 | 6 | -- Test stack overflow handling on return from coroutine. 7 | do 8 | wrap(function() 9 | local co = create(function() 10 | yield(string.byte(string.rep(" ", 100), 1, 100)) 11 | end) 12 | assert(select('#', resume(co)) == 101) 13 | end)() 14 | end 15 | 16 | do 17 | wrap(function() 18 | local f = wrap(function() 19 | yield(string.byte(string.rep(" ", 100), 1, 100)) 20 | end) 21 | assert(select('#', f()) == 100) 22 | end)() 23 | end 24 | 25 | do 26 | local function cogen(x) 27 | return wrap(function(n) repeat x = x+n; n = yield(x) until false end), 28 | wrap(function(n) repeat x = x*n; n = yield(x) until false end) 29 | end 30 | 31 | local a,b=cogen(3) 32 | local c,d=cogen(5) 33 | assert(d(b(c(a(d(b(c(a(1)))))))) == 168428160) 34 | end 35 | 36 | do 37 | local function verify(what, expect, ...) 38 | local got = {...} 39 | for i=1,100 do 40 | if expect[i] ~= got[i] then 41 | error("FAIL " .. what) 42 | end 43 | if expect[i] == nil then 44 | break 45 | end 46 | end 47 | end 48 | 49 | local function cofunc(...) 50 | verify("call", { 1, "foo" }, ...) 51 | verify("yield", { "bar" }, yield(2, "test")) 52 | verify("pcall yield", { true, "again" }, pcall(yield, "from pcall")) 53 | return "end" 54 | end 55 | 56 | local co = create(cofunc) 57 | verify("resume", { true, 2, "test" }, resume(co, 1, "foo")) 58 | verify("resume pcall", { true, "from pcall" }, resume(co, "bar")) 59 | verify("resume end", { true, "end" }, resume(co, "again")) 60 | end 61 | 62 | do 63 | local function verify(expect, func, ...) 64 | local co = create(func) 65 | for i=1,100 do 66 | local ok, res = resume(co, ...) 67 | if not ok then 68 | if expect[i] ~= nil then 69 | error("too few results: ["..i.."] = "..tostring(expect[i]).." (got: "..tostring(res)..")") 70 | end 71 | break 72 | end 73 | if expect[i] ~= res then 74 | error("bad result: ["..i.."] = "..tostring(res).." (should be: "..tostring(expect[i])..")") 75 | end 76 | end 77 | end 78 | 79 | verify({ 42, 99 }, 80 | function(x) pcall(yield, x) return 99 end, 81 | 42) 82 | 83 | verify({ 42, 99 }, 84 | function(x) pcall(function(y) yield(y) end, x) return 99 end, 85 | 42) 86 | 87 | verify({ 42, 99 }, 88 | function(x) xpcall(yield, debug.traceback, x) return 99 end, 89 | 42) 90 | 91 | verify({ 45, 44, 43, 42, 99 }, 92 | function(x, y) 93 | for i in 94 | function(o, k) 95 | yield(o+k) 96 | if k ~= 0 then return k-1 end 97 | end,x,y do 98 | end 99 | return 99 100 | end, 101 | 42, 3) 102 | 103 | verify({ 84, 99 }, 104 | function(x) 105 | local o = setmetatable({ x }, 106 | {__add = function(a, b) yield(a[1]+b[1]) return 99 end }) 107 | return o+o 108 | end, 109 | 42) 110 | end 111 | 112 | -------------------------------------------------------------------------------- /test/misc/debug_gc.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Do not run this test unless the JIT compiler is turned off. 3 | if jit and jit.status and jit.status() then return end 4 | 5 | local caught, caught_line, caught_mm 6 | 7 | local function gcmeta() 8 | if caught ~= "end" then 9 | -- print(debug.traceback()) 10 | -- This may point to the wrong instruction if in a JIT trace. 11 | -- But there's no guarantee if, when or where any GC steps occur. 12 | local dbg = debug.getinfo(2) 13 | caught_line = dbg.currentline 14 | caught_mm = debug.getinfo(1).name 15 | caught = true 16 | end 17 | end 18 | 19 | local function testgc(mm, f) 20 | collectgarbage() 21 | caught = false 22 | local u = newproxy(true) 23 | getmetatable(u).__gc = gcmeta 24 | u = nil 25 | for i=1,100000 do 26 | f(i) 27 | -- This check may be hoisted. __gc is not supposed to have side-effects. 28 | if caught then break end 29 | end 30 | if not caught then 31 | error(mm.." metamethod not called", 2) 32 | end 33 | if type(caught_line) ~= "number" or caught_line < 0 then 34 | error("bad linenumber in debug info", 2) 35 | end 36 | if caught_mm ~= mm then 37 | error("bad name for metamethod in debug info", 2) 38 | end 39 | end 40 | 41 | local x 42 | testgc("__gc", function(i) x = {} end) 43 | testgc("__gc", function(i) x = {1} end) 44 | testgc("__gc", function(i) x = function() end end) 45 | testgc("__concat", function(i) x = i.."" end) 46 | 47 | caught = "end" 48 | -------------------------------------------------------------------------------- /test/misc/dualnum.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Positive overflow 3 | do 4 | local x = 0 5 | for i=2147483446,2147483647,2 do x = x + 1 end 6 | assert(x == 101) 7 | end 8 | 9 | -- Negative overflow 10 | do 11 | local x = 0 12 | for i=-2147483447,-2147483648,-2 do x = x + 1 end 13 | assert(x == 101) 14 | end 15 | 16 | -- SLOAD with number to integer conversion. 17 | do 18 | local k = 1 19 | local a, b, c = 1/k, 20/k, 1/k 20 | for i=1,20 do 21 | for j=a,b,c do end 22 | end 23 | end 24 | 25 | do 26 | local function fmin(a, b) 27 | for i=1,100 do a = math.min(a, b) end 28 | return a 29 | end 30 | local function fmax(a, b) 31 | for i=1,100 do a = math.max(a, b) end 32 | return a 33 | end 34 | assert(fmin(1, 3) == 1) 35 | assert(fmin(3, 1) == 1) 36 | assert(fmin(-1, 3) == -1) 37 | assert(fmin(3, -1) == -1) 38 | assert(fmin(-1, -3) == -3) 39 | assert(fmin(-3, -1) == -3) 40 | assert(fmax(1, 3) == 3) 41 | assert(fmax(3, 1) == 3) 42 | assert(fmax(-1, 3) == 3) 43 | assert(fmax(3, -1) == 3) 44 | assert(fmax(-1, -3) == -1) 45 | assert(fmax(-3, -1) == -1) 46 | end 47 | 48 | -------------------------------------------------------------------------------- /test/misc/for_dir.lua: -------------------------------------------------------------------------------- 1 | 2 | local a,b,c = 10,1,-1 3 | for i=1,20 do 4 | if c == -1 then 5 | a,b,c = 1,10,1 6 | else 7 | a,b,c = 10,1,-1 8 | end 9 | local x = 0 10 | for i=a,b,c do for j=1,10 do end x=x+1 end 11 | assert(x == 10) 12 | end 13 | 14 | -------------------------------------------------------------------------------- /test/misc/fori_coerce.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local n = 1 4 | local x = 0 5 | for i=1,20 do 6 | for j=n,100 do x = x + 1 end 7 | if i == 13 then n = "2" end 8 | end 9 | assert(x == 1993) 10 | end 11 | 12 | do 13 | local n = 1 14 | local x = 0 15 | for i=1,20 do 16 | for j=n,100 do x = x + 1 end 17 | if i == 10 then n = "2" end 18 | end 19 | assert(x == 1990) 20 | end 21 | 22 | do 23 | local function f() 24 | local n = 1 25 | local x = 0 26 | for i=1,20 do 27 | for j=n,100 do x = x + 1 end 28 | if i == 10 then n = "x" end 29 | end 30 | end 31 | assert(not pcall(f)) 32 | end 33 | 34 | -------------------------------------------------------------------------------- /test/misc/gc_rechain.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local k 4 | 5 | collectgarbage() 6 | 7 | local t = {} 8 | t.ac = 1 9 | 10 | t.nn = 1 11 | t.mm = 1 12 | t.nn = nil 13 | t.mm = nil 14 | 15 | k = "a".."i" 16 | t[k] = 2 17 | 18 | t.ad = 3 19 | 20 | t[k] = nil 21 | k = nil 22 | 23 | collectgarbage() 24 | 25 | k = "a".."f" 26 | t[k] = 4 27 | 28 | t.ak = 5 29 | 30 | assert(t[k] == 4) 31 | end 32 | 33 | -------------------------------------------------------------------------------- /test/misc/gc_trace.lua: -------------------------------------------------------------------------------- 1 | 2 | if not jit or not jit.status or not jit.status() then return end 3 | 4 | collectgarbage() 5 | for j=1,100 do 6 | loadstring("for i=1,100 do end")() 7 | end 8 | local jutil = require("jit.util") 9 | assert(jutil.traceinfo(90) == nil) 10 | collectgarbage() 11 | assert(jutil.traceinfo(1) == nil) 12 | assert(jutil.traceinfo(2) == nil) 13 | assert(jutil.traceinfo(3) == nil) 14 | 15 | do 16 | local f 17 | local function reccb(tr) 18 | if f == nil then 19 | collectgarbage() 20 | local info = jutil.traceinfo(tr) 21 | jutil.tracek(tr, -info.nk) 22 | -- Error in lj_ir_kvalue() if KGC not marked. 23 | -- Only caught with assertions or Valgrind. 24 | end 25 | end 26 | jit.attach(reccb, "record") 27 | for i=1,200 do 28 | if i % 5 == 0 then 29 | f = function() end 30 | elseif f then 31 | f() 32 | f = nil 33 | end 34 | end 35 | jit.attach(reccb) 36 | end 37 | 38 | -------------------------------------------------------------------------------- /test/misc/gcstep.lua: -------------------------------------------------------------------------------- 1 | 2 | local function testgc(what, func) 3 | collectgarbage() 4 | local oc = gcinfo() 5 | func() 6 | local nc = gcinfo() 7 | assert(nc < oc*4, "GC step missing for "..what) 8 | end 9 | 10 | testgc("TNEW", function() 11 | for i=1,10000 do 12 | local t = {} 13 | end 14 | end) 15 | 16 | testgc("TDUP", function() 17 | for i=1,10000 do 18 | local t = {1} 19 | end 20 | end) 21 | 22 | testgc("FNEW", function() 23 | for i=1,10000 do 24 | local function f() end 25 | end 26 | end) 27 | 28 | testgc("CAT", function() 29 | for i=1,10000 do 30 | local s = "x"..i 31 | end 32 | end) 33 | 34 | -------------------------------------------------------------------------------- /test/misc/hook_active.lua: -------------------------------------------------------------------------------- 1 | local ctest = require("ctest") 2 | 3 | local called = 0 4 | local function clearhook() debug.sethook(nil, "", 0) end 5 | 6 | -- Return from pcall with active hook must prepend true. FF pcall. 7 | called = 0 8 | debug.sethook(function() called=called+1; assert(pcall(function() end) == true); clearhook() end, "", 1) 9 | do local x = 1 end 10 | assert(called == 1) 11 | 12 | -- Hook with special caught error must not unblock hooks. FF pcall. 13 | called = 0 14 | debug.sethook(function() called=called+1; pcall(nil); clearhook() end, "", 1) 15 | do local x = 1 end 16 | assert(called == 1) 17 | 18 | -- Hook with caught error must not unblock hooks. FF pcall. 19 | called = 0 20 | local function p2() error("") end 21 | debug.sethook(function() called=called+1; pcall(p2); clearhook() end, "", 1) 22 | do local x = 1 end 23 | assert(called == 1) 24 | 25 | -- Hook with special caught error must not unblock hooks. C pcall. 26 | called = 0 27 | debug.sethook(function() called=called+1; ctest.pcall(nil); clearhook() end, "", 1) 28 | do local x = 1 end 29 | assert(called == 1) 30 | 31 | -- Hook with caught error must not unblock hooks. C pcall 32 | called = 0 33 | local function p2() error("") end 34 | debug.sethook(function() called=called+1; ctest.pcall(p2); clearhook() end, "", 1) 35 | do local x = 1 end 36 | assert(called == 1) 37 | 38 | -- Regular pcall must not block hooks. 39 | debug.sethook(function() called=called+1 end, "", 1) 40 | pcall(function() end) 41 | called = 0 42 | do local x = 1 end 43 | assert(called > 0) 44 | pcall(function() error("") end) 45 | called = 0 46 | do local x = 1 end 47 | assert(called > 0) 48 | ctest.pcall(function() end) 49 | called = 0 50 | do local x = 1 end 51 | assert(called > 0) 52 | ctest.pcall(function() error("") end) 53 | called = 0 54 | do local x = 1 end 55 | assert(called > 0) 56 | clearhook() 57 | 58 | -- Hook with uncaught error must unblock hooks. FF pcall 59 | called = 0 60 | pcall(function() 61 | debug.sethook(function() 62 | local old = called 63 | called = 1 64 | if old == 0 then error("") end 65 | end, "", 1) 66 | do local x = 1 end 67 | end) 68 | assert(called == 1) 69 | called = 2 70 | do local x = 1 end 71 | assert(called == 1, "hook not unblocked after uncaught error") 72 | clearhook() 73 | called = 2 74 | do local x = 1 end 75 | assert(called == 2) 76 | 77 | -- Hook with uncaught error must unblock hooks. C pcall 78 | called = 0 79 | ctest.pcall(function() 80 | debug.sethook(function() 81 | local old = called 82 | called = 1 83 | if old == 0 then error("") end 84 | end, "", 1) 85 | do local x = 1 end 86 | end) 87 | assert(called == 1) 88 | called = 2 89 | do local x = 1 end 90 | assert(called == 1, "hook not unblocked after uncaught error") 91 | clearhook() 92 | called = 2 93 | do local x = 1 end 94 | assert(called == 2) 95 | 96 | -------------------------------------------------------------------------------- /test/misc/hook_line.lua: -------------------------------------------------------------------------------- 1 | local lines = {} 2 | local function hook() 3 | lines[#lines+1] = debug.getinfo(2).currentline 4 | end 5 | 6 | local function dummy() 7 | end -- <-- line 7 8 | 9 | debug.sethook(hook, "l", 0) 10 | -- <-- line 10 11 | local x 12 | dummy() 13 | local y = 1 14 | dummy() dummy() 15 | local z = 2; local r = true 16 | while y < 4 do y = y + 1 end 17 | while z < 4 do 18 | z = z + 1 19 | end 20 | -- <-- line 20 21 | local v 22 | debug.sethook(nil, "", 0) 23 | 24 | assert(#lines > 0) 25 | while lines[1] < 10 do table.remove(lines, 1) end 26 | while lines[#lines] > 20 do table.remove(lines) end 27 | 28 | local s = table.concat(lines, " ") 29 | assert(s == "11 12 7 13 14 7 7 15 16 16 16 16 17 18 17 18 17" or 30 | s == "11 12 7 13 14 7 14 7 15 16 16 16 16 17 18 17 18 17") 31 | 32 | lines = {} 33 | local function f() 34 | if true then return end 35 | local function x() end 36 | end -- <-- line 36 37 | debug.sethook(hook, "l", 0) 38 | f() 39 | debug.sethook(nil, "", 0) 40 | for i=1,#lines do assert(lines[i] ~= 36) end 41 | 42 | -------------------------------------------------------------------------------- /test/misc/hook_norecord.lua: -------------------------------------------------------------------------------- 1 | 2 | if not jit or not jit.status or not jit.status() then return end 3 | 4 | local called = false 5 | local function f() local x = "wrong"; called = true end 6 | jit.off(f) 7 | debug.sethook(f, "", 5) 8 | for i=1,1000 do local a,b,c,d,e,f=1,2,3,4,5,6 end 9 | assert(called) 10 | -- Check that no trace was generated. 11 | assert(require("jit.util").traceinfo(1) == nil) 12 | 13 | -------------------------------------------------------------------------------- /test/misc/hook_record.lua: -------------------------------------------------------------------------------- 1 | 2 | if not jit or not jit.status or not jit.status() then return end 3 | 4 | debug.sethook(function() for i=1,100 do end end, "", 10) 5 | for i=1,10 do end 6 | debug.sethook() 7 | assert((require("jit.util").traceinfo(1))) 8 | 9 | -------------------------------------------------------------------------------- /test/misc/hook_top.lua: -------------------------------------------------------------------------------- 1 | 2 | local t = {} 3 | for i=1,26 do t[i] = string.char(96+i) end 4 | 5 | local function tcheck(t1, t2) 6 | assert(#t1 == #t2) 7 | for i=1,#t1 do assert(t1[i] == t2[i]) end 8 | end 9 | 10 | local function foo1(...) -- VARG RETM 11 | return ... 12 | end 13 | 14 | local function foo2(...) -- VARG UCLO RETM 15 | local function dummy() end 16 | return ... 17 | end 18 | 19 | local function foo3(...) -- VARG UCLO -> RETM 20 | do return ... end 21 | local function dummy() end 22 | end 23 | 24 | local function foo4() -- UCLO UCLO RET 25 | do 26 | local x 27 | local function dummy() return x end 28 | end 29 | end 30 | 31 | called = false 32 | debug.sethook(function() local x = "wrong"; called = true end, "", 1) 33 | tcheck(t, {foo1(unpack(t))}) -- CALLM TSETM 34 | assert(called) 35 | called = false 36 | tcheck(t, {foo2(unpack(t))}) 37 | assert(called) 38 | called = false 39 | tcheck(t, {foo2(unpack(t))}) 40 | assert(called) 41 | called = false 42 | foo4() 43 | assert(called) 44 | 45 | debug.sethook(function() 46 | local name, val = debug.getlocal(2, 1) 47 | assert(name == "a" and val == nil) 48 | debug.setlocal(2, 1, "bar") 49 | debug.sethook(nil) 50 | end, "c") 51 | local function foo5(a) 52 | assert(a == "bar") 53 | end 54 | foo5() 55 | 56 | -------------------------------------------------------------------------------- /test/misc/jit_flush.lua: -------------------------------------------------------------------------------- 1 | 2 | if not jit or not jit.status or not jit.status() then return end 3 | 4 | for i=1,100 do 5 | if i==50 then jit.flush(2) end 6 | for j=1,100 do end 7 | for j=1,100 do end 8 | end 9 | 10 | jit.flush() 11 | 12 | local function f() for i=1,100 do end end 13 | for i=1,100 do local x = gcinfo(); f() end 14 | 15 | jit.flush() 16 | 17 | local function fib(n) 18 | if n < 2 then return 1 end 19 | return fib(n-2) + fib(n-1) 20 | end 21 | 22 | fib(11) 23 | 24 | jit.flush() 25 | 26 | local names = {} 27 | for i=1,100 do names[i] = i end 28 | 29 | function f() 30 | for k,v in ipairs(names) do end 31 | end 32 | 33 | f() 34 | 35 | for i=1,2 do 36 | f() 37 | f() 38 | jit.flush() 39 | end 40 | 41 | jit.flush() 42 | 43 | jit.flush(1) -- ignored 44 | jit.flush(2) -- ignored 45 | for i=1,1e7 do end -- causes trace #1 46 | 47 | jit.flush(2) -- ignored 48 | jit.flush(1) -- ok 49 | jit.flush(1) -- crashes 50 | 51 | -------------------------------------------------------------------------------- /test/misc/lightud.lua: -------------------------------------------------------------------------------- 1 | local ctest = require("ctest") 2 | 3 | local lightud = ctest.lightud 4 | local assert = assert 5 | 6 | -- x64 lightud tests 7 | if jit and jit.arch == "x64" then 8 | do 9 | local ud1 = lightud(0x12345678) 10 | local ud2 = lightud(0x12345678) 11 | assert(ud1 == ud2) 12 | assert(tostring(ud1) == "userdata: 0x12345678") 13 | end 14 | do 15 | local ud1 = lightud(1) 16 | local ud2 = lightud(2) 17 | assert(ud1 ~= ud2) 18 | end 19 | do 20 | local ud1 = lightud(2^47-1) 21 | local ud2 = lightud(2^47-1) 22 | assert(ud1 == ud2) 23 | assert(tostring(ud1) == "userdata: 0x7fffffffffff") 24 | end 25 | do 26 | local ud1 = lightud(0x12345678+123*2^32) 27 | local ud2 = lightud(0x12345678+456*2^32) 28 | for i=1,100 do assert(ud1 ~= ud2) end 29 | end 30 | assert(tostring(lightud(0x5abc*2^32 + 0xdef01234)) == "userdata: 0x5abcdef01234") 31 | assert(pcall(lightud, 2^47) == false) 32 | assert(pcall(lightud, 2^64-2048) == false) 33 | end 34 | 35 | assert(getmetatable(lightud(1)) == nil) 36 | 37 | -- lightuserdata SLOAD value and HREF key 38 | do 39 | local ud = lightud(12345) 40 | local t = {[ud] = 42} 41 | for i=1,100 do 42 | assert(t[ud] == 42) 43 | end 44 | end 45 | 46 | -- lightuserdata NEWREF key 47 | do 48 | local ud = lightud(12345) 49 | for i=1,100 do 50 | local t = {[ud] = 42} 51 | assert(t[ud] == 42) 52 | end 53 | end 54 | 55 | -- lightuserdata ASTORE/HSTORE value 56 | do 57 | local ud = lightud(12345) 58 | local t = {} 59 | for i=1,100 do 60 | t[i] = ud 61 | end 62 | assert(t[100] == ud) 63 | end 64 | 65 | -- lightuserdata sync to stack 66 | do 67 | local ud = lightud(12345) 68 | local x = nil 69 | for j=1,20 do 70 | for i=1,50 do 71 | x = ud 72 | end 73 | assert(x == ud) 74 | end 75 | end 76 | 77 | -- lightuserdata vs. number type check 78 | do 79 | local t = {} 80 | for i=1,200 do t[i] = i end 81 | t[180] = lightud(12345) 82 | local x = 0 83 | assert(not pcall(function(t) 84 | for i=1,200 do x = x + t[i] end 85 | end, t)) 86 | assert(x == 16110) 87 | end 88 | 89 | -------------------------------------------------------------------------------- /test/misc/loop_unroll.lua: -------------------------------------------------------------------------------- 1 | 2 | -- type instability on loop unroll -> record unroll 3 | do 4 | local flip = true 5 | for i=1,100 do flip = not flip end 6 | assert(flip == true) 7 | end 8 | 9 | do 10 | local t = {} 11 | local a, b, c = 1, "", t 12 | for i=1,100 do a,b,c=b,c,a end 13 | assert(c == 1 and a == "" and b == t) 14 | end 15 | 16 | -- FAILFOLD on loop unroll -> LJ_TRERR_GFAIL -> record unroll 17 | do 18 | local t = { 1, 2 } 19 | local k = 2 20 | local x = 0 21 | for i=1,200 do 22 | x = x + t[k] 23 | k = k == 1 and 2 or 1 24 | end 25 | assert(x == 300 and k == 2) 26 | end 27 | 28 | -- Unroll if inner loop aborts. 29 | local j = 0 30 | for i = 1,100 do 31 | repeat 32 | j = j+1 33 | until true 34 | end 35 | 36 | -------------------------------------------------------------------------------- /test/misc/parse_comp.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local f = {{n=5}} 4 | local a = f[1].n 5 | assert(1 < a) 6 | assert(1 < (f[1].n)) 7 | assert(1 < f[1].n) 8 | end 9 | 10 | do 11 | tt = { a = 1 } 12 | assert(not(0 >= tt.a)) 13 | end 14 | -------------------------------------------------------------------------------- /test/misc/parse_esc.lua: -------------------------------------------------------------------------------- 1 | assert("\79\126" == "O~") 2 | assert("\x4f\x7e" == "O~") 3 | assert(loadstring[[return "\xxx"]] == nil) 4 | assert(loadstring[[return "\xxx"]] == nil) 5 | assert(assert(loadstring[[return "abc \z 6 | 7 | def"]])() == "abc def") 8 | -------------------------------------------------------------------------------- /test/misc/parse_misc.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Ambiguous syntax: function call vs. new statement. 3 | if os.getenv("LUA52") then 4 | assert(assert(loadstring([[ 5 | local function f() return 99 end 6 | return f 7 | () 8 | ]]))() == 99) 9 | else 10 | assert(loadstring([[ 11 | local function f() return 99 end 12 | return f 13 | () 14 | ]]) == nil) 15 | end 16 | 17 | -- UTF-8 identifiers. 18 | assert(loadstring([[ 19 | local ä = 1 20 | local aäa = 2 21 | local äöü·€晶 = 3 22 | 23 | assert(ä == 1) 24 | assert(aäa == 2) 25 | assert(äöü·€晶 == 3) 26 | 27 | assert(#"ä" == 2) 28 | assert(#"aäa" == 4) 29 | assert(#"äöü·€晶" == 14) 30 | ]]))() 31 | 32 | -------------------------------------------------------------------------------- /test/misc/phi_conv.lua: -------------------------------------------------------------------------------- 1 | 2 | local bit = require("bit") 3 | 4 | local Rm = {} 5 | for i=0,16 do Rm[i] = 0 end 6 | 7 | for k=1,10 do 8 | local seed = 1 9 | for i=16,0,-1 do 10 | seed = bit.band(seed*9069, 0x7fffffff) 11 | Rm[i] = seed 12 | end 13 | assert(seed == 1952688301) 14 | end 15 | 16 | local retindex = 0 17 | local retdata = { 3, 1, 1, 1, 0, 3, 1, 0, 0, 2, 0, 2, 0, 0, 3, 1, 1, 1, 1 } 18 | 19 | local function get_bits() 20 | retindex = retindex + 1 21 | return retdata[retindex] 22 | end 23 | 24 | local hufcodes = { [0] = true, [4] = true, [11] = true, [36] = true, [68] = true } 25 | 26 | local maskhuf = { 0x0002, 0x0003, 0x0004, 0x0005, } 27 | 28 | local function decodeCode() 29 | local lookup = get_bits() 30 | local code = hufcodes[lookup] 31 | local z = {1,1,1,1} 32 | if not code then 33 | for i = 1, 4 do 34 | lookup = bit.bor(lookup, bit.lshift(get_bits(), i + 1)) 35 | -- need PHI for CONV num.int of lookup, used in snapshot 36 | code = hufcodes[lookup + maskhuf[i]] 37 | if code then break end 38 | end 39 | end 40 | assert(code) 41 | return code 42 | end 43 | 44 | local function test() 45 | for i = 1, 6 do 46 | decodeCode() 47 | end 48 | end 49 | 50 | if jit and jit.status and jit.status() then jit.opt.start("hotloop=1") end 51 | 52 | test() 53 | 54 | -------------------------------------------------------------------------------- /test/misc/recurse_deep.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local function sum(n) 4 | if n == 1 then return 1 end 5 | return n + sum(n-1) 6 | end 7 | assert(sum(200) == 20100) 8 | end 9 | 10 | do 11 | local pcall = pcall 12 | local tr1 13 | local x = 0 14 | function tr1(n) 15 | if n <= 0 then return end 16 | x = x + 1 17 | return pcall(tr1, n-1) 18 | end 19 | assert(tr1(200) == true and x == 200) 20 | end 21 | 22 | do 23 | local function fib(n) 24 | if n < 2 then return 1 end 25 | return fib(n-2) + fib(n-1) 26 | end 27 | assert(fib(15) == 987) 28 | end 29 | 30 | -------------------------------------------------------------------------------- /test/misc/recurse_tail.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local tr1 4 | function tr1(n) 5 | if n <= 0 then return 0 end 6 | return tr1(n-1) 7 | end 8 | assert(tr1(200) == 0) 9 | end 10 | 11 | do 12 | local tr1, tr2 13 | function tr1(n) 14 | if n <= 0 then return 0 end 15 | return tr2(n-1) 16 | end 17 | function tr2(n) 18 | return tr1(n) 19 | end 20 | assert(tr2(200) == 0) 21 | end 22 | 23 | -------------------------------------------------------------------------------- /test/misc/stack_gc.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local t = setmetatable({}, { __index=function(t, k) 4 | k = k - 1 5 | if k == 0 then 6 | collectgarbage() -- Mark stack, including holes. 7 | return 0 8 | else 9 | return t[k] -- Leaves holes in each frame. 10 | end 11 | do local a,b,c,d,e,f,g,h,i,j,k,l,m,n end -- Ensure bigger frame size. 12 | end}) 13 | local x = t[50] 14 | end 15 | 16 | -------------------------------------------------------------------------------- /test/misc/stack_purge.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Must preserve the modified function slot in the RET snapshot. 3 | local function a() 4 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 5 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 6 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 7 | return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8 | end 9 | 10 | local function b() 11 | return a() 12 | end 13 | 14 | local function c() 15 | for j=1,10 do 16 | for i=1,50 do b() b() b() end 17 | collectgarbage() 18 | local t = {} 19 | for i=1,50 do t = {t} end 20 | end 21 | end 22 | 23 | jit.off(c) 24 | c() 25 | 26 | -------------------------------------------------------------------------------- /test/misc/stackov.lua: -------------------------------------------------------------------------------- 1 | 2 | local function f() 3 | f() 4 | end 5 | 6 | local err, s = xpcall(f, debug.traceback) 7 | assert(err == false) 8 | 9 | local first = string.match(s, "[^\n]+") 10 | local line = debug.getinfo(f, "S").linedefined+1 11 | assert(string.match(first, ":"..line..": stack overflow$")) 12 | 13 | local n = 1 14 | for _ in string.gmatch(s, "\n") do n = n + 1 end 15 | assert(n == 1+1+11+1+10) 16 | 17 | local function g(i) 18 | g(i) 19 | end 20 | 21 | local err, s = xpcall(g, debug.traceback, 1) 22 | assert(err == false) 23 | 24 | --[[ 25 | -- too slow 26 | local function vtail(...) 27 | return vtail(1, ...) 28 | end 29 | 30 | local err, s = xpcall(vtail, debug.traceback, 1) 31 | assert(err == false) 32 | --]] 33 | 34 | local function vcall(...) 35 | vcall(1, ...) 36 | end 37 | 38 | local err, s = xpcall(vcall, debug.traceback, 1) 39 | assert(err == false) 40 | 41 | -------------------------------------------------------------------------------- /test/misc/stackovc.lua: -------------------------------------------------------------------------------- 1 | local j = 1e4 2 | local co = coroutine.create(function() t = {} for i = 1, j do t[i] = i end return unpack(t) end) 3 | local ok, err = coroutine.resume(co) 4 | assert(not ok and string.find(err, "unpack")) 5 | -------------------------------------------------------------------------------- /test/misc/tcall_base.lua: -------------------------------------------------------------------------------- 1 | 2 | local r = 0 3 | local function g() 4 | r = r + 1 5 | for i=1,100 do end 6 | end 7 | 8 | local function f() 9 | for j=1,20 do 10 | if j > 19 then 11 | return g() -- Tailcall at base. 12 | -- Let this link to the already compiled loop in g(). 13 | end 14 | end 15 | end 16 | 17 | g() -- Compile this loop first. 18 | for i=1,50 do f() end 19 | assert(r == 51) 20 | 21 | -------------------------------------------------------------------------------- /test/misc/tcall_loop.lua: -------------------------------------------------------------------------------- 1 | local function f(i) 2 | if i > 0 then return f(i-1) end 3 | return 1 4 | end 5 | 6 | local x = 0 7 | for i=1,100 do x = x + f(1000) end 8 | assert(x == 100) 9 | -------------------------------------------------------------------------------- /test/misc/uclo.lua: -------------------------------------------------------------------------------- 1 | 2 | local function test_for() 3 | local z1, z2 4 | for i=1,10 do 5 | local function f() return i end 6 | if z1 then z2 = f else z1 = f end 7 | end 8 | assert(z1() == 1) 9 | assert(z2() == 10) 10 | end 11 | 12 | local function test_while() 13 | local z1, z2 14 | local i = 1 15 | while i <= 10 do 16 | local j = i 17 | local function f() return j end 18 | if z1 then z2 = f else z1 = f end 19 | i = i + 1 20 | end 21 | assert(z1() == 1) 22 | assert(z2() == 10) 23 | end 24 | 25 | local function test_repeat() 26 | local z1, z2 27 | local i = 1 28 | repeat 29 | local j = i 30 | local function f() return j end 31 | if z1 then z2 = f else z1 = f end 32 | i = i + 1 33 | until i > 10 34 | assert(z1() == 1) 35 | assert(z2() == 10) 36 | end 37 | 38 | local function test_func() 39 | local function ff(x) 40 | return function() return x end 41 | end 42 | local z1, z2 43 | for i=1,10 do 44 | local f = ff(i) 45 | if z1 then z2 = f else z1 = f end 46 | end 47 | assert(z1() == 1) 48 | assert(z2() == 10) 49 | end 50 | 51 | test_for() 52 | test_while() 53 | test_repeat() 54 | test_func() 55 | 56 | do 57 | local function f1(a) 58 | if a > 0 then 59 | local b = f1(a - 1) 60 | return function() 61 | if type(b) == "function" then 62 | return a + b() 63 | end 64 | return a + b 65 | end 66 | end 67 | return a 68 | end 69 | 70 | local function f2(a) 71 | return f1(a)() 72 | end 73 | 74 | for i = 1, 41 do 75 | local r = f2(4) + f2(4) 76 | end 77 | end 78 | 79 | -- Don't mark upvalue as immutable if written to after prototype definition. 80 | do 81 | local x = 1 82 | local function f() 83 | local y = 0 84 | for i=1,100 do y=y+x end 85 | return y 86 | end 87 | assert(f() == 100) 88 | x = 2 89 | assert(f() == 200) 90 | end 91 | 92 | -------------------------------------------------------------------------------- /test/misc/wbarrier.lua: -------------------------------------------------------------------------------- 1 | local t={} 2 | for i=1,20000 do 3 | t[i] = tostring(i) 4 | end 5 | for i=1,#t do 6 | assert(t[i] == tostring(i)) 7 | end 8 | -------------------------------------------------------------------------------- /test/misc/wbarrier_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local t = {[0]={}} 4 | for i=1,1e5 do t[i] = {t[i-1]} end 5 | for i=1,1e5 do assert(t[i][1] == t[i-1]) end 6 | end 7 | 8 | do 9 | local f 10 | do 11 | local x = 0 12 | function f() 13 | for i=1,1e5 do x = {i} end 14 | end 15 | end 16 | f() 17 | end 18 | 19 | -------------------------------------------------------------------------------- /test/misc/wbarrier_obar.lua: -------------------------------------------------------------------------------- 1 | -- DSE of USTORE must eliminate OBAR, too. 2 | 3 | if jit and jit.opt then pcall(jit.opt.start, "-sink") end 4 | 5 | local f 6 | do 7 | local x 8 | f = function() 9 | local y = 0 10 | for i=1,10000 do 11 | x = {1} 12 | if y > 0 then end 13 | x = 1 14 | end 15 | end 16 | end 17 | 18 | collectgarbage() 19 | collectgarbage("setstepmul", 1) 20 | collectgarbage("restart") 21 | f() 22 | 23 | -------------------------------------------------------------------------------- /test/opt/dse/field.lua: -------------------------------------------------------------------------------- 1 | local getmetatable, setmetatable = getmetatable, setmetatable 2 | 3 | do --- 1. Store with same ref and same value. All stores in loop eliminated. 4 | local mt = {} 5 | local t = {} 6 | for i=1,100 do 7 | setmetatable(t, mt) 8 | assert(getmetatable(t) == mt) 9 | setmetatable(t, mt) 10 | assert(getmetatable(t) == mt) 11 | end 12 | assert(getmetatable(t) == mt) 13 | end 14 | 15 | do --- 2. Store with different ref and same value. All stores in loop eliminated. 16 | local mt = {} 17 | local t1 = {} 18 | local t2 = {} 19 | for i=1,100 do 20 | setmetatable(t1, mt) 21 | assert(getmetatable(t1) == mt) 22 | setmetatable(t2, mt) 23 | assert(getmetatable(t2) == mt) 24 | end 25 | assert(getmetatable(t1) == mt) 26 | assert(getmetatable(t2) == mt) 27 | end 28 | 29 | do --- 3. Store with different ref and different value. Cannot eliminate any stores. 30 | local mt1 = {} 31 | local mt2 = {} 32 | local t1 = {} 33 | local t2 = {} 34 | for i=1,100 do 35 | setmetatable(t1, mt1) 36 | assert(getmetatable(t1) == mt1) 37 | setmetatable(t2, mt2) 38 | assert(getmetatable(t2) == mt2) 39 | end 40 | assert(getmetatable(t1) == mt1) 41 | assert(getmetatable(t2) == mt2) 42 | end 43 | 44 | do --- 4. Store with same ref and different value. 2nd store remains in loop. 45 | local mt1 = {} 46 | local mt2 = {} 47 | local t = {} 48 | for i=1,100 do 49 | setmetatable(t, mt1) 50 | assert(getmetatable(t) == mt1) 51 | setmetatable(t, mt2) 52 | assert(getmetatable(t) == mt2) 53 | end 54 | assert(getmetatable(t) == mt2) 55 | end 56 | 57 | do --- 5. Store with same ref, different value and aliased loads. 58 | -- Cannot eliminate any stores. 59 | local mt1 = {} 60 | local mt2 = {} 61 | local t1 = {} 62 | local t2 = t1 63 | for i=1,100 do 64 | setmetatable(t1, mt1) 65 | assert(getmetatable(t2) == mt1) 66 | setmetatable(t1, mt2) 67 | assert(getmetatable(t2) == mt2) 68 | end 69 | assert(getmetatable(t1) == mt2) 70 | end 71 | -------------------------------------------------------------------------------- /test/opt/dse/index: -------------------------------------------------------------------------------- 1 | array.lua 2 | field.lua 3 | -------------------------------------------------------------------------------- /test/opt/fold/index: -------------------------------------------------------------------------------- 1 | kfold.lua 2 | -------------------------------------------------------------------------------- /test/opt/fuse.lua: -------------------------------------------------------------------------------- 1 | do --- Don't fuse i+101 on x64. 2 | -- (except if i is sign-extended to 64 bit or addressing is limited to 32 bit) 3 | local t = {} 4 | for i=-100,-1 do t[i+101] = 1 end 5 | end 6 | -------------------------------------------------------------------------------- /test/opt/fwd/hrefk_rollback.lua: -------------------------------------------------------------------------------- 1 | do --- https://github.com/LuaJIT/LuaJIT/issues/124 2 | local function foo(a, b, f) 3 | return f and (a.f0 < b.f1 and 4 | b.f0 < a.f1 and 5 | a.f2 < b.f3 and 6 | b.f2 < a.f3) 7 | end 8 | 9 | local function bar(f0, f1, f2, f3, X, f) 10 | for _, v in ipairs(X) do 11 | local b = {} 12 | b.f0 = 0 13 | b.f2 = v 14 | b.f1 = b.f0 + 1 15 | b.f3 = b.f2 + 1 16 | 17 | if foo({f0 = f0, f1 = f1, f2 = f2, f3 = f3}, b, f) then 18 | return false 19 | end 20 | end 21 | 22 | return true 23 | end 24 | 25 | local X = { 0, 1, 0, 0 } 26 | 27 | for i = 1, 20 do 28 | assert(bar(0, 1, 2, 3, X, true)) 29 | end 30 | 31 | assert(not bar(0, 1, 1, 2, X, true)) 32 | end 33 | -------------------------------------------------------------------------------- /test/opt/fwd/index: -------------------------------------------------------------------------------- 1 | hrefk_rollback.lua 2 | tnew_tdup.lua 3 | upval.lua 4 | -------------------------------------------------------------------------------- /test/opt/fwd/tnew_tdup.lua: -------------------------------------------------------------------------------- 1 | do --- 1. 2 | local x = 2 3 | for i=1,100 do 4 | local t = {} -- TNEW: DCE 5 | x = t.foo -- HREF -> niltv: folded 6 | end 7 | assert(x == nil) 8 | end 9 | 10 | do --- 2. 11 | local x = 2 12 | for i=1,100 do 13 | local t = {1} -- TDUP: DCE 14 | x = t.foo -- HREF -> niltv: folded 15 | end 16 | assert(x == nil) 17 | end 18 | 19 | do --- 3. 20 | local x = 2 21 | for i=1,100 do 22 | local t = {} 23 | t[1] = 11 -- NEWREF + HSTORE 24 | x = t[1] -- AREF + ALOAD, no forwarding, no fold 25 | end 26 | assert(x == 11) 27 | end 28 | 29 | do --- 4. HREFK not eliminated. Ditto for the EQ(FLOAD(t, #tab.hmask), k). 30 | local x = 2 31 | for i=1,100 do 32 | local t = {} 33 | t.foo = 11 -- NEWREF + HSTORE 34 | x = t.foo -- HREFK + HLOAD: store forwarding 35 | end 36 | assert(x == 11) 37 | end 38 | 39 | do --- 5. HREFK not eliminated. Ditto for the EQ(FLOAD(t, #tab.hmask), k). 40 | local x = 2 41 | for i=1,100 do 42 | local t = {foo=11} -- TDUP 43 | x = t.foo -- HREFK + non-nil HLOAD: folded 44 | end 45 | assert(x == 11) 46 | end 47 | 48 | do --- 6. 49 | local x = 2 50 | local k = 1 51 | for i=1,100 do 52 | local t = {[0]=11} -- TDUP 53 | t[k] = 22 -- AREF + ASTORE aliasing 54 | x = t[0] -- AREF + ALOAD, no fold 55 | end 56 | assert(x == 11) 57 | end 58 | 59 | do --- 7. 60 | local setmetatable = setmetatable 61 | local mt = { __newindex = function(t, k, v) 62 | assert(k == "foo") 63 | assert(v == 11) 64 | end } 65 | for i=1,100 do 66 | local t = setmetatable({}, mt) 67 | t.foo = 11 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /test/opt/fwd/upval.lua: -------------------------------------------------------------------------------- 1 | do --- 1. Open upvalue above base slot, aliasing an SSA value. 2 | local x = 7 3 | local function a() x = x + 1 end 4 | local function b() x = x + 2 end 5 | for i=1,100 do a(); b(); x = x + 5 end 6 | assert(x == 807) 7 | end 8 | 9 | do --- 2. Open upvalue below base slot. UREFO CSE for a.x + b.x, but not x in loop. 10 | -- ULOAD not disambiguated. 2x ULOAD + 2x USTORE (+ 1x DSE USTORE). 11 | local x = 7 12 | (function() 13 | local function a() x = x + 1 end 14 | local function b() x = x + 2 end 15 | for i=1,100 do a(); b(); x = x + 5 end 16 | end)() 17 | assert(x == 807) 18 | end 19 | 20 | do --- 3. Closed upvalue. UREFC CSE for a.x + b.x, but not x in loop. 21 | -- ULOAD not disambiguated. 2x ULOAD + 2x USTORE (+ 1x DSE for USTORE). 22 | local xx = (function() 23 | local x = 7 24 | local function a() x = x + 1 end 25 | local function b() x = x + 2 end 26 | return function() for i=1,100 do a(); b(); x = x + 5 end; return x end 27 | end)()() 28 | assert(xx == 807) 29 | end 30 | 31 | do --- 4. Open upvalue below base slot. Forwarded. 1x USTORE (+ 1x DSE USTORE). 32 | local x = 7 33 | (function() 34 | local function a() x = x + 1 end 35 | for i=1,100 do a(); a() end 36 | end)() 37 | assert(x == 207) 38 | end 39 | 40 | do --- 5. Closed upvalue. Forwarded. 1x USTORE (+ 1x DSE USTORE). 41 | local xx = (function() 42 | local x = 7 43 | return function() 44 | local function a() x = x + 1 end 45 | for i=1,100 do a(); a() end 46 | return x 47 | end 48 | end)()() 49 | assert(xx == 207) 50 | end 51 | -------------------------------------------------------------------------------- /test/opt/index: -------------------------------------------------------------------------------- 1 | dse +dse 2 | fold +fold 3 | fwd +fwd 4 | fuse.lua +fuse 5 | loop +loop 6 | sink +sink 7 | -------------------------------------------------------------------------------- /test/opt/loop/index: -------------------------------------------------------------------------------- 1 | unroll.lua 2 | -------------------------------------------------------------------------------- /test/opt/loop/unroll.lua: -------------------------------------------------------------------------------- 1 | do --- type instability on loop unroll -> record unroll 2 | local flip = true 3 | for i=1,100 do flip = not flip end 4 | assert(flip == true) 5 | end 6 | 7 | do --- untitled 8 | local t = {} 9 | local a, b, c = 1, "", t 10 | for i=1,100 do a,b,c=b,c,a end 11 | assert(c == 1 and a == "" and b == t) 12 | end 13 | 14 | do --- FAILFOLD on loop unroll -> LJ_TRERR_GFAIL -> record unroll 15 | local t = { 1, 2 } 16 | local k = 2 17 | local x = 0 18 | for i=1,200 do 19 | x = x + t[k] 20 | k = k == 1 and 2 or 1 21 | end 22 | assert(x == 300 and k == 2) 23 | end 24 | 25 | do --- Unroll if inner loop aborts. 26 | local j = 0 27 | for i = 1,100 do 28 | repeat 29 | j = j+1 30 | until true 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /test/opt/sink/ffi_nosink.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do --- escaping global !private_G 4 | local x = 0ll 5 | for i=1,100 do x=x+1; g=x end 6 | assert(x == 100ll) 7 | assert(g == 100ll) 8 | end 9 | 10 | do --- preincrement escaping global !private_G 11 | local x = 0ll 12 | for i=1,100 do local y=x; x=x+1; g=y end 13 | assert(x == 100ll) 14 | assert(g == 99ll) 15 | end 16 | 17 | do --- escaping global and local !private_G 18 | local x = 0ll 19 | local z 20 | for i=1,100 do z=x+1; g=z end 21 | assert(z == 1ll) 22 | assert(g == 1ll) 23 | end 24 | 25 | do --- swapping 26 | local x,y = 0ll, 0ll 27 | for i=1,100 do y,x=x,x+1 end 28 | assert(x == 100ll) 29 | assert(y == 99ll) 30 | end 31 | 32 | do --- pointer to self 33 | local st = ffi.typeof("struct { void *p; }") 34 | local x 35 | for i=1,100 do x = st(); x.p = x end 36 | assert(x.p == ffi.cast("void *", x)) 37 | end 38 | 39 | do --- strchr 40 | ffi.cdef[[char *strchr(char *, int);]] 41 | for i=1,100 do 42 | local p = ffi.new("char[2]"); 43 | ffi.C.strchr(p, 32) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/opt/sink/index: -------------------------------------------------------------------------------- 1 | alloc.lua 2 | nosink.lua 3 | ffi.lua +ffi 4 | ffi_nosink.lua +ffi 5 | -------------------------------------------------------------------------------- /test/opt/sink/nosink.lua: -------------------------------------------------------------------------------- 1 | local assert = assert 2 | 3 | do --- Cannot sink TNEW, aliased load. 4 | local k = 1 5 | for i=1,100 do local t={i}; assert(t[k]==i) end 6 | for i=1,100 do local t={}; t[k]=i; assert(t[1]==i) end 7 | end 8 | 9 | do --- Cannot sink TNEW, escaping to upvalue. 10 | (function() 11 | local uv 12 | return function() 13 | for i=1,100 do uv = {i} end 14 | assert(uv[1] == 100) 15 | end 16 | end)()() 17 | end 18 | 19 | do --- Cannot sink TNEW, escaping through a store. 20 | local t = {} 21 | for i=1,100 do t[1] = {i} end 22 | for i=1,100 do t.foo = {i} end 23 | for i=1,100 do setmetatable(t, {i}) end 24 | assert(t[1][1] == 100) 25 | assert(t.foo[1] == 100) 26 | assert(getmetatable(t)[1] == 100) 27 | end 28 | 29 | do --- Cannot sink TNEW, iteratively escaping through a store. 30 | local t = {} 31 | for i=1,100 do t[1] = {i}; t[1][1] = {i} end 32 | assert(t[1][1][1] == 100) 33 | end 34 | 35 | do --- Cannot sink TNEW, escaping to next iteration (unused in 1st variant). 36 | local t; 37 | for i=1,200 do t = {i} end 38 | assert(t[1] == 200) 39 | for i=1,200 do if i > 100 then assert(t[1] == i-1) end t = {i} end 40 | assert(t[1] == 200) 41 | end 42 | 43 | do --- Cannot sink TNEW, escaping to next iteration (snapshot ref). 44 | local t,x 45 | for i=1,100 do x=t; t={i} end 46 | assert(t[1] == 100) 47 | assert(x[1] == 99) 48 | end 49 | 50 | do --- Cannot sink TNEW, escaping to next iteration (IR/snapshot ref). 51 | local t 52 | for i=1,100 do t={t} end 53 | assert(type(t[1][1][1]) == "table") 54 | end 55 | 56 | do --- Cannot sink inner TNEW, escaping to next iteration (IR ref). 57 | -- (Could sink outer TNEW, but the logic for stores to PHI allocs is too simple). 58 | local t = {42, 43} 59 | for i=1,100 do t={t[2], {i}} end 60 | assert(t[2][1] == 100) 61 | assert(t[1][1] == 99) 62 | end 63 | 64 | do --- Cannot sink TNEW, cross-PHI ref (and snapshot ref). 65 | local x,y 66 | for i=1,100 do x,y={i},x end 67 | assert(x[1] == 100) 68 | assert(y[1] == 99) 69 | end 70 | 71 | do --- Cannot sink TNEW, cross-PHI ref (and snapshot ref). 72 | local x,y 73 | for i=1,100 do x,y=y,{i} end 74 | assert(x[1] == 99) 75 | assert(y[1] == 100) 76 | end 77 | 78 | do --- Cannot sink TNEW, escaping to exit. 79 | local function f(n, t) 80 | if n == 0 then return t end 81 | return (f(n-1, {t})) 82 | end 83 | local t = f(100, 42) 84 | assert(type(t[1][1][1]) == "table") 85 | t = f(3, 42) 86 | assert(t[1][1][1] == 42) 87 | end 88 | 89 | do --- Cannot sink TNEW, escaping to exit. 90 | local function f(n) 91 | if n == 0 then return 42 end 92 | local t = f(n-1) 93 | return {t} 94 | end 95 | for i=1,20 do 96 | local t = f(100) 97 | assert(type(t[1][1][1]) == "table") 98 | end 99 | local t = f(3) 100 | assert(t[1][1][1] == 42) 101 | end 102 | 103 | do --- Cannot sink, since nested inner table is non-PHI. 104 | local a, b = {{1}}, {{1}} 105 | for i=1,10000 do -- Need to force GC exit sometimes 106 | a = {{a[1][1]+b[1][1]}} 107 | end 108 | assert(a[1][1] == 10001) 109 | end 110 | -------------------------------------------------------------------------------- /test/src/cpptest.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | extern "C" { 5 | #define LUA_LIB 6 | #include "lua.h" 7 | #include "lauxlib.h" 8 | #include "luajit.h" 9 | } 10 | 11 | static int testobj_alloc; 12 | 13 | class TestObj { 14 | public: 15 | TestObj(int x) { foo = x; testobj_alloc = 1; } 16 | ~TestObj() { testobj_alloc = 0; } 17 | private: 18 | int foo; 19 | }; 20 | 21 | static int ct_alloc(lua_State *L) 22 | { 23 | TestObj foo(1); 24 | lua_pushlightuserdata(L, (void *)&foo); 25 | lua_call(L, lua_gettop(L)-1, LUA_MULTRET); 26 | if (lua_iscfunction(L, -1)) { 27 | lua_CFunction f = lua_tocfunction(L, -1); 28 | lua_pop(L, 1); 29 | f(L); 30 | } 31 | return lua_gettop(L); 32 | } 33 | 34 | static int ct_isalloc(lua_State *L) 35 | { 36 | lua_pushboolean(L, testobj_alloc); 37 | return 1; 38 | } 39 | 40 | static int ct_usereg(lua_State *L) 41 | { 42 | int n = luaL_checkint(L, 1); 43 | int m = luaL_checkint(L, 2); 44 | int i; 45 | int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; 46 | for (i = 0; i < n; i++) { 47 | a = (a + 1) ^ 0x12345678; 48 | b = (b + 2) ^ 0x12345678; 49 | c = (c + 3) ^ 0x12345678; 50 | d = (d + 4) ^ 0x12345678; 51 | e = (e + 5) ^ 0x12345678; 52 | f = (f + 5) ^ 0x12345678; 53 | if (i == m) { 54 | if (i & 1) 55 | lua_pcall(L, 1, 0, 0); 56 | else 57 | lua_call(L, 1, 0); 58 | } 59 | } 60 | lua_pushinteger(L, a); 61 | lua_pushinteger(L, b); 62 | lua_pushinteger(L, c); 63 | lua_pushinteger(L, d); 64 | lua_pushinteger(L, e); 65 | lua_pushinteger(L, f); 66 | return 6; 67 | } 68 | 69 | static int ct_catch(lua_State *L) 70 | { 71 | try { 72 | lua_call(L, lua_gettop(L)-1, LUA_MULTRET); 73 | return lua_gettop(L); 74 | } catch (const char *s) { 75 | lua_pushstring(L, s); 76 | } catch (...) { 77 | lua_pushliteral(L, "catch ..."); 78 | } 79 | return 1; 80 | } 81 | 82 | static int ct_throw(lua_State *L) 83 | { 84 | const char *s = lua_tostring(L, 1); 85 | throw(s); 86 | return 0; 87 | } 88 | 89 | static int ct_wrap(lua_State *L, lua_CFunction f) 90 | { 91 | try { 92 | return f(L); 93 | } catch (const char *s) { 94 | lua_pushstring(L, s); 95 | } 96 | return lua_error(L); 97 | } 98 | 99 | static int ct_wrapon(lua_State *L) 100 | { 101 | lua_pushlightuserdata(L, (void *)ct_wrap); 102 | luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON); 103 | return 0; 104 | } 105 | 106 | static int ct_wrapoff(lua_State *L) 107 | { 108 | luaJIT_setmode(L, 0, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_OFF); 109 | return 0; 110 | } 111 | 112 | static luaL_Reg ct_funcs[] = { 113 | {"isalloc", ct_isalloc }, 114 | {"alloc", ct_alloc }, 115 | {"usereg", ct_usereg }, 116 | {"catch", ct_catch }, 117 | {"throw", ct_throw }, 118 | {"wrapon", ct_wrapon }, 119 | {"wrapoff", ct_wrapoff }, 120 | {NULL, NULL} 121 | }; 122 | 123 | extern "C" { 124 | LUA_API int luaopen_cpptest(lua_State *L) 125 | { 126 | luaL_register(L, "cpptest", ct_funcs); 127 | return 1; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /test/sysdep/catch_cpp.lua: -------------------------------------------------------------------------------- 1 | 2 | local cp = require("cpptest") 3 | 4 | do 5 | local a, b = pcall(cp.catch, function() return "x" end) 6 | assert(a == true and b == "x") 7 | end 8 | 9 | do 10 | local a, b = pcall(function() cp.throw("foo") end) 11 | assert(a == false and b == "C++ exception") 12 | end 13 | 14 | local unwind 15 | do 16 | local a, b = pcall(cp.catch, function() cp.throw("foo") end) 17 | unwind = a 18 | assert((a == false and b == "C++ exception") or (a == true and b == "foo")) 19 | end 20 | 21 | do 22 | local st = cp.alloc(function() return cp.isalloc() end) 23 | assert(st == true) 24 | assert(cp.isalloc() == false) 25 | end 26 | 27 | do 28 | local a, b = pcall(cp.alloc, function() 29 | assert(cp.isalloc() == true) 30 | return "foo", cp.throw 31 | end) 32 | assert(a == false and b == "C++ exception") 33 | assert(cp.isalloc() == false) 34 | end 35 | 36 | if unwind then 37 | local a, b = pcall(cp.alloc, function() 38 | assert(cp.isalloc() == true) 39 | return "foo", error 40 | end) 41 | assert(a == false and b == "foo") 42 | assert(cp.isalloc() == false) 43 | end 44 | 45 | do 46 | local a,b,c,d,e,f = cp.usereg(100, 50, function() end, false) 47 | assert(a==164 and b==312 and c==428 and d==3696 and e==404 and f==404) 48 | end 49 | 50 | do 51 | local function test() 52 | cp.usereg(100, 40, error, "foo") 53 | end 54 | local a,b,c,d,e,f = cp.usereg(100, 51, test, false) 55 | assert(a==164 and b==312 and c==428 and d==3696 and e==404 and f==404) 56 | end 57 | 58 | do 59 | local t = {}; 60 | t.t = t; 61 | local function foo() 62 | for i=1,100 do 63 | local a,b,c,d,e,f = t, t.t, t.t.t, t.t.t.t, t.t.t.t.t, t.t.t.t.t.t 64 | local g,h,j,k,l = f.t, f.t.t, f.t.t.t, f.t.t.t.t, f.t.t.t.t.t 65 | local m = { a,b,c,d,e,f,g,h,j,k,l } 66 | end 67 | end 68 | local a,b,c,d,e,f = cp.usereg(100, 50, foo, false) 69 | assert(a==164 and b==312 and c==428 and d==3696 and e==404 and f==404) 70 | end 71 | 72 | -------------------------------------------------------------------------------- /test/sysdep/ffi_include_gtk.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | if cdefs == "" then 6 | cdefs = "-pthread -D_REENTRANT -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/directfb -I/usr/include/libpng12 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/gdk-pixbuf-2.0" 7 | end 8 | 9 | include"/usr/include/gtk-2.0/gtk/gtk.h" 10 | -------------------------------------------------------------------------------- /test/sysdep/ffi_include_std.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | dofile("../common/ffi_util.inc") 4 | 5 | do 6 | local fp = assert(io.open("/tmp/__tmp.c", "w")) 7 | fp:write[[ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | ]] 27 | fp:close() 28 | 29 | local flags = ffi.abi("32bit") and "-m32" or "-m64" 30 | fp = assert(io.popen("cc -E -P -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE /tmp/__tmp.c "..flags)) 31 | local s = fp:read("*a") 32 | fp:close() 33 | os.remove("/tmp/__tmp.c") 34 | ffi.cdef(s) 35 | end 36 | 37 | -------------------------------------------------------------------------------- /test/sysdep/ffi_lib_c.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | ffi.cdef[[ 4 | // libc/libm 5 | int sprintf(char *buf, const char *fmt, ...); 6 | double pow(double x, double y); 7 | int rmdir(const char *name); 8 | int errno; 9 | 10 | // Windows 11 | unsigned int GetSystemDirectoryA(char *buf, unsigned int sz); 12 | char *CharUpperA(char *str); 13 | int GdiFlush(void); 14 | int _rmdir(const char *name); 15 | static const int _O_TEXT = 0x4000; 16 | static const int _O_BINARY = 0x8000; 17 | int *_errno(void); 18 | int _fmode; 19 | 20 | // Lua/C API 21 | typedef struct lua_State lua_State; 22 | typedef double lua_Number; 23 | lua_State *luaL_newstate(void); 24 | void luaL_openlibs(lua_State *L); 25 | void lua_close(lua_State *L); 26 | int luaL_loadstring(lua_State *L, const char *s); 27 | int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc); 28 | lua_Number lua_tonumber(lua_State *L, int idx); 29 | ]] 30 | 31 | local C = ffi.C 32 | 33 | do 34 | local buf = ffi.new("char[?]", 100) 35 | local n = C.sprintf(buf, "test %g %s", 12.5, "foo") 36 | assert(ffi.string(buf, n) == "test 12.5 foo") 37 | end 38 | 39 | assert(ffi.C.pow(2.5, 5) == 97.65625) 40 | 41 | if ffi.abi("win") then 42 | do 43 | local buf = ffi.new("char[?]", 4, "abc") 44 | C.CharUpperA(buf) 45 | assert(ffi.string(buf) == "ABC") 46 | end 47 | 48 | do 49 | local buf = ffi.new("char[?]", 256) 50 | local len = C.GetSystemDirectoryA(buf, 255) 51 | local s = ffi.string(buf, len) 52 | assert(string.find(string.lower(s), "\\system32")) 53 | end 54 | 55 | assert(C.GdiFlush() == 1) 56 | 57 | assert(ffi.C._rmdir("/tmp/does_not_exist") == -1) 58 | assert(ffi.C._errno()[0] == 2) 59 | 60 | ffi.C._fmode = ffi.C._O_BINARY 61 | assert(ffi.C._fmode == ffi.C._O_BINARY) 62 | ffi.C._fmode = ffi.C._O_TEXT 63 | else 64 | assert(ffi.C.rmdir("/tmp/does_not_exist") == -1) 65 | assert(ffi.C.errno == 2) 66 | 67 | ffi.C.errno = 17 68 | assert(ffi.C.errno == 17) 69 | ffi.C.errno = 0 70 | end 71 | 72 | do 73 | local L = C.luaL_newstate() 74 | local s = "local x = 0; for i=1,100 do x=x+i end; return x" 75 | C.luaL_openlibs(L) 76 | assert(C.luaL_loadstring(L, s) == 0) 77 | assert(C.lua_pcall(L, 0, 1, 0) == 0) 78 | assert(C.lua_tonumber(L, -1) == 5050) 79 | C.lua_close(L) 80 | end 81 | 82 | do 83 | if not (ffi.os == "Windows" or ffi.os == "Other") then 84 | ffi.load("pthread") 85 | end 86 | end 87 | 88 | -------------------------------------------------------------------------------- /test/trace/exit_frame.lua: -------------------------------------------------------------------------------- 1 | do --- global assignments !private_G 2 | g = 0 3 | gf = 1 4 | gz = 2 5 | 6 | local function f(i) 7 | if i == 90 then 8 | gf = gf + 1 9 | return true 10 | end 11 | g = g + 1 12 | end 13 | 14 | local function z(i) 15 | if f(i) then 16 | gz = gz + 1 17 | end 18 | end 19 | 20 | for j=1,5 do 21 | for i=1,100 do z(i) end 22 | end 23 | 24 | assert(g == 495) 25 | assert(gf == 6) 26 | assert(gz == 7) 27 | end 28 | 29 | do --- mutual recursion 30 | local f, g 31 | function f(j) 32 | if j >= 0 then return g(j-1) end 33 | end 34 | function g(j) 35 | for i=1,200 do 36 | if i > 100 then return f(j) end 37 | end 38 | end 39 | for k=1,20 do g(20) end 40 | end 41 | 42 | do --- multi-path mutual recursion 43 | local f, g 44 | function f(j, k) 45 | if j >= 0 then return g(j-1, k) end 46 | if k >= 0 then return g(20, k-1) end 47 | end 48 | function g(j, k) 49 | for i=1,200 do 50 | if i > 100 then return f(j, k) end 51 | end 52 | end 53 | g(20, 20) 54 | end 55 | 56 | do --- late mutual recursion 57 | local k = 0 58 | local f, g 59 | 60 | function g(a) 61 | -- 'a' is an SLOAD #1 from f's frame and still at slot #1 62 | -- Avoid losing a in exit if the SLOAD is ignored 63 | if k > 10 then k = 0 end 64 | k= k + 1 65 | return f(a) 66 | end 67 | 68 | function f(a,b,c,d,e) 69 | if not e then e =1 end 70 | a=a+1 71 | if a > 1000 then return end 72 | for i=1,100 do 73 | e=e+1 74 | if i > 90 then return g(a) end 75 | end 76 | end 77 | 78 | f(1,2,3,4,5) 79 | end 80 | -------------------------------------------------------------------------------- /test/trace/exit_growstack.lua: -------------------------------------------------------------------------------- 1 | do --- Exit needs to grow stack before slot fill. 2 | local function f(i) 3 | local a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a; 4 | local a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a; 5 | local a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a; 6 | if i==90 then return end 7 | end 8 | for j=1,5 do 9 | collectgarbage() -- Shrink stack. 10 | for i=1,100 do f(i) end 11 | end 12 | end 13 | 14 | do --- Exit needs to grow stack after slot fill. 15 | local function g(i) 16 | if i==90 then return end 17 | do return end 18 | do 19 | local a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a; 20 | local a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a; 21 | local a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a; 22 | end 23 | end 24 | for j=1,5 do 25 | collectgarbage() -- Shrink stack. 26 | for i=1,100 do g(i) end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/trace/exit_jfuncf.lua: -------------------------------------------------------------------------------- 1 | do --- everything 2 | local assert = assert 3 | 4 | local function rec(a, b, c, d, e, f) 5 | assert(f == a+1) 6 | if b == 0 then return 7 end 7 | do local x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x100 end 8 | return rec(a, b-1, c, d, e, f)+1 9 | end 10 | 11 | -- Compile recursive function. 12 | assert(rec(42, 200, 1, 2, 3, 43) == 207) 13 | 14 | local function trec() 15 | return rec(42, 0, 1, 2, 3, 43) 16 | end 17 | 18 | -- Compile function jumping to JFUNCF. 19 | for i=1,200 do 20 | gcinfo() 21 | assert(trec() == 7) 22 | end 23 | 24 | -- Shrink stack. 25 | for j=1,10 do collectgarbage() end 26 | 27 | -- Cause an exit due to stack growth with PC pointing to JFUNCF. 28 | -- Needs to load RD with nres+1 and not with the bytecode RD. 29 | assert(trec() == 7) 30 | end 31 | -------------------------------------------------------------------------------- /test/trace/gc64_slot_revival.lua: -------------------------------------------------------------------------------- 1 | do --- BC_KNIL 2 | local function f(x, y) end 3 | for i = 1,100 do 4 | f(i, i) 5 | f(nil, nil) 6 | end 7 | end 8 | 9 | do --- BC_VARG 10 | local function f() end 11 | local function g(...) 12 | f() 13 | f(...) 14 | end 15 | for i = 1,100 do 16 | g() 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/trace/index: -------------------------------------------------------------------------------- 1 | exit_frame.lua 2 | exit_growstack.lua 3 | exit_jfuncf.lua 4 | gc64_slot_revival.lua 5 | phi 6 | snap.lua 7 | stitch.lua 8 | -------------------------------------------------------------------------------- /test/trace/phi/copyspill.lua: -------------------------------------------------------------------------------- 1 | do --- mat4mul !private_G 2 | function mat4mul(a11, a21, a31, a41, 3 | a12, a22, a32, a42, 4 | a13, a23, a33, a43, 5 | a14, a24, a34, a44, 6 | b11, b21, b31, b41, 7 | b12, b22, b32, b42, 8 | b13, b23, b33, b43, 9 | b14, b24, b34, b44) 10 | return a11*b11+a21*b12+a31*b13+a41*b14, 11 | a11*b21+a21*b22+a31*b23+a41*b24, 12 | a11*b31+a21*b32+a31*b33+a41*b34, 13 | a11*b41+a21*b42+a31*b43+a41*b44, 14 | a12*b11+a22*b12+a32*b13+a42*b14, 15 | a12*b21+a22*b22+a32*b23+a42*b24, 16 | a12*b31+a22*b32+a32*b33+a42*b34, 17 | a12*b41+a22*b42+a32*b43+a42*b44, 18 | a13*b11+a23*b12+a33*b13+a43*b14, 19 | a13*b21+a23*b22+a33*b23+a43*b24, 20 | a13*b31+a23*b32+a33*b33+a43*b34, 21 | a13*b41+a23*b42+a33*b43+a43*b44, 22 | a14*b11+a24*b12+a34*b13+a44*b14, 23 | a14*b21+a24*b22+a34*b23+a44*b24, 24 | a14*b31+a24*b32+a34*b33+a44*b34, 25 | a14*b41+a24*b42+a34*b43+a44*b44 26 | end 27 | 28 | local a11, a21, a31, a41 = 1, 0, 0, 0 29 | local a12, a22, a32, a42 = 0, 1, 0, 0 30 | local a13, a23, a33, a43 = 0, 0, 1, 0 31 | local a14, a24, a34, a44 = 0, 0, 0, 1 32 | 33 | local b11, b21, b31, b41 = 0, 0, -1, 0 34 | local b12, b22, b32, b42 = 0, 1, 0, 0 35 | local b13, b23, b33, b43 = 1, 0, 0, 0 36 | local b14, b24, b34, b44 = 0, 0, 0, 1 37 | 38 | for i = 1, 1000 do 39 | a11, a21, a31, a41, 40 | a12, a22, a32, a42, 41 | a13, a23, a33, a43, 42 | a14, a24, a34, a44 = mat4mul(a11, a21, a31, a41, 43 | a12, a22, a32, a42, 44 | a13, a23, a33, a43, 45 | a14, a24, a34, a44, 46 | b11, b21, b31, b41, 47 | b12, b22, b32, b42, 48 | b13, b23, b33, b43, 49 | b14, b24, b34, b44) 50 | end 51 | assert(a11 == 1) 52 | assert(a31 == 0) 53 | end 54 | -------------------------------------------------------------------------------- /test/trace/phi/index: -------------------------------------------------------------------------------- 1 | copyspill.lua 2 | ref.lua 3 | rotate.lua 4 | -------------------------------------------------------------------------------- /test/trace/snap.lua: -------------------------------------------------------------------------------- 1 | do --- gcexit 2 | local x = 0 3 | local t 4 | for i=1,1000 do 5 | if i >= 100 then 6 | -- causes an exit for atomic phase 7 | -- must not merge snapshot #0 with comparison since it has the wrong PC 8 | if i < 150 then x=x+1 end 9 | t = {i} 10 | end 11 | end 12 | assert(x == 50) 13 | assert(t[1] == 1000) 14 | end 15 | 16 | 17 | do --- top !private_G 18 | function randomtable(entries, depth) 19 | if depth == 0 then 20 | return tostring(math.random(2)) -- snapshot between return and CALLMT 21 | end 22 | local t = {} 23 | for k=1,entries do 24 | t[k] = randomtable(entries, depth-1) 25 | end 26 | return t 27 | end 28 | 29 | local t = randomtable(10, 2) 30 | end 31 | 32 | do --- top2 33 | local function f() 34 | gcinfo() 35 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 36 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 37 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 38 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 39 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 40 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 41 | end 42 | 43 | for i=1,100 do 44 | f() 45 | if i % 3 == 0 then collectgarbage() end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/trace/stitch.lua: -------------------------------------------------------------------------------- 1 | do --- octal 2 | local tonumber = tonumber 3 | local function octal(s) return tonumber(s, 8) end 4 | for i=1,100 do 5 | octal("1") 6 | octal("1") 7 | octal("1") 8 | end 9 | end 10 | 11 | do --- coroutines 12 | local t = { 13 | [0] = function() end, 14 | coroutine.wrap(function() while true do coroutine.yield() end end), 15 | } 16 | for i=1,100 do 17 | t[i % 2]() 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/unportable/ffi_arith_int64.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | local int = ffi.typeof("int") 4 | 5 | local inp = { 6 | 0, 0.5, -0.5, 1.5, -1.5, 1, -1, 2, -2, 37, -37, false, 7 | int(0), int(1), int(-1), int(2), int(-2), int(37), int(-37), false, 8 | 0ll, 1ll, -1ll, 2ll, -2ll, 37ll, -37ll, false, 9 | 0ull, 1ull, -1ull, 2ull, -2ull, 37ull, -37ull, 10 | } 11 | 12 | local function cksum(s, r) 13 | local z = 0 14 | for i=1,#s do z = (z + string.byte(s, i)*i) % 2147483629 end 15 | if z ~= r then 16 | error("test failed (got "..z..", expected "..r..") for:\n"..s, 3) 17 | end 18 | end 19 | 20 | local function tostr(n) 21 | if type(n) == "cdata" then return tostring(n) 22 | elseif n ~= n then return "nan" 23 | else return string.format("%+1.5g", n) end 24 | end 25 | 26 | local function check(f, expected, y) 27 | local inp = inp 28 | local out = {} 29 | for i=1,#inp do 30 | if inp[i] then out[i] = tostr(f(inp[i], y)) else out[i] = "\n" end 31 | end 32 | local got = string.gsub(table.concat(out, " ").."\n", "\n ", "\n") 33 | cksum(got, expected) 34 | end 35 | 36 | jit.off(check) 37 | 38 | local function check2(f, exparray) 39 | local k = 1 40 | for j=1,#inp do 41 | local y = inp[j] 42 | if y then 43 | check(f, exparray[k], y) 44 | k = k + 1 45 | end 46 | end 47 | end 48 | 49 | check(function(x) return -x end, 1174528) 50 | 51 | check2(function(x, y) return x+y end, 52 | {1171039,1239261,1239303,1011706,1490711,949996,1415869,756412,1682910,768883,2201023,1265370,1015700,1556902,807607,1862947,814710,2423097,1265370,1015700,1556902,807607,1862947,814710,2423097,4833809,2909723,7784653,1736671,10743770,1126700,13324037,}) 53 | 54 | check2(function(x, y) return x-y end, 55 | {1171039,1239303,1239261,1490711,1011706,1415869,949996,1682910,756412,2201023,768883,1265370,1556902,1015700,1862947,807607,2423097,814710,1265370,1556902,1015700,1862947,807607,2423097,814710,4833809,7784653,2909723,10743770,1736671,13324037,1126700,}) 56 | 57 | check2(function(x, y) return x*y end, 58 | {470257,637182,637132,1308150,1311627,1171039,1174528,1083877,1087553,1561321,1564869,564568,1265370,1269122,1265037,1268973,1643392,1647266,564568,1265370,1269122,1265037,1268973,1643392,1647266,827768,4833809,4847593,4823713,4838210,5230281,5244035,}) 59 | 60 | check2(function(x, y) return x/y end, 61 | {7946210,7360895,7360865,1580465,927251,1171039,622069,1252901,704706,1542087,960011,14749620,1265370,695208,1188639,661058,1049280,587329,14749620,1265370,695208,1188639,661058,1049280,587329,15042810,4833809,828129,4559889,828509,4208862,828929,}) 62 | 63 | 64 | check2(function(x, y) return x%y end, 65 | {7653740,7304160,7304160,527871,851988,527061,850910,556674,717022,610671,613599,14749620,564568,894526,618652,785052,641760,644574,14749620,564568,894526,618652,785052,641760,644574,15042810,827768,2913108,829285,1737261,951059,959905,}) 66 | 67 | check2(function(x, y) return x^y end, 68 | {471871,702627,720692,1385612,1803393,1171039,1772007,763817,1583994,4486762,2380423,566647,1265370,2319256,770581,1990479,4566660,2319835,566647,1265370,2319256,770581,1990479,4566660,2319835,830322,4833809,4644705,1071753,2822313,7709069,4647021,}) 69 | -------------------------------------------------------------------------------- /test/unportable/math_special.lua: -------------------------------------------------------------------------------- 1 | 2 | local inp = { 0, -"0", 0.5, -0.5, 1, -1, 1/0, -1/0, 0/0 } 3 | 4 | local function tostr(n) 5 | if n == 0 and 1/n < 0 then return "-0" 6 | elseif 1/n == 0 then return n < 0 and "-inf" or "+inf" 7 | elseif n ~= n then return "nan" 8 | else return string.format("%+1.5g", n) end 9 | end 10 | 11 | local function check(f, expected) 12 | local inp = inp 13 | local out = {} 14 | for i=1,#inp do out[i] = tostr(f(inp[i])) end 15 | local got = table.concat(out, " ") 16 | if got ~= expected then 17 | error("got: \""..got.."\"\nexpected: \""..expected.."\"", 2) 18 | end 19 | end 20 | 21 | check(function(x) return x end, "+0 -0 +0.5 -0.5 +1 -1 +inf -inf nan") 22 | 23 | local powcheck = { 24 | "+1 +1 +1 +1 +1 +1 +1 +1 +1", 25 | "+1 +1 +1 +1 +1 +1 +1 +1 +1", 26 | "+0 +0 +0.70711 nan +1 nan +inf +inf nan", 27 | "+inf +inf +1.4142 nan +1 nan +0 +0 nan", 28 | "+0 -0 +0.5 -0.5 +1 -1 +inf -inf nan", 29 | "+inf -inf +2 -2 +1 -1 +0 -0 nan", 30 | "+0 +0 +0 +0 +1 +1 +inf +inf nan", 31 | "+inf +inf +inf +inf +1 +1 +0 +0 nan", 32 | "nan nan nan nan +1 nan nan nan nan", 33 | } 34 | for j=1,#inp do 35 | local y = inp[j] 36 | check(function(x) return x^y end, powcheck[j]) 37 | end 38 | 39 | check(math.abs, "+0 +0 +0.5 +0.5 +1 +1 +inf +inf nan") 40 | check(math.floor, "+0 -0 +0 -1 +1 -1 +inf -inf nan") 41 | check(math.ceil, "+0 -0 +1 -0 +1 -1 +inf -inf nan") 42 | check(math.sqrt, "+0 -0 +0.70711 nan +1 nan +inf nan nan") 43 | check(math.sin, "+0 -0 +0.47943 -0.47943 +0.84147 -0.84147 nan nan nan") 44 | check(math.cos, "+1 +1 +0.87758 +0.87758 +0.5403 +0.5403 nan nan nan") 45 | check(math.tan, "+0 -0 +0.5463 -0.5463 +1.5574 -1.5574 nan nan nan") 46 | check(math.asin, "+0 -0 +0.5236 -0.5236 +1.5708 -1.5708 nan nan nan") 47 | check(math.acos, "+1.5708 +1.5708 +1.0472 +2.0944 +0 +3.1416 nan nan nan") 48 | check(math.atan, "+0 -0 +0.46365 -0.46365 +0.7854 -0.7854 +1.5708 -1.5708 nan") 49 | check(math.log, "-inf -inf -0.69315 nan +0 nan +inf nan nan") 50 | check(math.log10, "-inf -inf -0.30103 nan +0 nan +inf nan nan") 51 | check(math.exp, "+1 +1 +1.6487 +0.60653 +2.7183 +0.36788 +inf +0 nan") 52 | 53 | -- Pointless: deg, rad, min, max, pow 54 | -- LATER: %, fmod, frexp, ldexp, modf, sinh, cosh, tanh 55 | 56 | --------------------------------------------------------------------------------