├── .gitignore ├── .travis.yml ├── README.md ├── 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 ├── run-tests ├── test ├── clib │ ├── cpptest.cpp │ └── ctest.c ├── common │ └── ffi_util.inc ├── ffi │ ├── ffi_arith_ptr.lua │ ├── ffi_bit64.lua │ ├── ffi_bitfield.lua │ ├── ffi_call.lua │ ├── ffi_callback.lua │ ├── ffi_const.lua │ ├── ffi_convert.lua │ ├── ffi_copy_fill.lua │ ├── ffi_enum.lua │ ├── ffi_err.lua │ ├── ffi_gcstep_recursive.lua │ ├── ffi_istype.lua │ ├── ffi_jit_arith.lua │ ├── ffi_jit_array.lua │ ├── ffi_jit_call.lua │ ├── ffi_jit_complex.lua │ ├── ffi_jit_conv.lua │ ├── ffi_jit_misc.lua │ ├── ffi_jit_struct.lua │ ├── ffi_lex_number.lua │ ├── ffi_meta_tostring.lua │ ├── ffi_metatype.lua │ ├── ffi_new.lua │ ├── ffi_nosink.lua │ ├── ffi_parse_array.lua │ ├── ffi_parse_basic.lua │ ├── ffi_parse_cdef.lua │ ├── ffi_parse_struct.lua │ ├── ffi_redir.lua │ ├── ffi_sink.lua │ ├── ffi_tabov.lua │ ├── ffi_type_punning.lua │ └── unsink_64_kptr.lua ├── misc │ ├── ack.lua │ ├── ack_notail.lua │ ├── alias_alloc.lua │ ├── api_call.lua │ ├── argcheck.lua │ ├── assign_tset_prevnil.lua │ ├── assign_tset_tmp.lua │ ├── bit_op.lua │ ├── cat_jit.lua │ ├── catch_wrap.lua │ ├── compare.lua │ ├── constov.lua │ ├── coro_traceback.lua │ ├── coro_yield.lua │ ├── debug_gc.lua │ ├── debug_meta.lua │ ├── dse_array.lua │ ├── dse_field.lua │ ├── dualnum.lua │ ├── exit_frame.lua │ ├── exit_growstack.lua │ ├── exit_jfuncf.lua │ ├── fac.lua │ ├── fastfib.lua │ ├── fib.lua │ ├── for_dir.lua │ ├── fori_coerce.lua │ ├── fuse.lua │ ├── fwd_hrefk_rollback.lua │ ├── fwd_tnew_tdup.lua │ ├── fwd_upval.lua │ ├── gc_rechain.lua │ ├── gc_trace.lua │ ├── gcstep.lua │ ├── getfenv.lua │ ├── goto.lua │ ├── hook_active.lua │ ├── hook_line.lua │ ├── hook_norecord.lua │ ├── hook_record.lua │ ├── hook_top.lua │ ├── hstore_elimination.lua │ ├── iter-bug.lua │ ├── iter.lua │ ├── jit_flush.lua │ ├── jit_record.lua │ ├── jloop-itern-stack-check-fix.lua │ ├── kfold.lua │ ├── libfuncs.lua │ ├── lightud.lua │ ├── loop_unroll.lua │ ├── math_random.lua │ ├── meta_arith.lua │ ├── meta_arith_jit.lua │ ├── meta_call.lua │ ├── meta_cat.lua │ ├── meta_comp.lua │ ├── meta_comp_jit.lua │ ├── meta_eq.lua │ ├── meta_eq_jit.lua │ ├── meta_framegap.lua │ ├── meta_getset.lua │ ├── meta_len.lua │ ├── meta_nomm.lua │ ├── meta_pairs.lua │ ├── meta_tget.lua │ ├── meta_tget_nontab.lua │ ├── meta_tset.lua │ ├── meta_tset_nilget.lua │ ├── meta_tset_resize.lua │ ├── meta_tset_str.lua │ ├── modulo.lua │ ├── multi_result_call_next.lua │ ├── nsieve.lua │ ├── num_int.lua │ ├── pairs_bug.lua │ ├── parse_andor.lua │ ├── parse_comp.lua │ ├── parse_esc.lua │ ├── parse_hex.lua │ ├── parse_misc.lua │ ├── pcall_jit.lua │ ├── phi_conv.lua │ ├── phi_copyspill.lua │ ├── phi_ref.lua │ ├── phi_rot18.lua │ ├── phi_rot8.lua │ ├── phi_rot9.lua │ ├── phi_rotx.lua │ ├── recsum.lua │ ├── recsump.lua │ ├── recurse_deep.lua │ ├── recurse_tail.lua │ ├── select.lua │ ├── self.lua │ ├── sink_alloc.lua │ ├── sink_nosink.lua │ ├── snap_gcexit.lua │ ├── snap_top.lua │ ├── snap_top2.lua │ ├── sort.lua │ ├── stack_gc.lua │ ├── stack_purge.lua │ ├── stackov.lua │ ├── stackovc.lua │ ├── stitch.lua │ ├── strcmp.lua │ ├── string_byte.lua │ ├── string_char.lua │ ├── string_dump.lua │ ├── string_op.lua │ ├── string_sub.lua │ ├── string_sub_opt.lua │ ├── table_alias.lua │ ├── table_chain_bug_LuaJIT_494.lua │ ├── table_insert.lua │ ├── table_misc.lua │ ├── table_remove.lua │ ├── tak.lua │ ├── tcall_base.lua │ ├── tcall_loop.lua │ ├── tlen_loop.lua │ ├── tnew_tdup.lua │ ├── tonumber_scan.lua │ ├── tonumber_tostring.lua │ ├── uclo.lua │ ├── unordered.lua │ ├── unordered_jit.lua │ ├── vararg_jit.lua │ ├── wbarrier.lua │ ├── wbarrier_jit.lua │ ├── wbarrier_obar.lua │ └── xpcall_jit.lua ├── sysdep │ ├── catch_cpp.lua │ ├── ffi_include_gtk.lua │ ├── ffi_include_std.lua │ ├── ffi_lib_c.lua │ └── ffi_lib_z.lua └── unportable │ ├── ffi_arith_int64.lua │ └── math_special.lua └── valgrind.suppress /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | *.swo 4 | *.bak 5 | *.tar.gz 6 | test/clib/cpptest 7 | test/clib/ctest 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | os: linux 5 | 6 | language: c 7 | 8 | compiler: 9 | - gcc 10 | 11 | addons: 12 | apt: 13 | packages: 14 | - libtest-base-perl 15 | - libtext-diff-perl 16 | - libtest-longstring-perl 17 | - liblist-moreutils-perl 18 | - libparallel-forkmanager-perl 19 | - libgd-dev 20 | - libmpc-dev 21 | - build-essential 22 | - libgtk2.0-dev 23 | - valgrind 24 | 25 | env: 26 | global: 27 | - JOBS=3 28 | - LUAJIT_PREFIX=/opt/luajit21 29 | - LUAJIT_SYSM_PREFIX=/opt/luajit21-sysm 30 | - LUAJIT_COMMON_XCFLAGS="-DLUA_USE_APICHECK -DLUA_USE_ASSERT -DLUAJIT_NUMMODE=2 -msse4.2 -O1" 31 | matrix: 32 | - LUAJIT_XCFLAGS="$LUAJIT_COMMON_XCFLAGS" 33 | - LUAJIT_XCFLAGS="-DLUAJIT_ENABLE_LUA52COMPAT $LUAJIT_COMMON_XCFLAGS" LUA52=1 34 | - LUAJIT_XCFLAGS="-DLUAJIT_USE_VALGRIND -DLUAJIT_USE_SYSMALLOC -DLUAJIT_ENABLE_LUA52COMPAT $LUAJIT_COMMON_XCFLAGS" LUA52=1 FLAGS=-v 35 | - LUAJIT_XCFLAGS="-DLUAJIT_USE_GC64 -DLUAJIT_ENABLE_LUA52COMPAT $LUAJIT_COMMON_XCFLAGS" LUA52=1 36 | 37 | install: 38 | - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git ../luajit2 39 | 40 | script: 41 | - valgrind --version 42 | - cd ../luajit2 43 | - make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS="$LUAJIT_XCFLAGS" > build.log 2>&1 || (cat build.log && exit 1) 44 | - sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1) 45 | - cd ../luajit2-test-suite 46 | - ./run-tests -j $JOBS $FLAGS $LUAJIT_PREFIX 47 | -------------------------------------------------------------------------------- /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/openresty/luajit2-test-suite/7dbf11af3df9f5e819f97444138489d29a803160/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/clib/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/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 | local jit = require("jit") 7 | 8 | function checkfail(t, f) 9 | f = f or ffi.typeof 10 | for i=1,1e9 do 11 | local tp = t[i] 12 | if not tp then break end 13 | assert(pcall(f, tp) == false, tp) 14 | end 15 | end 16 | 17 | function checktypes(t) 18 | for i=1,1e9,3 do 19 | local tp = t[i+2] 20 | if not tp then break end 21 | local id = ffi.typeof(tp) 22 | assert(ffi.sizeof(id) == t[i], tp) 23 | assert(ffi.alignof(id) == t[i+1], tp) 24 | end 25 | end 26 | 27 | function fails(f, ...) 28 | if pcall(f, ...) ~= false then error("failure expected", 2) end 29 | end 30 | 31 | local incroot = os.getenv("INCROOT") or "/usr/include" 32 | local cdefs = os.getenv("CDEFS") or "" 33 | 34 | function include(name) 35 | local flags 36 | if jit.arch == "arm64" then 37 | flags = "" 38 | else 39 | flags = ffi.abi("32bit") and "-m32" or "-m64" 40 | end 41 | flags = "" 42 | if string.sub(name, 1, 1) ~= "/" then name = incroot.."/"..name end 43 | local fp = assert(io.popen("cc -E -P "..flags.." "..cdefs.." "..name)) 44 | local s = fp:read("*a") 45 | fp:close() 46 | s = s:gsub("__float128", "double") 47 | s = s:gsub("__uint128_t", "unsigned long long") 48 | s = s:gsub("__attribute__%s*%(%s*%(%s*__deprecated__%s*%([^)]+%)%s*%)%s*%)", "") 49 | s = s:gsub("__attribute__%s*%(%s*%(%s*__deprecated__%s*%)%s*%)", "") 50 | s = s:gsub("#pragma%s+[^\n]*", "") 51 | -- io.stderr:write("code: " .. s) 52 | ffi.cdef(s) 53 | end 54 | 55 | -------------------------------------------------------------------------------- /test/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/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/ffi/ffi_copy_fill.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do 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 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 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/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/ffi/ffi_err.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | -- error in FFI metamethod: don't print metamethod frame. 4 | do 5 | local ok, err = xpcall(function() 6 | local x = (1ll).foo 7 | end, debug.traceback) 8 | assert(ok == false) 9 | assert(not string.find(err, "__index")) 10 | end 11 | 12 | -- tailcall in regular metamethod: keep metamethod frame. 13 | do 14 | local ok, err = xpcall(function() 15 | local t = setmetatable({}, {__index = function() return rawget("x") end }) 16 | local y = t[1] 17 | end, debug.traceback) 18 | assert(ok == false) 19 | assert(string.find(err, "__index")) 20 | end 21 | 22 | -- error in FFI metamethod: set correct PC. 23 | do 24 | ffi.cdef[[ 25 | typedef struct { int x; int y; } point; 26 | point strchr(point* op1, point* op2); 27 | ]] 28 | local point = ffi.metatype("point", { __add = ffi.C.strchr }) 29 | local function foo() 30 | local p = point{ 3, 4 } 31 | local r = p + p 32 | local r = p + 5 33 | end 34 | local ok, err = xpcall(foo, debug.traceback) 35 | local line = debug.getinfo(foo).linedefined+3 36 | assert(string.match(err, "traceback:[^:]*:"..line..":")) 37 | end 38 | 39 | -------------------------------------------------------------------------------- /test/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/ffi/ffi_istype.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | ffi.cdef[[ 4 | typedef int arr_t[10]; 5 | typedef const arr_t carr_t; 6 | typedef struct { int x; } struct_t; 7 | ]] 8 | 9 | do 10 | local void_t = ffi.typeof("void") 11 | assert(ffi.istype(void_t, void_t)) 12 | assert(ffi.istype("const void", void_t)) 13 | 14 | assert(ffi.istype("void", "void") == false) -- 2nd arg is a string. 15 | assert(ffi.istype("double", 1.5) == false) -- 2nd arg is a number. 16 | end 17 | 18 | do 19 | local i8_t = ffi.typeof("int8_t") 20 | local u8_t = ffi.typeof("uint8_t") 21 | local i32_t = ffi.typeof("int32_t") 22 | assert(ffi.istype(i32_t, i32_t) == true) 23 | assert(ffi.istype("const int32_t", i32_t) == true) 24 | 25 | assert(ffi.istype("bool", u8_t) == false) 26 | assert(ffi.istype(i8_t, u8_t) == false) 27 | assert(ffi.istype(i32_t, u8_t) == false) 28 | assert(ffi.istype(u8_t, i32_t) == false) 29 | assert(ffi.istype("double", i32_t) == false) 30 | 31 | assert(ffi.istype("int64_t", ffi.typeof("long long"))) 32 | assert(ffi.istype("long long", ffi.typeof("int64_t"))) 33 | end 34 | 35 | do 36 | local ptr_t = ffi.typeof("int *") 37 | local p = ptr_t() 38 | assert(ffi.istype(ptr_t, ptr_t) == true) 39 | assert(ffi.istype(ptr_t, p) == true) 40 | assert(ffi.istype(p, ptr_t) == true) 41 | assert(ffi.istype("const int *", ptr_t) == true) 42 | assert(ffi.istype("const int * const", ptr_t) == true) 43 | assert(ffi.istype("unsigned int *", ptr_t) == true) 44 | 45 | assert(ffi.istype("char *", ptr_t) == false) 46 | assert(ffi.istype("void *", ptr_t) == false) 47 | end 48 | 49 | do 50 | local arr_t = ffi.typeof("arr_t") 51 | local carr_t = ffi.typeof("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("struct_t") 64 | local structp_t = ffi.typeof("struct_t *") 65 | assert(ffi.istype(struct_t, struct_t) == true) 66 | assert(ffi.istype("const 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 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 | 90 | -------------------------------------------------------------------------------- /test/ffi/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 cc_t { 8 | struct cc_t *next; 9 | complex c; 10 | } cc_t; 11 | ]] 12 | 13 | do 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 23 | local cp = ffi.new("cc_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 38 | local cp = ffi.new("cc_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 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 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 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 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 | -- Index overflow for complex is ignored 106 | do 107 | local c = cx(1, 2) 108 | local x 109 | for i=1e7,1e7+100 do x = c[i] end 110 | end 111 | 112 | -------------------------------------------------------------------------------- /test/ffi/ffi_jit_misc.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do 4 | ffi.errno(42) 5 | local x = 0 6 | for i=1,100 do x = x + ffi.errno() end 7 | assert(x == 4200) 8 | ffi.errno(0) 9 | end 10 | 11 | do 12 | local a = ffi.new("uint8_t[?]", 101) 13 | for i=0,99 do a[i] = i end 14 | local s 15 | for i=1,90 do s = ffi.string(a+i, 10) end 16 | assert(s == "Z[\\]^_`abc") 17 | for i=1,90 do s = ffi.string(a+i) end 18 | assert(s == "Z[\\]^_`abc") 19 | end 20 | 21 | do 22 | local a = ffi.new("uint8_t[?]", 100) 23 | local x = 0 24 | for i=0,90 do x = x + a[i]; ffi.fill(a+i, 10, i); x = x + a[i] end 25 | assert(x == 8100) 26 | for i=1,100 do ffi.fill(a, 15, 0x1234) end 27 | assert(a[0] == 0x34 and a[14] == 0x34 and a[15] == 15) 28 | local b = ffi.new("uint32_t[?]", 104) 29 | for i=0,100 do ffi.fill(b+i, 15, 0x1234) end 30 | assert(b[0] == 0x34343434) 31 | assert(b[103] == (ffi.abi("le") and 0x343434 or 0x34343400)) 32 | end 33 | 34 | do 35 | local a = ffi.new("uint8_t[?]", 100) 36 | local b = ffi.new("uint8_t[?]", 100) 37 | for i=0,99 do b[i] = i end 38 | local x = 0 39 | for i=0,90 do x = x + a[i]; ffi.copy(a+i, b+i, 1); x = x + a[i] end 40 | assert(x == 4095) 41 | local x = 0 42 | for i=0,90 do ffi.copy(b+i, a+90-i, 10); x = x + b[i] end 43 | assert(x == 4095) 44 | end 45 | 46 | do 47 | local a = ffi.new("uint8_t[?]", 100, 42) 48 | for i=0,90 do ffi.copy(a+i, "abc") end 49 | local x = 0 50 | for i=0,99 do x = x + a[i] end 51 | assert(x == 9276) 52 | end 53 | 54 | do 55 | local tp = ffi.typeof("struct { int x, y; }") 56 | local a = tp(1, 2) 57 | local b = tp(3, 4) 58 | local x = 0 59 | for i=1,100 do a.y = i; ffi.copy(b, a, 8); x = x + b.y end 60 | assert(x == 5050) 61 | local x = 0 62 | for i=1,100 do a.y = i; local t = tp(a); x = x + t.y end 63 | assert(x == 5050) 64 | end 65 | 66 | do 67 | local tp = ffi.typeof("struct { complex x, y; }") 68 | local cx = ffi.typeof("complex") 69 | local a = tp(cx(1, 2), cx(3, 4)) 70 | local x = 0 71 | for i=1,100 do a.y = i; local t = tp(a); x = x + t.y.re end 72 | assert(x == 5050) 73 | end 74 | 75 | do 76 | local tp = ffi.typeof("int[10]") 77 | local a = tp(42) 78 | local b = ffi.new(ffi.typeof("struct { $ x; }", tp)) 79 | for i=1,100 do b.x = a end 80 | assert(b.x[0] == 42 and b.x[9] == 42) 81 | end 82 | 83 | do 84 | local tp = ffi.typeof("double[5]") 85 | local a = tp(42) 86 | local b = ffi.new(ffi.typeof("struct { $ x; }", tp)) 87 | for i=1,100 do b.x = a end 88 | assert(b.x[0] == 42 and b.x[4] == 42) 89 | b.x[0] = 0 90 | for i=1,100 do ffi.copy(b.x, a, ffi.sizeof(a)) end 91 | assert(b.x[0] == 42 and b.x[4] == 42) 92 | end 93 | 94 | do 95 | local x, y 96 | for i=1,100 do x = ffi.abi("32bit"); y = ffi.abi("64bit") end 97 | assert(x == ffi.abi("32bit")) 98 | assert(y == ffi.abi("64bit")) 99 | for _,s in ipairs{"64bit", "32bit", "fpu", "softfp", "hardfp", "eabi", "win", "le", "be"} do 100 | for i=1,100 do x = ffi.abi(s) end 101 | assert(x == ffi.abi(s)) 102 | end 103 | end 104 | 105 | do 106 | local ct = ffi.typeof("struct { int x; }") 107 | local cd = ct() 108 | for i=1,100 do assert(ffi.typeof(cd) == ct) end 109 | end 110 | 111 | -------------------------------------------------------------------------------- /test/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/ffi/ffi_meta_tostring.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | ffi.cdef[[ 4 | typedef union 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 | } foo_t; 12 | ]] 13 | 14 | do 15 | local foo_t = ffi.typeof("foo_t") 16 | local x = foo_t() 17 | local s 18 | 19 | assert(tostring(foo_t) == "ctype") 20 | assert(string.match(tostring(x), "^cdata: ")) 21 | 22 | assert(tostring(ffi.typeof("int (*(*[1][2])[3][4])[5][6]")) == 23 | "ctype") 24 | assert(tostring(ffi.typeof("int (*const)(void)")) == 25 | "ctype") 26 | assert(tostring(ffi.typeof("complex float(*(void))[2]")) == 27 | "ctype") 28 | assert(tostring(ffi.typeof("complex*")) == "ctype") 29 | 30 | x.i64 = -1; 31 | assert(tostring(x.i64) == "-1LL") 32 | assert(tostring(x.u64) == "18446744073709551615ULL") 33 | 34 | x.d[0] = 12.5 35 | x.d[1] = -753.125 36 | assert(tostring(x.cd) == "12.5-753.125i") 37 | x.d[0] = -12.5 38 | x.d[1] = 753.125 39 | assert(tostring(x.cd) == "-12.5+753.125i") 40 | x.d[0] = 0/-1 41 | x.d[1] = 0/-1 42 | assert(tostring(x.cd) == "-0-0i") 43 | x.d[0] = 1/0 44 | x.d[1] = -1/0 45 | assert(tostring(x.cd) == "inf-infI") 46 | x.d[0] = -1/0 47 | x.d[1] = 0/0 48 | assert(tostring(x.cd) == "-inf+nanI") 49 | 50 | x.f[0] = 12.5 51 | x.f[1] = -753.125 52 | assert(tostring(x.cf) == "12.5-753.125i") 53 | end 54 | 55 | -------------------------------------------------------------------------------- /test/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/ffi/ffi_nosink.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do 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 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 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 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 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 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/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/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/ffi/ffi_redir.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | ffi.cdef[[ 4 | int foo(const char *s) asm("strlen"); 5 | ]] 6 | 7 | assert(ffi.C.foo("abcd") == 4) 8 | 9 | if ffi.abi("win") then 10 | ffi.cdef[[ 11 | int bar asm("_fmode"); 12 | ]] 13 | else 14 | ffi.cdef[[ 15 | int bar asm("errno"); 16 | ]] 17 | end 18 | 19 | ffi.C.bar = 14 20 | assert(ffi.C.bar == 14) 21 | ffi.C.bar = 0 22 | 23 | -------------------------------------------------------------------------------- /test/ffi/ffi_sink.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | do 4 | local x = 10000000000000ll 5 | for i=1,100 do x=x+1 end 6 | assert(x == 10000000000100ll) 7 | end 8 | 9 | do 10 | local x = 10000000000000ll 11 | local z 12 | for i=1,100 do z=x+1 end 13 | assert(z == 10000000000001ll) 14 | for i=1,100 do local y=x; z=x+1; g=y end 15 | assert(z == 10000000000001ll) 16 | assert(g == 10000000000000ll) 17 | end 18 | 19 | do 20 | local x = 10000000000000ll 21 | for i=1,100 do local y=x+1; if i == 90 then x=y end end 22 | assert(x == 10000000000001ll) 23 | end 24 | 25 | do 26 | local x = 10000000000000ll 27 | for i=1,100 do local y=x+i; if i == 90 then x=y end end 28 | assert(x == 10000000000090ll) 29 | end 30 | 31 | do 32 | local x = 10000000000000ll 33 | for i=1,200 do local y=x+i; if i > 100 then x=y end end 34 | assert(x == 10000000015050ll) 35 | end 36 | 37 | do 38 | local a = ffi.new("int[?]", 100) 39 | local p = a 40 | for i=0,99 do p[0]=i; p=p+1 end 41 | assert(p == a+100) 42 | for i=0,99 do assert(a[i] == i) end 43 | end 44 | 45 | do 46 | local cx = ffi.typeof("complex") 47 | local x = cx(1, 2) 48 | local k = cx(3, 4) 49 | for i=1,100 do x = cx(x.re+k.re, x.im+k.im) end 50 | assert(x.re == 301) 51 | assert(x.im == 402) 52 | end 53 | 54 | do 55 | local st = ffi.typeof("struct { int a; int64_t b; double c; }") 56 | local x = st(1, 20000000000LL, 3.5) 57 | local k = st(3, 4, 5.0) 58 | for i=1,100 do x = st(x.a+k.a, x.b+k.b, x.c+k.c) end 59 | assert(x.a == 301) 60 | assert(x.b == 20000000400LL) 61 | assert(x.c == 503.5) 62 | local y, z 63 | for i=1,100 do 64 | local x = st(i, i, i) 65 | if i == 90 then y = st(x.a, x.b, x.c) end 66 | x.b = x.b + 20000000000LL 67 | if i == 95 then z = st(x.a, x.b, x.c) end 68 | end 69 | assert(y.a == 90) 70 | assert(y.b == 90) 71 | assert(y.c == 90) 72 | assert(z.a == 95) 73 | assert(z.b == 20000000095LL) 74 | assert(z.c == 95) 75 | for i=1,200 do 76 | local x = st(i, i, i) 77 | if i > 100 then y = st(x.a, x.b, x.c) end 78 | x.b = x.b + 20000000000LL 79 | if i > 150 then z = st(x.a, x.b, x.c) end 80 | end 81 | assert(y.a == 200) 82 | assert(y.b == 200) 83 | assert(y.c == 200) 84 | assert(z.a == 200) 85 | assert(z.b == 20000000200LL) 86 | assert(z.c == 200) 87 | end 88 | 89 | do 90 | local st = ffi.typeof("struct { int64_t a; double b; float c; }") 91 | local x = st(1, 2.5, 3.25) 92 | local k = st(3, 4, 5) 93 | for i=1,100 do x = st(x.a+k.a, x.b+k.b, x.c+k.c) end 94 | assert(x.a == 301) 95 | assert(x.b == 402.5) 96 | assert(x.c == 503.25) 97 | end 98 | 99 | do 100 | local st = ffi.typeof("struct { float a; }") 101 | local x 102 | for i=1,200 do 103 | local y = st(i) 104 | if i > 100 then x = y end 105 | end 106 | assert(x.a == 200) 107 | end 108 | 109 | do 110 | local t = {} 111 | for i=1,200 do t[i] = "abcd" end 112 | local r 113 | for i=1,200 do 114 | local a,b,c,d 115 | local g = t[201-i] -- Non-zero stack slot above. 116 | local v = ffi.cast("const char *", t[i]) -- Uses 32 bit stack slot! 117 | a,b,c,d = {v[0]},{v[1]},{v[2]},{v[3]} -- Force above to spill. 118 | r = {{i}} -- Spill due to call. 119 | if i > 100 then z = v[0]+a[1]+b[1]+c[1]+d[1] end -- Crash for 64 bit ptr v. 120 | end 121 | end 122 | 123 | -------------------------------------------------------------------------------- /test/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/ffi/unsink_64_kptr.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | local array = ffi.new("struct { int x; } [1]") 4 | 5 | -- This test forces the VM to unsink a pointer that was constructed 6 | -- from a constant. The IR will include a 'cnewi' instruction to 7 | -- allocate an FFI pointer object, the pointer value will be an IR 8 | -- constant, the allocation will be sunk, and the allocation will 9 | -- at some point be "unsunk" due to a reference in the snapshot for 10 | -- a taken exit. 11 | 12 | -- Note: JIT will recognize as a "singleton" and allow its 13 | -- address to be inlined ("constified") instead of looking up the 14 | -- upvalue at runtime. 15 | 16 | local function fn(i) 17 | local struct = array[0] -- Load pointer that the JIT will constify. 18 | if i == 1000 then end -- Force trace exit when i==1000. 19 | struct.x = 0 -- Ensure that 'struct' is live after exit. 20 | end 21 | 22 | -- Loop over the function to make it compile and take a trace exit 23 | -- during the final iteration. 24 | for i = 1, 1000 do 25 | fn(i) 26 | end 27 | -------------------------------------------------------------------------------- /test/misc/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 | if arg and arg[1] then 8 | local N = tonumber(arg and arg[1]) 9 | io.write("Ack(3,", N ,"): ", Ack(3,N), "\n") 10 | else 11 | assert(Ack(3,5) == 253) 12 | end 13 | -------------------------------------------------------------------------------- /test/misc/ack_notail.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 | if arg and arg[1] then 8 | local N = tonumber(arg and arg[1]) 9 | io.write("Ack(3,", N ,"): ", Ack(3,N), "\n") 10 | else 11 | assert(Ack(3,5) == 253) 12 | end 13 | -------------------------------------------------------------------------------- /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/argcheck.lua: -------------------------------------------------------------------------------- 1 | 2 | local function check(f, msg) 3 | local ok, err = pcall(f) 4 | if ok then error("error check unexpectedly succeeded", 2) end 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 error("error check failed with "..err, 2) end 10 | end 11 | 12 | assert(math.abs(-1.5) == 1.5) 13 | assert(math.abs("-1.5") == 1.5) 14 | 15 | check(function() math.abs() end, 16 | "bad argument #1 to 'abs' (number expected, got no value)") 17 | check(function() math.abs(false) end, 18 | "bad argument #1 to 'abs' (number expected, got boolean)") 19 | check(function() math.abs("a") end, 20 | "bad argument #1 to 'abs' (number expected, got string)") 21 | string.abs = math.abs 22 | check(function() ("a"):abs() end, 23 | "calling 'abs' on bad self (number expected, got string)") 24 | 25 | assert(string.len("abc") == 3) 26 | assert(string.len(123) == 3) 27 | 28 | check(function() string.len() end, 29 | "bad argument #1 to 'len' (string expected, got nil)") 30 | check(function() string.len(false) end, 31 | "bad argument #1 to 'len' (string expected, got boolean)") 32 | 33 | assert(string.sub("abc", 2) == "bc") 34 | assert(string.sub(123, "2") == "23") 35 | 36 | check(function() string.sub("abc", false) end, 37 | "bad argument #2 to 'sub' (number expected, got boolean)") 38 | check(function() ("abc"):sub(false) end, 39 | "bad argument #1 to 'sub' (number expected, got boolean)") 40 | 41 | -------------------------------------------------------------------------------- /test/misc/assign_tset_prevnil.lua: -------------------------------------------------------------------------------- 1 | a, b, c = 0, 1 2 | assert(a == 0) 3 | assert(b == 1) 4 | assert(c == nil) 5 | a, b = a+1, b+1, a+b 6 | assert(a == 1) 7 | assert(b == 2) 8 | a, b, c = 0 9 | assert(a == 0) 10 | assert(b == nil) 11 | assert(c == nil) 12 | -------------------------------------------------------------------------------- /test/misc/assign_tset_tmp.lua: -------------------------------------------------------------------------------- 1 | a = {} 2 | i = 3 3 | i, a[i] = i+1, 20 4 | assert(i == 4) 5 | assert(a[3] == 20) 6 | -------------------------------------------------------------------------------- /test/misc/bit_op.lua: -------------------------------------------------------------------------------- 1 | -- Test cases for bit operations library. Public domain. 2 | 3 | local bit = require"bit" 4 | 5 | local vb = { 6 | 0, 1, -1, 2, -2, 0x12345678, 0x87654321, 7 | 0x33333333, 0x77777777, 0x55aa55aa, 0xaa55aa55, 8 | 0x7fffffff, 0x80000000, 0xffffffff 9 | } 10 | 11 | local function cksum(name, s, r) 12 | local z = 0 13 | for i=1,#s do z = (z + string.byte(s, i)*i) % 2147483629 end 14 | if z ~= r then 15 | error("bit."..name.." test failed (got "..z..", expected "..r..")", 0) 16 | end 17 | end 18 | 19 | local function check_unop(name, r) 20 | local f = bit[name] 21 | local s = "" 22 | if pcall(f) or pcall(f, "z") or pcall(f, true) then 23 | error("bit."..name.." fails to detect argument errors", 0) 24 | end 25 | for _,x in ipairs(vb) do s = s..","..tostring(f(x)) end 26 | cksum(name, s, r) 27 | end 28 | 29 | local function check_binop(name, r) 30 | local f = bit[name] 31 | local s = "" 32 | if pcall(f) or pcall(f, "z") or pcall(f, true) then 33 | error("bit."..name.." fails to detect argument errors", 0) 34 | end 35 | for _,x in ipairs(vb) do 36 | for _,y in ipairs(vb) do s = s..","..tostring(f(x, y)) end 37 | end 38 | cksum(name, s, r) 39 | end 40 | 41 | local function check_binop_range(name, r, yb, ye) 42 | local f = bit[name] 43 | local s = "" 44 | if pcall(f) or pcall(f, "z") or pcall(f, true) or pcall(f, 1, true) then 45 | error("bit."..name.." fails to detect argument errors", 0) 46 | end 47 | for _,x in ipairs(vb) do 48 | for y=yb,ye do s = s..","..tostring(f(x, y)) end 49 | end 50 | cksum(name, s, r) 51 | end 52 | 53 | local function check_shift(name, r) 54 | check_binop_range(name, r, 0, 31) 55 | end 56 | 57 | -- Minimal sanity checks. 58 | assert(0x7fffffff == 2147483647, "broken hex literals") 59 | assert(0xffffffff == -1 or 0xffffffff == 2^32-1, "broken hex literals") 60 | assert(tostring(-1) == "-1", "broken tostring()") 61 | assert(tostring(0xffffffff) == "-1" or tostring(0xffffffff) == "4294967295", "broken tostring()") 62 | 63 | -- 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 | 69 | -- Apply operations to test vectors and compare checksums. 70 | check_unop("tobit", 277312) 71 | check_unop("bnot", 287870) 72 | check_unop("bswap", 307611) 73 | 74 | check_binop("band", 41206764) 75 | check_binop("bor", 51253663) 76 | check_binop("bxor", 79322427) 77 | 78 | check_shift("lshift", 325260344) 79 | check_shift("rshift", 139061800) 80 | check_shift("arshift", 111364720) 81 | check_shift("rol", 302401155) 82 | check_shift("ror", 302316761) 83 | 84 | check_binop_range("tohex", 47880306, -8, 8) 85 | 86 | -- Don't propagate TOBIT narrowing across two conversions. 87 | local tobit = bit.tobit 88 | local k = 0x8000000000003 89 | for i=1,100 do assert(tobit(k % (2^32)) == 3) end 90 | 91 | -------------------------------------------------------------------------------- /test/misc/cat_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Constant folding 3 | do 4 | local y 5 | for i=1,100 do y = "a".."b" end 6 | assert(y == "ab") 7 | for i=1,100 do y = "ab"..(1).."cd"..(1.5) end 8 | assert(y == "ab1cd1.5") 9 | end 10 | 11 | -- Fuse conversions to strings 12 | do 13 | local y 14 | local x = "a" 15 | for i=1,100 do y = x..i end 16 | assert(y == "a100") 17 | x = "a" 18 | for i=1.5,100.5 do y = x..i end 19 | assert(y == "a100.5") 20 | end 21 | 22 | -- Fuse string construction 23 | do 24 | local y 25 | local x = "abc" 26 | for i=1,100 do y = "x"..string.sub(x, 2) end 27 | assert(y == "xbc") 28 | end 29 | 30 | -- CSE, sink 31 | do 32 | local y 33 | local x = "a" 34 | for i=1,100 do y = x.."b" end 35 | assert(y == "ab") 36 | end 37 | 38 | -- CSE, two buffers in parallel, no sink 39 | do 40 | local y, z 41 | local x1, x2 = "xx", "yy" 42 | for i=1,100 do y = x1.."a"..x1; z = x1.."a"..x2 end 43 | assert(y == "xxaxx") 44 | assert(z == "xxayy") 45 | x1 = "xx" 46 | for i=1,100 do y = x1.."a"..x1; z = x1.."b"..x1 end 47 | assert(y == "xxaxx") 48 | assert(z == "xxbxx") 49 | end 50 | 51 | -- Append, CSE 52 | do 53 | local y, z 54 | local x = "a" 55 | for i=1,100 do 56 | y = x.."b" 57 | y = y.."c" 58 | end 59 | assert(y == "abc") 60 | x = "a" 61 | for i=1,100 do 62 | y = x.."b" 63 | z = y.."c" 64 | end 65 | assert(y == "ab") 66 | assert(z == "abc") 67 | x = "a" 68 | for i=1,100 do 69 | y = x.."b" 70 | z = y..i 71 | end 72 | assert(y == "ab") 73 | assert(z == "ab100") 74 | end 75 | 76 | -- Append, FOLD 77 | do 78 | local a, b = "x" 79 | for i=1,100 do b = (a.."y").."" end 80 | assert(b == "xy") 81 | end 82 | 83 | -- Append to buffer, sink 84 | do 85 | local x = "a" 86 | for i=1,100 do x = x.."b" end 87 | assert(x == "a"..string.rep("b", 100)) 88 | x = "a" 89 | for i=1,100 do x = x.."bc" end 90 | assert(x == "a"..string.rep("bc", 100)) 91 | end 92 | 93 | -- Append to two buffers in parallel, no append, no sink 94 | do 95 | local y, z = "xx", "yy" 96 | for i=1,100 do y = y.."a"; z = z.."b" end 97 | assert(y == "xx"..string.rep("a", 100)) 98 | assert(z == "yy"..string.rep("b", 100)) 99 | end 100 | 101 | -- Sink into side-exit 102 | do 103 | local x = "a" 104 | local z 105 | for i=1,200 do 106 | local y = x.."b" 107 | if i > 100 then 108 | z = y..i 109 | end 110 | end 111 | assert(z == "ab200") 112 | end 113 | 114 | -------------------------------------------------------------------------------- /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/constov.lua: -------------------------------------------------------------------------------- 1 | 2 | if not os.getenv("SLOWTEST") then return end 3 | 4 | do 5 | local t = { "local x\n" } 6 | for i=2,65537 do t[i] = "x="..i..".5\n" end 7 | assert(loadstring(table.concat(t)) ~= nil) 8 | t[65538] = "x=65538.5" 9 | assert(loadstring(table.concat(t)) == nil) 10 | end 11 | 12 | do 13 | local t = { "local x\n" } 14 | for i=2,65537 do t[i] = "x='"..i.."'\n" end 15 | assert(loadstring(table.concat(t)) ~= nil) 16 | t[65538] = "x='65538'" 17 | assert(loadstring(table.concat(t)) == nil) 18 | end 19 | 20 | -------------------------------------------------------------------------------- /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/debug_meta.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 | local t = setmetatable({}, mt) 33 | local t2 = setmetatable({}, mt) 34 | 35 | local x = t.x; ck("__index") 36 | t.x = 1; ck("__newindex") 37 | local x = t + t; ck("__add") 38 | local x = t - t; ck("__sub") 39 | local x = t * t; ck("__mul") 40 | local x = t / t; ck("__div") 41 | local x = t % t; ck("__mod") 42 | local x = t ^ t; ck("__pow") 43 | local x = -t; ck("__unm") 44 | --local x = #t; ck("__len") -- Not called for tables 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 | 55 | local u = newproxy() 56 | local u2 = newproxy() 57 | debug.setmetatable(u, mt) 58 | debug.setmetatable(u2, mt) 59 | 60 | local x = u.x; ck("__index") 61 | u.x = 1; ck("__newindex") 62 | local x = u + u; ck("__add") 63 | local x = u - u; ck("__sub") 64 | local x = u * u; ck("__mul") 65 | local x = u / u; ck("__div") 66 | local x = u % u; ck("__mod") 67 | local x = u ^ u; ck("__pow") 68 | local x = -u; ck("__unm") 69 | local x = #u; ck("__len") 70 | local x = u..u; ck("__concat") 71 | local x = u(); ck("local u") 72 | 73 | local x = u == u2; ck("__eq") 74 | local x = u ~= u2; ck("__eq") 75 | local x = u < u2; ck("__lt") 76 | local x = u > u2; ck("__lt") 77 | local x = u <= u2; ck("__le") 78 | local x = u >= u2; ck("__le") 79 | 80 | -------------------------------------------------------------------------------- /test/misc/dse_field.lua: -------------------------------------------------------------------------------- 1 | 2 | local getmetatable, setmetatable = getmetatable, setmetatable 3 | 4 | -- 1. Store with same ref and same value. All stores in loop eliminated. 5 | do 6 | local mt = {} 7 | local t = {} 8 | for i=1,100 do 9 | setmetatable(t, mt) 10 | assert(getmetatable(t) == mt) 11 | setmetatable(t, mt) 12 | assert(getmetatable(t) == mt) 13 | end 14 | assert(getmetatable(t) == mt) 15 | end 16 | 17 | -- 2. Store with different ref and same value. All stores in loop eliminated. 18 | do 19 | local mt = {} 20 | local t1 = {} 21 | local t2 = {} 22 | for i=1,100 do 23 | setmetatable(t1, mt) 24 | assert(getmetatable(t1) == mt) 25 | setmetatable(t2, mt) 26 | assert(getmetatable(t2) == mt) 27 | end 28 | assert(getmetatable(t1) == mt) 29 | assert(getmetatable(t2) == mt) 30 | end 31 | 32 | -- 3. Store with different ref and different value. Cannot eliminate any stores. 33 | do 34 | local mt1 = {} 35 | local mt2 = {} 36 | local t1 = {} 37 | local t2 = {} 38 | for i=1,100 do 39 | setmetatable(t1, mt1) 40 | assert(getmetatable(t1) == mt1) 41 | setmetatable(t2, mt2) 42 | assert(getmetatable(t2) == mt2) 43 | end 44 | assert(getmetatable(t1) == mt1) 45 | assert(getmetatable(t2) == mt2) 46 | end 47 | 48 | -- 4. Store with same ref and different value. 2nd store remains in loop. 49 | do 50 | local mt1 = {} 51 | local mt2 = {} 52 | local t = {} 53 | for i=1,100 do 54 | setmetatable(t, mt1) 55 | assert(getmetatable(t) == mt1) 56 | setmetatable(t, mt2) 57 | assert(getmetatable(t) == mt2) 58 | end 59 | assert(getmetatable(t) == mt2) 60 | end 61 | 62 | -- 5. Store with same ref, different value and aliased loads. 63 | -- Cannot eliminate any stores. 64 | do 65 | local mt1 = {} 66 | local mt2 = {} 67 | local t1 = {} 68 | local t2 = t1 69 | for i=1,100 do 70 | setmetatable(t1, mt1) 71 | assert(getmetatable(t2) == mt1) 72 | setmetatable(t1, mt2) 73 | assert(getmetatable(t2) == mt2) 74 | end 75 | assert(getmetatable(t1) == mt2) 76 | end 77 | 78 | -------------------------------------------------------------------------------- /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/exit_frame.lua: -------------------------------------------------------------------------------- 1 | do 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 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 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 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 | 81 | -------------------------------------------------------------------------------- /test/misc/exit_growstack.lua: -------------------------------------------------------------------------------- 1 | local function f(i) 2 | 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; 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 | if i==90 then return end -- Exit needs to grow stack before slot fill. 6 | end 7 | for j=1,5 do 8 | collectgarbage() -- Shrink stack. 9 | for i=1,100 do f(i) end 10 | end 11 | 12 | local function g(i) 13 | if i==90 then return end -- Exit needs to grow stack after slot fill. 14 | do return end 15 | do 16 | 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; 17 | 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; 18 | 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; 19 | end 20 | end 21 | for j=1,5 do 22 | collectgarbage() -- Shrink stack. 23 | for i=1,100 do g(i) end 24 | end 25 | -------------------------------------------------------------------------------- /test/misc/exit_jfuncf.lua: -------------------------------------------------------------------------------- 1 | 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 | 31 | -------------------------------------------------------------------------------- /test/misc/fac.lua: -------------------------------------------------------------------------------- 1 | local function fac(n) 2 | local x = 1 3 | for i=2,n do 4 | x = x * i 5 | end 6 | return x 7 | end 8 | 9 | if arg and arg[1] then 10 | print(fac(tonumber(arg[1]))) 11 | else 12 | assert(fac(10) == 3628800) 13 | end 14 | -------------------------------------------------------------------------------- /test/misc/fastfib.lua: -------------------------------------------------------------------------------- 1 | 2 | local function ffib(n) 3 | if n <= 2 then return n,1 end 4 | if n % 2 == 1 then 5 | local a,b = ffib((n-1)/2) 6 | local aa = a*a 7 | return aa+a*(b+b), aa+b*b 8 | else 9 | local a,b = ffib(n/2-1) 10 | local ab = a+b 11 | return ab*ab+a*a, (ab+b)*a 12 | end 13 | end 14 | 15 | local function fib(n) 16 | return (ffib(n)) 17 | end 18 | 19 | if arg and arg[1] then 20 | local n = tonumber(arg and arg[1]) or 10 21 | io.write(string.format("Fib(%d): %.0f\n", n, fib(n))) 22 | else 23 | assert(fib(40) == 165580141) 24 | assert(fib(39) == 102334155) 25 | assert(fib(77) == 8944394323791464) 26 | end 27 | -------------------------------------------------------------------------------- /test/misc/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 | if arg and arg[1] then 7 | local n = tonumber(arg[1]) or 10 8 | io.write(string.format("Fib(%d): %d\n", n, fib(n))) 9 | else 10 | assert(fib(27) == 317811) 11 | end 12 | -------------------------------------------------------------------------------- /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/fuse.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Don't fuse i+101 on x64. 3 | -- Except if i is sign-extended to 64 bit or addressing is limited to 32 bit. 4 | do 5 | local t = {} 6 | for i=-100,-1 do t[i+101] = 1 end 7 | end 8 | 9 | -------------------------------------------------------------------------------- /test/misc/fwd_hrefk_rollback.lua: -------------------------------------------------------------------------------- 1 | 2 | -- https://github.com/LuaJIT/LuaJIT/issues/124 3 | 4 | local function foo(a, b, f) 5 | return f and (a.f0 < b.f1 and 6 | b.f0 < a.f1 and 7 | a.f2 < b.f3 and 8 | b.f2 < a.f3) 9 | end 10 | 11 | local function bar(f0, f1, f2, f3, X, f) 12 | for _, v in ipairs(X) do 13 | local b = {} 14 | b.f0 = 0 15 | b.f2 = v 16 | b.f1 = b.f0 + 1 17 | b.f3 = b.f2 + 1 18 | 19 | if foo({f0 = f0, f1 = f1, f2 = f2, f3 = f3}, b, f) then 20 | return false 21 | end 22 | end 23 | 24 | return true 25 | end 26 | 27 | local X = { 0, 1, 0, 0 } 28 | 29 | for i = 1, 20 do 30 | assert(bar(0, 1, 2, 3, X, true)) 31 | end 32 | 33 | assert(not bar(0, 1, 1, 2, X, true)) 34 | 35 | -------------------------------------------------------------------------------- /test/misc/fwd_tnew_tdup.lua: -------------------------------------------------------------------------------- 1 | 2 | -- 1. 3 | do 4 | local x = 2 5 | for i=1,100 do 6 | local t = {} -- TNEW: DCE 7 | x = t.foo -- HREF -> niltv: folded 8 | end 9 | assert(x == nil) 10 | end 11 | 12 | -- 2. 13 | do 14 | local x = 2 15 | for i=1,100 do 16 | local t = {1} -- TDUP: DCE 17 | x = t.foo -- HREF -> niltv: folded 18 | end 19 | assert(x == nil) 20 | end 21 | 22 | -- 3. 23 | do 24 | local x = 2 25 | for i=1,100 do 26 | local t = {} 27 | t[1] = 11 -- NEWREF + HSTORE 28 | x = t[1] -- AREF + ALOAD, no forwarding, no fold 29 | end 30 | assert(x == 11) 31 | end 32 | 33 | -- 4. HREFK not eliminated. Ditto for the EQ(FLOAD(t, #tab.hmask), k). 34 | do 35 | local x = 2 36 | for i=1,100 do 37 | local t = {} 38 | t.foo = 11 -- NEWREF + HSTORE 39 | x = t.foo -- HREFK + HLOAD: store forwarding 40 | end 41 | assert(x == 11) 42 | end 43 | 44 | -- 5. HREFK not eliminated. Ditto for the EQ(FLOAD(t, #tab.hmask), k). 45 | do 46 | local x = 2 47 | for i=1,100 do 48 | local t = {foo=11} -- TDUP 49 | x = t.foo -- HREFK + non-nil HLOAD: folded 50 | end 51 | assert(x == 11) 52 | end 53 | 54 | -- 6. 55 | do 56 | local x = 2 57 | local k = 1 58 | for i=1,100 do 59 | local t = {[0]=11} -- TDUP 60 | t[k] = 22 -- AREF + ASTORE aliasing 61 | x = t[0] -- AREF + ALOAD, no fold 62 | end 63 | assert(x == 11) 64 | end 65 | 66 | -- 7. 67 | do 68 | local setmetatable = setmetatable 69 | local mt = { __newindex = function(t, k, v) 70 | assert(k == "foo") 71 | assert(v == 11) 72 | end } 73 | for i=1,100 do 74 | local t = setmetatable({}, mt) 75 | t.foo = 11 76 | end 77 | end 78 | 79 | -------------------------------------------------------------------------------- /test/misc/fwd_upval.lua: -------------------------------------------------------------------------------- 1 | 2 | -- 1. Open upvalue above base slot, aliasing an SSA value. 3 | do 4 | local x = 7 5 | local function a() x = x + 1 end 6 | local function b() x = x + 2 end 7 | for i=1,100 do a(); b(); x = x + 5 end 8 | assert(x == 807) 9 | end 10 | 11 | -- 2. Open upvalue below base slot. UREFO CSE for a.x + b.x, but not x in loop. 12 | -- ULOAD not disambiguated. 2x ULOAD + 2x USTORE (+ 1x DSE USTORE). 13 | do 14 | local x = 7 15 | (function() 16 | local function a() x = x + 1 end 17 | local function b() x = x + 2 end 18 | for i=1,100 do a(); b(); x = x + 5 end 19 | end)() 20 | assert(x == 807) 21 | end 22 | 23 | -- 3. Closed upvalue. UREFC CSE for a.x + b.x, but not x in loop. 24 | -- ULOAD not disambiguated. 2x ULOAD + 2x USTORE (+ 1x DSE for USTORE). 25 | do 26 | local xx = (function() 27 | local x = 7 28 | local function a() x = x + 1 end 29 | local function b() x = x + 2 end 30 | return function() for i=1,100 do a(); b(); x = x + 5 end; return x end 31 | end)()() 32 | assert(xx == 807) 33 | end 34 | 35 | -- 4. Open upvalue below base slot. Forwarded. 1x USTORE (+ 1x DSE USTORE). 36 | do 37 | local x = 7 38 | (function() 39 | local function a() x = x + 1 end 40 | for i=1,100 do a(); a() end 41 | end)() 42 | assert(x == 207) 43 | end 44 | 45 | -- 5. Closed upvalue. Forwarded. 1x USTORE (+ 1x DSE USTORE). 46 | do 47 | local xx = (function() 48 | local x = 7 49 | return function() 50 | local function a() x = x + 1 end 51 | for i=1,100 do a(); a() end 52 | return x 53 | end 54 | end)()() 55 | assert(xx == 207) 56 | end 57 | 58 | -------------------------------------------------------------------------------- /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(96) == 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/getfenv.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local x 4 | local function f() 5 | x = getfenv(0) 6 | end 7 | local co = coroutine.create(f) 8 | local t = {} 9 | debug.setfenv(co, t) 10 | for i=1,50 do f() f() f() end 11 | assert(x == getfenv(0)) 12 | coroutine.resume(co) 13 | assert(x == t) 14 | end 15 | 16 | -------------------------------------------------------------------------------- /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/hstore_elimination.lua: -------------------------------------------------------------------------------- 1 | local clone = require "table.clone" 2 | local nkeys = require "table.nkeys" 3 | local c, n 4 | local t = {idx = 0} 5 | 6 | -- jit.off() 7 | 8 | for i = 1, 100000 do 9 | t.idx = nil 10 | n = nkeys(t) 11 | c = clone(t) 12 | t.idx = i 13 | end 14 | 15 | -- print(n, c.idx) 16 | assert(n==0) 17 | assert(c.idx==nil) 18 | -------------------------------------------------------------------------------- /test/misc/iter-bug.lua: -------------------------------------------------------------------------------- 1 | -- from Mike Pall 2 | 3 | if jit and jit.opt then jit.opt.start("maxside=0") end 4 | local t={1}; for i=1,100 do for k,v in pairs(t) do end end 5 | -------------------------------------------------------------------------------- /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/jit_record.lua: -------------------------------------------------------------------------------- 1 | if jit and jit.opt then jit.opt.start("hotloop=2", "hotexit=1", "maxsnap=9") end 2 | 3 | local m = 1 4 | 5 | local function foo(n) 6 | m = m + n 7 | if n >= 2 then 8 | m = m * n 9 | end 10 | end 11 | 12 | foo(1); foo(1); foo(1); foo(1); foo(1); foo(1); 13 | 14 | local tb = { 15 | foo = 1, 16 | bar = 2, 17 | } 18 | 19 | local function bar() 20 | for i = 2, 3 do 21 | foo(i); 22 | end 23 | 24 | tb.foo = 10 25 | 26 | print(tb.foo) 27 | end 28 | 29 | bar() 30 | 31 | print(m) 32 | -------------------------------------------------------------------------------- /test/misc/jloop-itern-stack-check-fix.lua: -------------------------------------------------------------------------------- 1 | -- reproducer from Mike Pall for the fix in commit dad04f1754 in the official 2 | -- v2.1 branch. 3 | 4 | -- Trace exit (stack check) to JLOOP originating in ITERN. 5 | do 6 | local function f(t) 7 | do 8 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 9 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 10 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 11 | end 12 | local n = 0 13 | for k in pairs(t) do 14 | n = n + 1 15 | end 16 | return n 17 | end 18 | 19 | local x = 0 20 | for i=1,20 do 21 | local t = {} 22 | for i=1,20 do t[i] = true end 23 | collectgarbage() 24 | x = x + f(t) 25 | end 26 | assert(x == 400) 27 | end 28 | -------------------------------------------------------------------------------- /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(tostring(lightud(2^47)) == "userdata: 0x800000000000") 32 | assert(tostring(lightud(2^64-2048)) == "userdata: 0x8000000000000000") 33 | -- assert(pcall(lightud, 2^64-2048) == false) 34 | assert(tostring(lightud(2^47 + 1)) == "userdata: 0x800000000001") 35 | assert(tostring(lightud(2^59 - 42)) == "userdata: 0x07ffffffffffffc0") 36 | end 37 | 38 | assert(getmetatable(lightud(1)) == nil) 39 | 40 | -- lightuserdata SLOAD value and HREF key 41 | do 42 | local ud = lightud(12345) 43 | local t = {[ud] = 42} 44 | for i=1,100 do 45 | assert(t[ud] == 42) 46 | end 47 | end 48 | 49 | -- lightuserdata NEWREF key 50 | do 51 | local ud = lightud(12345) 52 | for i=1,100 do 53 | local t = {[ud] = 42} 54 | assert(t[ud] == 42) 55 | end 56 | end 57 | 58 | -- lightuserdata ASTORE/HSTORE value 59 | do 60 | local ud = lightud(12345) 61 | local t = {} 62 | for i=1,100 do 63 | t[i] = ud 64 | end 65 | assert(t[100] == ud) 66 | end 67 | 68 | -- lightuserdata sync to stack 69 | do 70 | local ud = lightud(12345) 71 | local x = nil 72 | for j=1,20 do 73 | for i=1,50 do 74 | x = ud 75 | end 76 | assert(x == ud) 77 | end 78 | end 79 | 80 | -- lightuserdata vs. number type check 81 | do 82 | local t = {} 83 | for i=1,200 do t[i] = i end 84 | t[180] = lightud(12345) 85 | local x = 0 86 | assert(not pcall(function(t) 87 | for i=1,200 do x = x + t[i] end 88 | end, t)) 89 | assert(x == 16110) 90 | end 91 | 92 | -------------------------------------------------------------------------------- /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/math_random.lua: -------------------------------------------------------------------------------- 1 | 2 | local random = math.random 3 | local randomseed = math.randomseed 4 | 5 | do 6 | local N = 1000 7 | local min, max = math.min, math.max 8 | for j=1,100 do 9 | randomseed(j) 10 | local lo, hi, sum = math.huge, -math.huge, 0 11 | for i=1,N do 12 | local x = random() 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 | -------------------------------------------------------------------------------- /test/misc/meta_arith.lua: -------------------------------------------------------------------------------- 1 | 2 | local function create(arith, v1, v2) 3 | local meta = { 4 | __add=function(a,b) return arith("add", a, b) end, 5 | __sub=function(a,b) return arith("sub", a, b) end, 6 | __mul=function(a,b) return arith("mul", a, b) end, 7 | __div=function(a,b) return arith("div", a, b) end, 8 | __mod=function(a,b) return arith("mod", a, b) end, 9 | __pow=function(a,b) return arith("pow", a, b) end, 10 | __unm=function(a,b) return arith("unm", a, b) end, 11 | } 12 | return setmetatable({v1}, meta), setmetatable({v2}, meta) 13 | end 14 | 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 | 24 | local a, b = create(function(op,a,b) return a[1] end, "foo", 42) 25 | assert(a+b == "foo") 26 | assert(a-b == "foo") 27 | assert(a*b == "foo") 28 | assert(a/b == "foo") 29 | assert(a%b == "foo") 30 | assert(a^b == "foo") 31 | assert(-a == "foo") 32 | 33 | local a, b = create(function(op,a,b) return b[1] end, 42, "foo") 34 | assert(a+b == "foo") 35 | assert(a-b == "foo") 36 | assert(a*b == "foo") 37 | assert(a/b == "foo") 38 | assert(a%b == "foo") 39 | assert(a^b == "foo") 40 | assert(-a == 42) 41 | 42 | 43 | local a, b = create(function(op,a,b) return a[1]+b end, 39), 3 44 | assert(a+b == 42) 45 | assert(a-b == 42) 46 | assert(a*b == 42) 47 | assert(a/b == 42) 48 | assert(a%b == 42) 49 | assert(a^b == 42) 50 | 51 | local a, b = 39, create(function(op,a,b) return a+b[1] end, 3) 52 | assert(a+b == 42) 53 | assert(a-b == 42) 54 | assert(a*b == 42) 55 | assert(a/b == 42) 56 | assert(a%b == 42) 57 | assert(a^b == 42) 58 | 59 | 60 | local a, b = "39", 3 61 | assert(a+b == 42) 62 | assert(a-b == 36) 63 | assert(a*b == 117) 64 | assert(a/b == 13) 65 | assert(a%b == 0) 66 | assert(a^b == 59319) 67 | assert(-a == -39) 68 | 69 | local a, b = 39, "3" 70 | assert(a+b == 42) 71 | assert(a-b == 36) 72 | assert(a*b == 117) 73 | assert(a/b == 13) 74 | assert(a%b == 0) 75 | assert(a^b == 59319) 76 | assert(-a == -39) 77 | 78 | local a, b = "39", "3" 79 | assert(a+b == 42) 80 | assert(a-b == 36) 81 | assert(a*b == 117) 82 | assert(a/b == 13) 83 | assert(a%b == 0) 84 | assert(a^b == 59319) 85 | assert(-a == -39) 86 | 87 | 88 | local a = "39" 89 | assert(a+3 == 42) 90 | assert(a-3 == 36) 91 | assert(a*3 == 117) 92 | assert(a/3 == 13) 93 | assert(a%3 == 0) 94 | assert(a^3 == 59319) 95 | 96 | local b = "3" 97 | assert(39+b == 42) 98 | assert(39-b == 36) 99 | assert(39*b == 117) 100 | assert(39/b == 13) 101 | assert(39%b == 0) 102 | assert(39^b == 59319) 103 | 104 | -------------------------------------------------------------------------------- /test/misc/meta_arith_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 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 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 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/misc/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 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 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 | debug.setmetatable(0, meta) 31 | local o,a,b = (42)() 32 | assert(o == 42 and a == nil and b == nil) 33 | local o,a,b = (42)("foo") 34 | assert(o == 42 and a == "foo" and b == nil) 35 | local o,a,b = (42)("foo", "bar") 36 | assert(o == 42 and a == "foo" and b == "bar") 37 | debug.setmetatable(0, nil) 38 | 39 | do 40 | local tc = setmetatable({}, { __call = function(o,a,b) return o end}) 41 | local ta = setmetatable({}, { __add = tc}) 42 | local o,a = ta + ta 43 | assert(o == tc and a == nil) 44 | 45 | getmetatable(tc).__call = function(o,a,b) return a end 46 | local o,a = ta + ta 47 | assert(o == ta and a == nil) 48 | end 49 | 50 | do 51 | local t = setmetatable({}, { __call = function(t, a) return 100-a end }) 52 | for i=1,100 do assert(t(i) == 100-i) end 53 | end 54 | 55 | do 56 | local t = setmetatable({}, { __call = rawget }) 57 | for i=1,100 do t[i] = 100-i end 58 | for i=1,100 do assert(t(i) == 100-i) end 59 | end 60 | 61 | debug.setmetatable(0, { __call = function(n) return 100-n end }) 62 | for i=1,100 do assert((i)() == 100-i) end 63 | debug.setmetatable(0, nil) 64 | 65 | do 66 | local t = setmetatable({}, { __newindex = pcall, __call = rawset }) 67 | for i=1,100 do t[i] = 100-i end 68 | for i=1,100 do assert(t[i] == 100-i) end 69 | end 70 | 71 | do 72 | local t = setmetatable({}, { 73 | __index = pcall, __newindex = rawset, 74 | __call = function(t, i) t[i] = 100-i end, 75 | }) 76 | for i=1,100 do assert(t[i] == true and rawget(t, i) == 100-i) end 77 | end 78 | 79 | -------------------------------------------------------------------------------- /test/misc/meta_cat.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local a, b, c = "foo", "bar", "baz" 4 | assert(a..b == "foobar") 5 | assert(a..b..c == "foobarbaz") 6 | end 7 | 8 | local function create(cat, v1, v2) 9 | local meta = { __concat = cat } 10 | return setmetatable({v1}, meta), setmetatable({v2}, meta) 11 | end 12 | 13 | do 14 | local a, b = create(function(a, b) return a end) 15 | assert(a..b == a) 16 | assert(b..a == b) 17 | assert(a..b..b == a) 18 | assert(a..a..b == a) 19 | assert(a..b..a == a) 20 | assert(a..b..b..b..b..b..b..b == a) 21 | end 22 | 23 | do 24 | local a, b = create(function(a, b) return b end) 25 | assert(a..b == b) 26 | assert(b..a == a) 27 | assert(a..b..b == b) 28 | assert(a..a..b == b) 29 | assert(b..b..a == a) 30 | assert(a..a..a..a..a..a..a..b == b) 31 | end 32 | 33 | do 34 | local a, b = create(function(a, b) 35 | return (type(a) == "string" and a or a[1]).. 36 | (type(b) == "string" and b or b[1]) 37 | end, "a", "b") 38 | assert(a..b == "ab") 39 | assert(a..b == "ab") 40 | assert(a..b..b == "abb") 41 | assert(a..b..a == "aba") 42 | assert(a..a..a..a..a..a..a..b == "aaaaaaab") 43 | assert(a..a..a.."x".."x"..a..a..b == "aaaxxaab") 44 | assert("x"..a..a..a..a..a..a..b == "xaaaaaab") 45 | assert(a..b..a..b..a.."x".."x".."x" == "ababaxxx") 46 | end 47 | 48 | do 49 | local a, b = create(function(a, b) 50 | if a ~= b then local x = gg end 51 | return (type(a) == "string" and a or a[1]).. 52 | (type(b) == "string" and b or b[1]) 53 | end, "a", "b") 54 | local y 55 | for i=1,100 do y = a..b end 56 | assert(y == "ab") 57 | for i=1,100 do y = a..b.."x" end 58 | assert(y == "abx") 59 | for i=1,100 do y = a..b.. 1 .. "z" end 60 | assert(y == "ab1z") 61 | end 62 | 63 | -------------------------------------------------------------------------------- /test/misc/meta_eq.lua: -------------------------------------------------------------------------------- 1 | 2 | local function create(equal, v1, v2) 3 | local meta = { __eq = equal } 4 | return setmetatable({v1}, meta), setmetatable({v2}, meta) 5 | end 6 | 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 | 17 | local a, b = create(function(a,b) return a[1] == b[1] end, 1, 2) 18 | assert(a==b == false) 19 | assert(a~=b == true) 20 | 21 | b[1] = 1 22 | assert(a==b == true) 23 | assert(a~=b == false) 24 | 25 | a[1] = 2 26 | assert(a==b == false) 27 | assert(a~=b == true) 28 | 29 | 30 | local function obj_eq(a, b) 31 | assert(a==b == true) 32 | assert(a~=b == false) 33 | end 34 | 35 | local function obj_ne(a, b) 36 | assert(a==b == false) 37 | assert(a~=b == true) 38 | end 39 | 40 | obj_eq(nil, nil) 41 | obj_ne(nil, false) 42 | obj_ne(nil, true) 43 | 44 | obj_ne(false, nil) 45 | obj_eq(false, false) 46 | obj_ne(false, true) 47 | 48 | obj_ne(true, nil) 49 | obj_ne(true, false) 50 | obj_eq(true, true) 51 | 52 | obj_eq(1, 1) 53 | obj_ne(1, 2) 54 | obj_ne(2, 1) 55 | 56 | obj_eq("a", "a") 57 | obj_ne("a", "b") 58 | obj_ne("a", 1) 59 | obj_ne(1, "a") 60 | 61 | local t, t2 = {}, {} 62 | obj_eq(t, t) 63 | obj_ne(t, t2) 64 | obj_ne(t, 1) 65 | obj_ne(t, "") 66 | 67 | -------------------------------------------------------------------------------- /test/misc/meta_eq_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 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 | 37 | -------------------------------------------------------------------------------- /test/misc/meta_framegap.lua: -------------------------------------------------------------------------------- 1 | 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 | -------------------------------------------------------------------------------- /test/misc/meta_getset.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local t = setmetatable({}, { __metatable = "foo" }) 4 | for i=1,100 do assert(getmetatable(t) == "foo") end 5 | end 6 | 7 | do 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 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 30 | local x = true 31 | for i=1,100 do x = getmetatable(i) end 32 | assert(x == nil) 33 | end 34 | 35 | -------------------------------------------------------------------------------- /test/misc/meta_len.lua: -------------------------------------------------------------------------------- 1 | 2 | local lua52 = os.getenv("LUA52") 3 | 4 | local mt = { __len = function(o, o2) 5 | if lua52 then 6 | assert(o2 == o) 7 | else 8 | assert(o2 == nil) 9 | end 10 | return 42 11 | end } 12 | 13 | do 14 | local t = {1,2,3} 15 | assert(#t == 3) 16 | assert(#"abcdef" == 6) 17 | 18 | setmetatable(t, { __foo = function() end }) 19 | assert(#t == 3) 20 | assert(#t == 3) 21 | 22 | setmetatable(t, mt) 23 | if lua52 then 24 | assert(#t == 42) -- __len DOES work on tables. 25 | assert(rawlen(t) == 3) 26 | else 27 | assert(#t == 3) -- __len does NOT work on tables. 28 | end 29 | end 30 | 31 | do 32 | local u = newproxy(true) 33 | getmetatable(u).__len = function(o) return 42 end 34 | assert(#u == 42) 35 | local x = 0 36 | for i=1,100 do x = x + #u end 37 | assert(x == 4200) 38 | end 39 | 40 | debug.setmetatable(0, mt) 41 | assert(#1 == 42) 42 | debug.setmetatable(0, nil) 43 | 44 | -------------------------------------------------------------------------------- /test/misc/meta_nomm.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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/misc/meta_pairs.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 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 | if os.getenv("LUA52") then 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 | -------------------------------------------------------------------------------- /test/misc/meta_tget.lua: -------------------------------------------------------------------------------- 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 | 14 | 15 | local x 16 | local t2=setmetatable({}, {__index=function(t,k) 17 | x = k 18 | end}) 19 | 20 | assert(t2[1] == nil) 21 | assert(x == 1) 22 | 23 | assert(t2.foo == nil) 24 | assert(x == "foo") 25 | 26 | -------------------------------------------------------------------------------- /test/misc/meta_tget_nontab.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local u = newproxy(true) 4 | getmetatable(u).__index = { foo = u, bar = 42 } 5 | 6 | local x = 0 7 | for i=1,100 do 8 | x = x + u.bar 9 | u = u.foo 10 | end 11 | assert(x == 4200) 12 | 13 | x = 0 14 | for i=1,100 do 15 | u = u.foo 16 | x = x + u.bar 17 | end 18 | assert(x == 4200) 19 | end 20 | 21 | do 22 | local s = "foo" 23 | string.s = s 24 | local x = 0 25 | local t = {} 26 | for i=1,100 do 27 | x = x + s:len() 28 | s = s.s 29 | t[s] = t -- Hash store with same type prevents hoisting 30 | end 31 | assert(x == 300) 32 | end 33 | 34 | -------------------------------------------------------------------------------- /test/misc/meta_tset.lua: -------------------------------------------------------------------------------- 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 | 16 | -------------------------------------------------------------------------------- /test/misc/meta_tset_nilget.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local count = 0 4 | local t = setmetatable({ foo = nil }, 5 | { __newindex=function() count = count + 1 end }) 6 | for j=1,2 do 7 | for i=1,100 do t.foo = 1 end 8 | rawset(t, "foo", 1) 9 | end 10 | assert(count == 100) 11 | end 12 | 13 | do 14 | local count = 0 15 | local t = setmetatable({ nil }, 16 | { __newindex=function() count = count + 1 end }) 17 | for j=1,2 do 18 | for i=1,100 do t[1] = 1 end 19 | rawset(t, 1, 1) 20 | end 21 | assert(count == 100) 22 | end 23 | 24 | -------------------------------------------------------------------------------- /test/misc/meta_tset_resize.lua: -------------------------------------------------------------------------------- 1 | local grandparent = {} 2 | grandparent.__newindex = function(s,_,_) tostring(s) end 3 | 4 | local parent = {} 5 | parent.__newindex = parent 6 | parent.bar = 1 7 | setmetatable(parent, grandparent) 8 | 9 | local child = setmetatable({}, parent) 10 | child.foo = _ 11 | -------------------------------------------------------------------------------- /test/misc/meta_tset_str.lua: -------------------------------------------------------------------------------- 1 | 2 | local t=setmetatable({}, {__newindex=function(t,k,v) 3 | assert(v == "foo"..k) 4 | rawset(t, k, "bar"..k) 5 | end}) 6 | 7 | for i=1,100 do t[i]="foo"..i end 8 | for i=1,100 do assert(t[i] == "bar"..i) end 9 | 10 | for i=1,100 do t[i]="baz"..i end 11 | for i=1,100 do assert(t[i] == "baz"..i) end 12 | 13 | local t=setmetatable({foo=1,bar=1,baz=1},{}) 14 | t.baz=nil 15 | t.baz=2 16 | t.baz=nil 17 | t.baz=2 18 | 19 | -------------------------------------------------------------------------------- /test/misc/modulo.lua: -------------------------------------------------------------------------------- 1 | 2 | for x=-5,5 do 3 | for y=-5,5 do 4 | if y ~= 0 then 5 | assert(x%y == x-math.floor(x/y)*y) 6 | end 7 | end 8 | end 9 | 10 | for x=-5,5,0.25 do 11 | for y=-5,5,0.25 do 12 | if y ~= 0 then 13 | assert(x%y == x-math.floor(x/y)*y) 14 | end 15 | end 16 | end 17 | 18 | do 19 | local y = 0 20 | for x=-100,123 do 21 | y = y + x%17 22 | end 23 | assert(y == 1777) 24 | end 25 | 26 | do 27 | local y = 0 28 | for x=-100,123 do 29 | if x ~= 0 then 30 | y = y + 85%x 31 | end 32 | end 33 | assert(y == 2059) 34 | end 35 | 36 | do 37 | local x = 1%0 38 | assert(x ~= x) 39 | x = math.floor(0/0) 40 | assert(x ~= x) 41 | end 42 | 43 | -------------------------------------------------------------------------------- /test/misc/multi_result_call_next.lua: -------------------------------------------------------------------------------- 1 | -- from Mike Pall 2 | 3 | do 4 | local xnext = next 5 | local t = {1} 6 | local function f() end 7 | for i=1,100 do 8 | f(xnext(t)) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/misc/nsieve.lua: -------------------------------------------------------------------------------- 1 | local function nsieve(m, isPrime) 2 | for i=2,m do isPrime[i] = true end 3 | local count = 0 4 | for i=2,m do 5 | if isPrime[i] then 6 | for k=i+i,m,i do isPrime[k] = false end 7 | count = count + 1 8 | end 9 | end 10 | return count 11 | end 12 | 13 | local flags = {} 14 | if arg and arg[1] then 15 | local N = tonumber(arg and arg[1]) 16 | io.write(string.format("Primes up to %8d %8d", N, nsieve(N,flags)), "\n") 17 | else 18 | assert(nsieve(100, flags) == 25) 19 | assert(nsieve(12345, flags) == 1474) 20 | end 21 | -------------------------------------------------------------------------------- /test/misc/pairs_bug.lua: -------------------------------------------------------------------------------- 1 | local t = {1,2,3,4,5} 2 | local tab = {a=t,b=t,c=t,d=t,e=t} 3 | 4 | local function f(...) 5 | for j=1,100 do end 6 | end 7 | 8 | for i=1, 100000 do 9 | f() -- force return to interpreter 10 | local c = 0 11 | for k,v in pairs(tab) do -- this will eventually be blacklisted and patched to ITERC/JMP 12 | for _ in pairs(v) do end 13 | c = c+1 14 | end 15 | assert(c == 5) -- eventually c=1 16 | end 17 | -------------------------------------------------------------------------------- /test/misc/parse_andor.lua: -------------------------------------------------------------------------------- 1 | local x = ((1 or false) and true) or false 2 | assert(x == true) 3 | 4 | local basiccases = { 5 | {"nil", nil}, 6 | {"false", false}, 7 | {"true", true}, 8 | {"10", 10}, 9 | } 10 | 11 | local mem = {basiccases} -- for memoization 12 | 13 | local function allcases (n) 14 | if mem[n] then return mem[n] end 15 | local res = {} 16 | -- include all smaller cases 17 | for _, v in ipairs(allcases(n - 1)) do 18 | res[#res + 1] = v 19 | end 20 | for i = 1, n - 1 do 21 | for _, v1 in ipairs(allcases(i)) do 22 | for _, v2 in ipairs(allcases(n - i)) do 23 | res[#res + 1] = { 24 | "(" .. v1[1] .. " and " .. v2[1] .. ")", 25 | v1[2] and v2[2] 26 | } 27 | res[#res + 1] = { 28 | "(" .. v1[1] .. " or " .. v2[1] .. ")", 29 | v1[2] or v2[2] 30 | } 31 | end 32 | end 33 | end 34 | mem[n] = res -- memoize 35 | return res 36 | end 37 | 38 | for _, v in pairs(allcases(4)) do 39 | local res = loadstring("return " .. v[1])() 40 | if res ~= v[2] then 41 | error(string.format("bad conditional eval\n%s\nexpected: %s\ngot: %s", 42 | v[1], tostring(v[2]), tostring(res))) 43 | end 44 | end 45 | 46 | do 47 | -- 0001 KSHORT 1 2 48 | -- 0002 ISGE 0 1 49 | -- 0003 JMP 1 => 0006 50 | -- 0004 KSHORT 1 1 51 | -- 0005 JMP 1 => 0013 52 | -- ^^^ must be 2 53 | -- fix in jmp_patchtestreg 54 | local function fib(n) return (n < 2) and 1 or fib(n-1)+fib(n-2) end 55 | assert(fib(5) == 8) 56 | assert(fib(10) == 89) 57 | end 58 | 59 | -------------------------------------------------------------------------------- /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_hex.lua: -------------------------------------------------------------------------------- 1 | assert(1e5 == 100000) 2 | assert(1e+5 == 100000) 3 | assert(1e-5 == 0.00001) 4 | assert(0xe+9 == 23) 5 | assert(0xep9 == 7168) 6 | assert(0xep+9 == 7168) 7 | assert(0xep-9 == 0.02734375) 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/pcall_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 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 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 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 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 | 76 | -------------------------------------------------------------------------------- /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/phi_copyspill.lua: -------------------------------------------------------------------------------- 1 | function mat4mul(a11, a21, a31, a41, 2 | a12, a22, a32, a42, 3 | a13, a23, a33, a43, 4 | a14, a24, a34, a44, 5 | b11, b21, b31, b41, 6 | b12, b22, b32, b42, 7 | b13, b23, b33, b43, 8 | b14, b24, b34, b44) 9 | return a11*b11+a21*b12+a31*b13+a41*b14, 10 | a11*b21+a21*b22+a31*b23+a41*b24, 11 | a11*b31+a21*b32+a31*b33+a41*b34, 12 | a11*b41+a21*b42+a31*b43+a41*b44, 13 | a12*b11+a22*b12+a32*b13+a42*b14, 14 | a12*b21+a22*b22+a32*b23+a42*b24, 15 | a12*b31+a22*b32+a32*b33+a42*b34, 16 | a12*b41+a22*b42+a32*b43+a42*b44, 17 | a13*b11+a23*b12+a33*b13+a43*b14, 18 | a13*b21+a23*b22+a33*b23+a43*b24, 19 | a13*b31+a23*b32+a33*b33+a43*b34, 20 | a13*b41+a23*b42+a33*b43+a43*b44, 21 | a14*b11+a24*b12+a34*b13+a44*b14, 22 | a14*b21+a24*b22+a34*b23+a44*b24, 23 | a14*b31+a24*b32+a34*b33+a44*b34, 24 | a14*b41+a24*b42+a34*b43+a44*b44 25 | end 26 | 27 | local a11, a21, a31, a41 = 1, 0, 0, 0 28 | local a12, a22, a32, a42 = 0, 1, 0, 0 29 | local a13, a23, a33, a43 = 0, 0, 1, 0 30 | local a14, a24, a34, a44 = 0, 0, 0, 1 31 | 32 | local b11, b21, b31, b41 = 0, 0, -1, 0 33 | local b12, b22, b32, b42 = 0, 1, 0, 0 34 | local b13, b23, b33, b43 = 1, 0, 0, 0 35 | local b14, b24, b34, b44 = 0, 0, 0, 1 36 | 37 | for i = 1, 1000 do 38 | a11, a21, a31, a41, 39 | a12, a22, a32, a42, 40 | a13, a23, a33, a43, 41 | a14, a24, a34, a44 = mat4mul(a11, a21, a31, a41, 42 | a12, a22, a32, a42, 43 | a13, a23, a33, a43, 44 | a14, a24, a34, a44, 45 | b11, b21, b31, b41, 46 | b12, b22, b32, b42, 47 | b13, b23, b33, b43, 48 | b14, b24, b34, b44) 49 | end 50 | assert(a11 == 1) 51 | assert(a31 == 0) 52 | -------------------------------------------------------------------------------- /test/misc/phi_ref.lua: -------------------------------------------------------------------------------- 1 | -- rref points into invariant part 2 | do 3 | local x,y=1,2; for i=1,100 do x=x+y; y=i end 4 | assert(y == 100) 5 | end 6 | 7 | do 8 | local x,y=1,2; for i=1,100.5 do x=x+y; y=i end 9 | assert(y == 100) 10 | end 11 | 12 | do 13 | local x,y=1,2; for i=1,100 do x,y=y,x end 14 | assert(x == 1) 15 | assert(y == 2) 16 | end 17 | 18 | do 19 | local x,y,z=1,2,3; for i=1,100 do x,y,z=y,z,x end 20 | assert(x == 2) 21 | assert(y == 3) 22 | assert(z == 1) 23 | end 24 | 25 | do 26 | local x,y,z=1,2,3; for i=1,100 do x,y,z=z,x,y end 27 | assert(x == 3) 28 | assert(y == 1) 29 | assert(z == 2) 30 | end 31 | 32 | do 33 | local a,x,y,z=0,1,2,3; for i=1,100 do a=a+x; x=y; y=z; z=i end 34 | assert(a == 4759) 35 | assert(x == 98) 36 | assert(y == 99) 37 | assert(z == 100) 38 | end 39 | 40 | -- variant slot, but no corresponding SLOAD 41 | do 42 | local x,y=1,2; for i=1,100 do x=i; y=i-1 end 43 | assert(x == 100) 44 | assert(y == 99) 45 | end 46 | 47 | do 48 | local x,y=1,2; for i=1,100 do x=i; y=i+1 end 49 | assert(x == 100) 50 | assert(y == 101) 51 | end 52 | 53 | do 54 | local x=0; for i=1,100 do if i==90 then break end x=i end 55 | assert(x == 89) 56 | end 57 | 58 | -- dup lref from variant slot (suppressed) 59 | do 60 | local x,y=1,2; for i=1,100 do x=i; y=i end 61 | assert(x == 100) 62 | assert(y == 100) 63 | end 64 | 65 | -- const rref 66 | do 67 | local x,y=1,2 local bxor,tobit=bit.bxor,bit.tobit; 68 | for i=1,100 do x=bxor(i,y); y=tobit(i+1) end 69 | assert(x == 0) 70 | assert(y == 101) 71 | end 72 | 73 | -- dup rref (ok) 74 | do 75 | local x,y,z1,z2=1,2,3,4 local bxor,tobit=bit.bxor,bit.tobit; 76 | for i=1,100 do x=bxor(i,y); z2=tobit(i+5); z1=bxor(x,i+5); y=tobit(i+1) end 77 | assert(x == 0) 78 | assert(y == 101) 79 | assert(z1 == 105) 80 | assert(z2 == 105) 81 | end 82 | 83 | -- variant slot, no corresponding SLOAD, 84 | do 85 | for i=1,5 do 86 | local a, b = 1, 2 87 | local bits = 0 88 | while a ~= b do 89 | bits = bits + 1 90 | a = b 91 | b = bit.lshift(b, 1) 92 | end 93 | assert(bits == 32) 94 | end 95 | end 96 | 97 | -- don't eliminate PHI if referenced from snapshot 98 | do 99 | local t = { 0 } 100 | local a = 0 101 | for i=1,100 do 102 | local b = t[1] 103 | t[1] = i + a 104 | a = b 105 | end 106 | assert(a == 2500) 107 | assert(t[1] == 2550) 108 | end 109 | 110 | -- don't eliminate PHI if referenced from snapshot 111 | do 112 | local x = 1 113 | local function f() 114 | local t = {} 115 | for i=1,200 do t[i] = i end 116 | for i=1,200 do 117 | local x1 = x 118 | x = t[i] 119 | if i > 100 then return x1 end 120 | end 121 | end 122 | assert(f() == 100) 123 | end 124 | 125 | -- don't eliminate PHI if referenced from another non-redundant PHI 126 | do 127 | local t = {} 128 | for i=1,256 do 129 | local a, b, k = i, math.floor(i/2), -i 130 | while a > 1 and t[b] > k do 131 | t[a] = t[b] 132 | a = b 133 | b = math.floor(a/2) 134 | end 135 | t[a] = k 136 | end 137 | local x = 0 138 | for i=1,256 do x = x + bit.bxor(i, t[i]) end 139 | assert(x == -41704) 140 | end 141 | 142 | -------------------------------------------------------------------------------- /test/misc/phi_rot18.lua: -------------------------------------------------------------------------------- 1 | local function rot18r(N) 2 | local a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 3 | for x=1,N do 4 | a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=r,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q 5 | end 6 | return table.concat{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r} 7 | end 8 | 9 | local function rot18l(N) 10 | local a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 11 | for x=1,N do 12 | a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,a 13 | end 14 | return table.concat{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r} 15 | end 16 | 17 | assert(rot18r(0) == "123456789101112131415161718") 18 | assert(rot18r(10) == "910111213141516171812345678") 19 | assert(rot18r(105) == "456789101112131415161718123") 20 | assert(rot18r(0) == "123456789101112131415161718") 21 | assert(rot18r(1) == "181234567891011121314151617") 22 | assert(rot18r(2) == "171812345678910111213141516") 23 | assert(rot18r(0) == "123456789101112131415161718") 24 | assert(rot18r(1) == "181234567891011121314151617") 25 | assert(rot18r(2) == "171812345678910111213141516") 26 | assert(rot18r(105) == "456789101112131415161718123") 27 | 28 | assert(rot18l(0) == "123456789101112131415161718") 29 | assert(rot18l(10) == "111213141516171812345678910") 30 | assert(rot18l(105) == "161718123456789101112131415") 31 | assert(rot18l(0) == "123456789101112131415161718") 32 | assert(rot18l(1) == "234567891011121314151617181") 33 | assert(rot18l(2) == "345678910111213141516171812") 34 | assert(rot18l(0) == "123456789101112131415161718") 35 | assert(rot18l(1) == "234567891011121314151617181") 36 | assert(rot18l(2) == "345678910111213141516171812") 37 | 38 | assert(rot18r(100) == "910111213141516171812345678") 39 | assert(rot18l(100) == "111213141516171812345678910") 40 | -------------------------------------------------------------------------------- /test/misc/phi_rot8.lua: -------------------------------------------------------------------------------- 1 | local function rot8r(n) 2 | local a,b,c,d,e,f,g,h=1,2,3,4,5,6,7,8 3 | for x=1,n do 4 | a,b,c,d,e,f,g,h=h,a,b,c,d,e,f,g 5 | end 6 | return table.concat{a,b,c,d,e,f,g,h} 7 | end 8 | 9 | local function rot8l(n) 10 | local a,b,c,d,e,f,g,h=1,2,3,4,5,6,7,8 11 | for x=1,n do 12 | a,b,c,d,e,f,g,h=b,c,d,e,f,g,h,a 13 | end 14 | return table.concat{a,b,c,d,e,f,g,h} 15 | end 16 | 17 | assert(rot8r(0) == "12345678") 18 | assert(rot8r(10) == "78123456") 19 | assert(rot8r(105) == "81234567") 20 | assert(rot8r(0) == "12345678") 21 | assert(rot8r(1) == "81234567") 22 | assert(rot8r(2) == "78123456") 23 | assert(rot8r(0) == "12345678") 24 | assert(rot8r(1) == "81234567") 25 | assert(rot8r(2) == "78123456") 26 | assert(rot8r(105) == "81234567") 27 | 28 | assert(rot8l(0) == "12345678") 29 | assert(rot8l(10) == "34567812") 30 | assert(rot8l(105) == "23456781") 31 | assert(rot8l(0) == "12345678") 32 | assert(rot8l(1) == "23456781") 33 | assert(rot8l(2) == "34567812") 34 | assert(rot8l(0) == "12345678") 35 | assert(rot8l(1) == "23456781") 36 | assert(rot8l(2) == "34567812") 37 | 38 | assert(rot8r(100) == "56781234") 39 | assert(rot8l(100) == "56781234") 40 | -------------------------------------------------------------------------------- /test/misc/phi_rot9.lua: -------------------------------------------------------------------------------- 1 | local function rot9r(n) 2 | local a,b,c,d,e,f,g,h,i=1,2,3,4,5,6,7,8,9 3 | for x=1,n do 4 | a,b,c,d,e,f,g,h,i=i,a,b,c,d,e,f,g,h 5 | end 6 | return table.concat{a,b,c,d,e,f,g,h,i} 7 | end 8 | 9 | local function rot9l(n) 10 | local a,b,c,d,e,f,g,h,i=1,2,3,4,5,6,7,8,9 11 | for x=1,n do 12 | a,b,c,d,e,f,g,h,i=b,c,d,e,f,g,h,i,a 13 | end 14 | return table.concat{a,b,c,d,e,f,g,h,i} 15 | end 16 | 17 | assert(rot9r(0) == "123456789") 18 | assert(rot9r(10) == "912345678") 19 | assert(rot9r(105) == "456789123") 20 | assert(rot9r(0) == "123456789") 21 | assert(rot9r(1) == "912345678") 22 | assert(rot9r(2) == "891234567") 23 | assert(rot9r(0) == "123456789") 24 | assert(rot9r(1) == "912345678") 25 | assert(rot9r(2) == "891234567") 26 | assert(rot9r(105) == "456789123") 27 | 28 | assert(rot9l(0) == "123456789") 29 | assert(rot9l(10) == "234567891") 30 | assert(rot9l(105) == "789123456") 31 | assert(rot9l(0) == "123456789") 32 | assert(rot9l(1) == "234567891") 33 | assert(rot9l(2) == "345678912") 34 | assert(rot9l(0) == "123456789") 35 | assert(rot9l(1) == "234567891") 36 | assert(rot9l(2) == "345678912") 37 | 38 | assert(rot9r(100) == "912345678") 39 | assert(rot9l(100) == "234567891") 40 | -------------------------------------------------------------------------------- /test/misc/phi_rotx.lua: -------------------------------------------------------------------------------- 1 | local function rot9r(n, m) 2 | local a,b,c,d,e,f,g,h,i=1,2,3,4,5,6,7,8,9 3 | local s = "" 4 | for x=1,n do 5 | a,b,c,d,e,f,g,h,i=i,a,b,c,d,e,f,g,h 6 | if x == m then s = table.concat{a,b,c,d,e,f,g,h,i} end 7 | c,d = d,c 8 | end 9 | return table.concat{a,b,c,d,e,f,g,h,i, s} 10 | end 11 | 12 | assert(rot9r(0,0) == "123456789") 13 | assert(rot9r(10,0) == "893124567") 14 | assert(rot9r(105,0) == "913245678") 15 | assert(rot9r(105,90) == "913245678891324567") 16 | assert(rot9r(0,0) == "123456789") 17 | assert(rot9r(1,0) == "913245678") 18 | assert(rot9r(2,0) == "893124567") 19 | assert(rot9r(1,1) == "913245678912345678") 20 | assert(rot9r(2,1) == "893124567912345678") 21 | assert(rot9r(2,2) == "893124567891324567") 22 | -------------------------------------------------------------------------------- /test/misc/recsum.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 | for i=1,tonumber(arg and arg[1]) or 100 do 8 | assert(sum(100) == 5050) 9 | end 10 | end 11 | 12 | -------------------------------------------------------------------------------- /test/misc/recsump.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local abs = math.abs 4 | local function sum(n) 5 | if n == 1 then return 1 end 6 | return abs(n + sum(n-1)) 7 | end 8 | for i=1,tonumber(arg and arg[1]) or 100 do 9 | assert(sum(100) == 5050) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /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/select.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local x = 0 4 | for i=1,100 do 5 | x = x + select("#", 3, 4) 6 | end 7 | assert(x == 200) 8 | end 9 | 10 | do 11 | local x = 0 12 | for i=1,100 do 13 | x = x + select("#", math.modf(i)) 14 | end 15 | assert(x == 200) 16 | end 17 | 18 | do 19 | local x = 0 20 | for i=1,100 do 21 | x = x + select(1, i) 22 | end 23 | assert(x == 5050) 24 | end 25 | 26 | do 27 | local x, y = 0, 0 28 | for i=1,100 do 29 | local a, b = select(2, 1, i, i+10) 30 | x = x + a 31 | y = y + b 32 | end 33 | assert(x == 5050 and y == 6050) 34 | end 35 | 36 | do 37 | local function f(a, ...) 38 | local x = 0 39 | for i=1,select('#', ...) do 40 | x = x + select(i, ...) 41 | end 42 | assert(x == a) 43 | end 44 | for i=1,100 do 45 | f(1, 1) 46 | f(3, 1, 2) 47 | f(15, 1, 2, 3, 4, 5) 48 | f(0) 49 | f(3200, string.byte(string.rep(" ", 100), 1, 100)) 50 | end 51 | end 52 | 53 | do 54 | local function f(a, ...) 55 | local x = 0 56 | for i=1,20 do 57 | local b = select(i, ...) 58 | if b then x = x + b else x = x + 9 end 59 | end 60 | assert(x == a) 61 | end 62 | for i=1,100 do 63 | f(172, 1) 64 | f(165, 1, 2) 65 | f(150, 1, 2, 3, 4, 5) 66 | f(180) 67 | f(640, string.byte(string.rep(" ", 100), 1, 100)) 68 | end 69 | end 70 | 71 | do 72 | local function f(a, ...) 73 | local x = 0 74 | for i=1,20 do 75 | local b = select(4, ...) 76 | if b then x = x + b else x = x + 9 end 77 | end 78 | assert(x == a) 79 | end 80 | for i=1,100 do 81 | f(180, 1) 82 | f(180, 1, 2) 83 | f(80, 1, 2, 3, 4, 5) 84 | f(180) 85 | f(640, string.byte(string.rep(" ", 100), 1, 100)) 86 | end 87 | end 88 | 89 | -------------------------------------------------------------------------------- /test/misc/self.lua: -------------------------------------------------------------------------------- 1 | local t={} 2 | 3 | function t:set(x) 4 | self.a=x 5 | end 6 | 7 | function t:get() 8 | return self.a 9 | end 10 | 11 | t:set("foo") 12 | assert(t:get() == "foo") 13 | assert(t.a == "foo") 14 | 15 | t:set(42) 16 | assert(t:get() == 42) 17 | assert(t.a == 42) 18 | 19 | -------------------------------------------------------------------------------- /test/misc/sink_nosink.lua: -------------------------------------------------------------------------------- 1 | 2 | local assert = assert 3 | 4 | -- Cannot sink TNEW, aliased load. 5 | do 6 | local k = 1 7 | for i=1,100 do local t={i}; assert(t[k]==i) end 8 | for i=1,100 do local t={}; t[k]=i; assert(t[1]==i) end 9 | end 10 | 11 | -- Cannot sink TNEW, escaping to upvalue. 12 | do 13 | (function() 14 | local uv 15 | return function() 16 | for i=1,100 do uv = {i} end 17 | assert(uv[1] == 100) 18 | end 19 | end)()() 20 | end 21 | 22 | -- Cannot sink TNEW, escaping through a store. 23 | do 24 | local t = {} 25 | for i=1,100 do t[1] = {i} end 26 | for i=1,100 do t.foo = {i} end 27 | for i=1,100 do setmetatable(t, {i}) end 28 | assert(t[1][1] == 100) 29 | assert(t.foo[1] == 100) 30 | assert(getmetatable(t)[1] == 100) 31 | end 32 | 33 | -- Cannot sink TNEW, iteratively escaping through a store. 34 | do 35 | local t = {} 36 | for i=1,100 do t[1] = {i}; t[1][1] = {i} end 37 | assert(t[1][1][1] == 100) 38 | end 39 | 40 | -- Cannot sink TNEW, escaping to next iteration (unused in 1st variant). 41 | do 42 | local t; 43 | for i=1,200 do t = {i} end 44 | assert(t[1] == 200) 45 | for i=1,200 do if i > 100 then assert(t[1] == i-1) end t = {i} end 46 | assert(t[1] == 200) 47 | end 48 | 49 | -- Cannot sink TNEW, escaping to next iteration (snapshot ref). 50 | do 51 | local t,x 52 | for i=1,100 do x=t; t={i} end 53 | assert(t[1] == 100) 54 | assert(x[1] == 99) 55 | end 56 | 57 | -- Cannot sink TNEW, escaping to next iteration (IR/snapshot ref). 58 | do 59 | local t 60 | for i=1,100 do t={t} end 61 | assert(type(t[1][1][1]) == "table") 62 | end 63 | 64 | -- Could sink outer TNEW, but the logic for stores to PHI allocs is too simple. 65 | -- Cannot sink inner TNEW, escaping to next iteration (IR ref). 66 | do 67 | local t = {42, 43} 68 | for i=1,100 do t={t[2], {i}} end 69 | assert(t[2][1] == 100) 70 | assert(t[1][1] == 99) 71 | end 72 | 73 | -- Cannot sink TNEW, cross-PHI ref (and snapshot ref). 74 | do 75 | local x,y 76 | for i=1,100 do x,y={i},x end 77 | assert(x[1] == 100) 78 | assert(y[1] == 99) 79 | end 80 | 81 | -- Cannot sink TNEW, cross-PHI ref (and snapshot ref). 82 | do 83 | local x,y 84 | for i=1,100 do x,y=y,{i} end 85 | assert(x[1] == 99) 86 | assert(y[1] == 100) 87 | end 88 | 89 | -- Cannot sink TNEW, escaping to exit. 90 | do 91 | local function f(n, t) 92 | if n == 0 then return t end 93 | return (f(n-1, {t})) 94 | end 95 | local t = f(100, 42) 96 | assert(type(t[1][1][1]) == "table") 97 | t = f(3, 42) 98 | assert(t[1][1][1] == 42) 99 | end 100 | 101 | -- Cannot sink TNEW, escaping to exit. 102 | do 103 | local function f(n) 104 | if n == 0 then return 42 end 105 | local t = f(n-1) 106 | return {t} 107 | end 108 | for i=1,20 do 109 | local t = f(100) 110 | assert(type(t[1][1][1]) == "table") 111 | end 112 | t = f(3) 113 | assert(t[1][1][1] == 42) 114 | end 115 | 116 | -- Cannot sink, since nested inner table is non-PHI. 117 | do 118 | local a, b = {{1}}, {{1}} 119 | for i=1,10000 do -- Need to force GC exit sometimes 120 | a = {{a[1][1]+b[1][1]}} 121 | end 122 | assert(a[1][1] == 10001) 123 | end 124 | 125 | -------------------------------------------------------------------------------- /test/misc/snap_gcexit.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local x = 0 4 | local t 5 | for i=1,1000 do 6 | if i >= 100 then 7 | -- causes an exit for atomic phase 8 | -- must not merge snapshot #0 with comparison since it has the wrong PC 9 | if i < 150 then x=x+1 end 10 | t = {i} 11 | end 12 | end 13 | assert(x == 50) 14 | assert(t[1] == 1000) 15 | end 16 | 17 | -------------------------------------------------------------------------------- /test/misc/snap_top.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | function randomtable(entries, depth) 4 | if depth == 0 then 5 | return tostring(math.random(2)) -- snapshot between return and CALLMT 6 | end 7 | local t = {} 8 | for k=1,entries do 9 | t[k] = randomtable(entries, depth-1) 10 | end 11 | return t 12 | end 13 | 14 | local t = randomtable(10, 2) 15 | end 16 | 17 | -------------------------------------------------------------------------------- /test/misc/snap_top2.lua: -------------------------------------------------------------------------------- 1 | 2 | local function f() 3 | gcinfo() 4 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 5 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 6 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 7 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 8 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 9 | local _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ 10 | end 11 | 12 | for i=1,100 do 13 | f() 14 | if i % 3 == 0 then collectgarbage() end 15 | end 16 | -------------------------------------------------------------------------------- /test/misc/sort.lua: -------------------------------------------------------------------------------- 1 | -- Really a test for lua_lessthan() 2 | 3 | local N = 1000 4 | 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 | 11 | math.randomseed(42) 12 | local t = {} 13 | for i=1,N do t[i] = math.random(N).."" end 14 | table.sort(t) 15 | for i=2,N do assert(t[i-1] <= t[i]) end 16 | 17 | math.randomseed(42) 18 | local mt = { __lt = function(a,b) return a[1] < b[1] end } 19 | local t = {} 20 | for i=1,N do t[i] = setmetatable({ math.random(N) }, mt) end 21 | table.sort(t) 22 | for i=2,N do assert(t[i-1][1] <= t[i][1]) end 23 | 24 | -------------------------------------------------------------------------------- /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 | 12 | print("[[" .. first .. "]]") 13 | -- stackov.lua:2: stack overflow 14 | assert(string.match(first, ":"..line..": stack overflow$") or 15 | string.match(first, "error in error handling") or 16 | first == "stack overflow" or 17 | first == "stackov.lua:2: stack overflow") 18 | 19 | local n = 1 20 | for _ in string.gmatch(s, "\n") do n = n + 1 end 21 | assert(n == 1+1+11+1+10 or n == 1) 22 | 23 | local function g(i) 24 | g(i) 25 | end 26 | 27 | local err, s = xpcall(g, debug.traceback, 1) 28 | assert(err == false) 29 | 30 | --[[ 31 | -- too slow 32 | local function vtail(...) 33 | return vtail(1, ...) 34 | end 35 | 36 | local err, s = xpcall(vtail, debug.traceback, 1) 37 | assert(err == false) 38 | --]] 39 | 40 | local function vcall(...) 41 | vcall(1, ...) 42 | end 43 | 44 | local err, s = xpcall(vcall, debug.traceback, 1) 45 | assert(err == false) 46 | 47 | -------------------------------------------------------------------------------- /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/stitch.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local tonumber = tonumber 4 | local function octal(s) return tonumber(s, 8) end 5 | for i=1,100 do 6 | octal("1") 7 | octal("1") 8 | octal("1") 9 | end 10 | end 11 | 12 | do 13 | local t = { 14 | [0] = function() end, 15 | coroutine.wrap(function() while true do coroutine.yield() end end), 16 | } 17 | for i=1,100 do 18 | t[i % 2]() 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /test/misc/strcmp.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local a = "\255\255\255\255" 4 | local b = "\1\1\1\1" 5 | 6 | assert(a > b) 7 | assert(a > b) 8 | assert(a >= b) 9 | assert(b <= a) 10 | end 11 | 12 | -------------------------------------------------------------------------------- /test/misc/string_byte.lua: -------------------------------------------------------------------------------- 1 | 2 | local band, bor = bit.band, bit.bor 3 | local byte = string.byte 4 | 5 | -- Fixed slice [i,i+k] or overflow 6 | do 7 | local s = "abcdefg" 8 | local x,y,z 9 | for j=100,107 do 10 | for i=1,j do x,y,z = byte("abcdefg", band(i, 7), band(i+2, 7)) end 11 | local a,b,c = byte("abcdefg", band(j, 7), band(j+2, 7)) 12 | assert(x == a and y == b and z == c) 13 | end 14 | for j=100,107 do 15 | for i=1,j do x,y,z = byte(s, band(i, 7), band(i+2, 7)) end 16 | local a,b,c = byte(s, band(j, 7), band(j+2, 7)) 17 | assert(x == a and y == b and z == c) 18 | end 19 | end 20 | 21 | -- Positive slice [i,len] or overflow 22 | do 23 | local s = "abc" 24 | local x,y,z 25 | for j=100,107 do 26 | for i=1,j do x,y,z = byte("abc", band(i, 7), -1) end 27 | local a,b,c = byte("abc", band(j, 7), -1) 28 | assert(x == a and y == b and z == c) 29 | end 30 | for j=100,107 do 31 | for i=1,j do x,y,z = byte(s, band(i, 7), -1) end 32 | local a,b,c = byte(s, band(j, 7), -1) 33 | assert(x == a and y == b and z == c) 34 | end 35 | end 36 | 37 | -- Negative slice [-i,len] or underflow 38 | do 39 | local s = "abc" 40 | local x,y,z 41 | for j=-100,-107,-1 do 42 | for i=-1,j,-1 do x,y,z = byte("abc", bor(i, -8), -1) end 43 | local a,b,c = byte("abc", bor(j, -8), -1) 44 | assert(x == a and y == b and z == c) 45 | end 46 | for j=-100,-107,-1 do 47 | for i=-1,j,-1 do x,y,z = byte(s, bor(i, -8), -1) end 48 | local a,b,c = byte(s, bor(j, -8), -1) 49 | assert(x == a and y == b and z == c) 50 | end 51 | end 52 | 53 | -- Positive slice [1,i] or overflow 54 | do 55 | local s = "abc" 56 | local x,y,z 57 | for j=100,107 do 58 | for i=1,j do x,y,z = byte("abc", 1, band(i, 7)) end 59 | local a,b,c = byte("abc", 1, band(j, 7)) 60 | assert(x == a and y == b and z == c) 61 | end 62 | for j=100,107 do 63 | for i=1,j do x,y,z = byte(s, 1, band(i, 7)) end 64 | local a,b,c = byte(s, 1, band(j, 7)) 65 | assert(x == a and y == b and z == c) 66 | end 67 | end 68 | 69 | -- Negative slice [1,-i] or underflow 70 | do 71 | local s = "abc" 72 | local x,y,z 73 | for j=-100,-107,-1 do 74 | for i=-1,j,-1 do x,y,z = byte("abc", 1, bor(i, -8)) end 75 | local a,b,c = byte("abc", 1, bor(j, -8)) 76 | assert(x == a and y == b and z == c) 77 | end 78 | for j=-100,-107,-1 do 79 | for i=-1,j,-1 do x,y,z = byte(s, 1, bor(i, -8)) end 80 | local a,b,c = byte(s, 1, bor(j, -8)) 81 | assert(x == a and y == b and z == c) 82 | end 83 | end 84 | 85 | -- Check for slot stack overflow 86 | do 87 | local s = string.rep("x", 500) 88 | for i=1,100 do byte(s, 1, 500) end 89 | end 90 | 91 | -------------------------------------------------------------------------------- /test/misc/string_char.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local y 4 | for i=1,100 do y = string.char(65) end 5 | assert(y == "A") 6 | local x = 97 7 | for i=1,100 do y = string.char(x) end 8 | assert(y == "a") 9 | x = "98" 10 | for i=1,100 do y = string.char(x) end 11 | assert(y == "b") 12 | for i=1,100 do y = string.char(32+i) end 13 | assert(y == "\132") 14 | end 15 | 16 | do 17 | local y 18 | assert(not pcall(function() 19 | for i=1,200 do y = string.char(100+i) end 20 | end)) 21 | assert(y == "\255") 22 | end 23 | 24 | do 25 | local y 26 | for i=1,100 do y = string.char(65, 66, i, 67, 68) end 27 | assert(y == "ABdCD") 28 | end 29 | -------------------------------------------------------------------------------- /test/misc/string_dump.lua: -------------------------------------------------------------------------------- 1 | 2 | -- Must unpatch modified bytecode with ILOOP/JLOOP etc. 3 | do 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 | jit.off(foo) 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 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/misc/string_op.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local y 4 | for i=1,100 do y = string.reverse("abc") end 5 | assert(y == "cba") 6 | local x = "abcd" 7 | for i=1,100 do y = string.reverse(x) end 8 | assert(y == "dcba") 9 | x = 1234 10 | for i=1,100 do y = string.reverse(x) end 11 | assert(y == "4321") 12 | end 13 | 14 | do 15 | local y 16 | for i=1,100 do y = string.upper("aBc9") end 17 | assert(y == "ABC9") 18 | local x = ":abCd+" 19 | for i=1,100 do y = string.upper(x) end 20 | assert(y == ":ABCD+") 21 | x = 1234 22 | for i=1,100 do y = string.upper(x) end 23 | assert(y == "1234") 24 | end 25 | 26 | do 27 | local y 28 | for i=1,100 do y = string.lower("aBc9") end 29 | assert(y == "abc9") 30 | local x = ":abcd+" 31 | for i=1,100 do y = string.lower(x) end 32 | assert(y == ":abcd+") 33 | x = 1234 34 | for i=1,100 do y = string.lower(x) end 35 | assert(y == "1234") 36 | end 37 | 38 | do 39 | local t, y = {}, {} 40 | for i=1,100 do t[i] = string.char(i, 16+i, 32+i) end 41 | for i=1,100 do t[i] = string.reverse(t[i]) end 42 | assert(t[100] == "\132\116\100") 43 | for i=1,100 do t[i] = string.reverse(t[i]) end 44 | for i=1,100 do assert(t[i] == string.char(i, 16+i, 32+i)) end 45 | for i=1,100 do y[i] = string.upper(t[i]) end 46 | assert(y[65] == "AQA") 47 | assert(y[97] == "AQ\129") 48 | assert(y[100] == "DT\132") 49 | for i=1,100 do y[i] = string.lower(t[i]) end 50 | assert(y[65] == "aqa") 51 | assert(y[97] == "aq\129") 52 | assert(y[100] == "dt\132") 53 | end 54 | 55 | do 56 | local y, z 57 | local x = "aBcDe" 58 | for i=1,100 do 59 | y = string.upper(x) 60 | z = y.."fgh" 61 | end 62 | assert(y == "ABCDE") 63 | assert(z == "ABCDEfgh") 64 | end 65 | 66 | do 67 | local y 68 | for i=1,100 do y = string.rep("a", 10) end 69 | assert(y == "aaaaaaaaaa") 70 | for i=1,100 do y = string.rep("ab", 10) end 71 | assert(y == "abababababababababab") 72 | for i=1,100 do y = string.rep("ab", 10, "c") end 73 | assert(y == "abcabcabcabcabcabcabcabcabcab") 74 | local x = "a" 75 | for i=1,100 do y = string.rep(x, 10) end 76 | assert(y == "aaaaaaaaaa") 77 | local n = 10 78 | for i=1,100 do y = string.rep(x, n) end 79 | assert(y == "aaaaaaaaaa") 80 | x = "ab" 81 | for i=1,100 do y = string.rep(x, n) end 82 | assert(y == "abababababababababab") 83 | x = 12 84 | n = "10" 85 | for i=1,100 do y = string.rep(x, n) end 86 | assert(y == "12121212121212121212") 87 | end 88 | 89 | do 90 | local t = {} 91 | for i=1,100 do t[i] = string.rep("ab", i-85) end 92 | assert(t[100] == "ababababababababababababababab") 93 | for i=1,100 do t[i] = string.rep("ab", i-85, "c") end 94 | assert(t[85] == "") 95 | assert(t[86] == "ab") 96 | assert(t[87] == "abcab") 97 | assert(t[100] == "abcabcabcabcabcabcabcabcabcabcabcabcabcabcab") 98 | end 99 | 100 | do 101 | local y, z 102 | local x = "ab" 103 | for i=1,100 do 104 | y = string.rep(x, i-90) 105 | z = y.."fgh" 106 | end 107 | assert(y == "abababababababababab") 108 | assert(z == "ababababababababababfgh") 109 | end 110 | 111 | -------------------------------------------------------------------------------- /test/misc/string_sub.lua: -------------------------------------------------------------------------------- 1 | 2 | local band, bor = bit.band, bit.bor 3 | local sub = string.sub 4 | 5 | -- Positive slice [i,len] or overflow 6 | do 7 | local s = "abc" 8 | local x 9 | for j=100,107 do 10 | for i=1,j do x = sub("abc", band(i, 7)) end 11 | assert(x == sub("abc", band(j, 7))) 12 | end 13 | for j=100,107 do 14 | for i=1,j do x = sub(s, band(i, 7)) end 15 | assert(x == sub(s, band(j, 7))) 16 | end 17 | end 18 | 19 | -- Negative slice [-i,len] or underflow 20 | do 21 | local s = "abc" 22 | local x 23 | for j=-100,-107,-1 do 24 | for i=-1,j,-1 do x = sub("abc", bor(i, -8)) end 25 | assert(x == sub("abc", bor(j, -8))) 26 | end 27 | for j=-100,-107,-1 do 28 | for i=-1,j,-1 do x = sub(s, bor(i, -8)) end 29 | assert(x == sub(s, bor(j, -8))) 30 | end 31 | end 32 | 33 | -- Positive slice [1,i] or overflow 34 | do 35 | local s = "abc" 36 | local x 37 | for j=100,107 do 38 | for i=1,j do x = sub("abc", 1, band(i, 7)) end 39 | assert(x == sub("abc", 1, band(j, 7))) 40 | end 41 | for j=100,107 do 42 | for i=1,j do x = sub(s, 1, band(i, 7)) end 43 | assert(x == sub(s, 1, band(j, 7))) 44 | end 45 | end 46 | 47 | -- Negative slice [1,-i] or underflow 48 | do 49 | local s = "abc" 50 | local x 51 | for j=-100,-107,-1 do 52 | for i=-1,j,-1 do x = sub("abc", 1, bor(i, -8)) end 53 | assert(x == sub("abc", 1, bor(j, -8))) 54 | end 55 | for j=-100,-107,-1 do 56 | for i=-1,j,-1 do x = sub(s, 1, bor(i, -8)) end 57 | assert(x == sub(s, 1, bor(j, -8))) 58 | end 59 | end 60 | 61 | -------------------------------------------------------------------------------- /test/misc/string_sub_opt.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local s = "abcde" 4 | local x = 0 5 | for i=1,100 do 6 | if string.sub(s, 1, 1) == "a" then x = x + 1 end 7 | end 8 | assert(x == 100) 9 | end 10 | 11 | do 12 | local s = "abcde" 13 | local x = 0 14 | for i=1,100 do 15 | if string.sub(s, 1, 1) == "b" then x = x + 1 end 16 | end 17 | assert(x == 0) 18 | end 19 | 20 | do 21 | local s = "abcde" 22 | local x = 0 23 | for i=1,100 do 24 | if string.sub(s, 1, 1) == "ab" then x = x + 1 end 25 | end 26 | assert(x == 0) 27 | end 28 | 29 | do 30 | local s = "abcde" 31 | local x = 0 32 | for i=1,100 do 33 | if string.sub(s, 1, 2) == "a" then x = x + 1 end 34 | end 35 | assert(x == 0) 36 | end 37 | 38 | do 39 | local s = "abcde" 40 | local x = 0 41 | local k = 1 42 | for i=1,100 do 43 | if string.sub(s, 1, k) == "a" then x = x + 1 end 44 | end 45 | assert(x == 100) 46 | end 47 | 48 | do 49 | local s = "abcde" 50 | local x = 0 51 | local k = 1 52 | for i=1,100 do 53 | if string.sub(s, 1, k) == "b" then x = x + 1 end 54 | end 55 | assert(x == 0) 56 | end 57 | 58 | do 59 | local s = "abcde" 60 | local x = 0 61 | local k = 1 62 | for i=1,100 do 63 | if string.sub(s, 1, k) == "ab" then x = x + 1 end 64 | end 65 | assert(x == 0) 66 | end 67 | 68 | ---- 69 | 70 | do 71 | local s = "abcde" 72 | local x = 0 73 | for i=1,100 do 74 | if string.sub(s, 1, 2) == "ab" then x = x + 1 end 75 | end 76 | assert(x == 100) 77 | end 78 | 79 | do 80 | local s = "abcde" 81 | local x = 0 82 | for i=1,100 do 83 | if string.sub(s, 1, 3) == "abc" then x = x + 1 end 84 | end 85 | assert(x == 100) 86 | end 87 | 88 | do 89 | local s = "abcde" 90 | local x = 0 91 | for i=1,100 do 92 | if string.sub(s, 1, 4) == "abcd" then x = x + 1 end 93 | end 94 | assert(x == 100) 95 | end 96 | 97 | do 98 | local t = {} 99 | local line = string.rep("..XX", 100) 100 | local i = 1 101 | local c = line:sub(i, i) 102 | while c ~= "" and c ~= "Z" do 103 | t[i] = c == "X" and "Y" or c 104 | i = i + 1 105 | c = line:sub(i, i) 106 | end 107 | assert(table.concat(t) == string.rep("..YY", 100)) 108 | end 109 | 110 | -------------------------------------------------------------------------------- /test/misc/table_alias.lua: -------------------------------------------------------------------------------- 1 | local t = {} 2 | local ta = t 3 | local s = 0 4 | for i = 1, 1000 do 5 | ta[i] = i 6 | s = s + #t 7 | end 8 | assert(s==500500) 9 | -------------------------------------------------------------------------------- /test/misc/table_insert.lua: -------------------------------------------------------------------------------- 1 | 2 | local tinsert = table.insert 3 | local assert = assert 4 | 5 | do 6 | local t = {} 7 | for i=1,100 do t[i] = i end 8 | for i=1,100 do tinsert(t, i) end 9 | assert(#t == 200 and t[100] == 100 and t[200] == 100) 10 | end 11 | 12 | do 13 | local t = {} 14 | for i=1,200 do t[i] = i end 15 | for i=101,200 do tinsert(t, i, i) end 16 | assert(#t == 300 and t[101] == 101 and t[200] == 200 and t[300] == 200) 17 | end 18 | 19 | -------------------------------------------------------------------------------- /test/misc/table_remove.lua: -------------------------------------------------------------------------------- 1 | 2 | local tremove = table.remove 3 | local assert = assert 4 | 5 | do 6 | local t = {} 7 | for i=1,200 do t[i] = i end 8 | for i=1,100 do tremove(t) end 9 | assert(#t == 100 and t[100] == 100) 10 | end 11 | 12 | do 13 | local t = {} 14 | for i=1,200 do t[i] = i end 15 | for i=1,100 do assert(tremove(t) == 201-i) end 16 | assert(#t == 100 and t[100] == 100) 17 | end 18 | 19 | do 20 | local t = {} 21 | for i=1,200 do t[i] = i end 22 | for i=1,100 do assert(tremove(t, 1) == i) end 23 | assert(#t == 100 and t[100] == 200) 24 | end 25 | 26 | -------------------------------------------------------------------------------- /test/misc/tak.lua: -------------------------------------------------------------------------------- 1 | 2 | local function tak(x, y, z) 3 | if y >= x then return z end 4 | return tak(tak(x-1, y, z), tak(y-1, z, x), (tak(z-1, x, y))) 5 | end 6 | 7 | if arg and arg[1] then 8 | local N = tonumber(arg and arg[1]) or 7 9 | print(tak(3*N, 2*N, N)) 10 | else 11 | assert(tak(21, 14, 7) == 14) 12 | end 13 | -------------------------------------------------------------------------------- /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/tlen_loop.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 | end 8 | 9 | do 10 | local t = {} 11 | t[90] = 999 12 | for i=1,100 do t[#t+1] = i end 13 | assert(#t > 100 and t[#t] == 100) 14 | end 15 | 16 | do 17 | local t = {} 18 | for i=1,100 do t[i] = i end 19 | t[10] = nil 20 | for i=1,99 do t[#t] = nil end 21 | assert(#t == 0) 22 | end 23 | 24 | -------------------------------------------------------------------------------- /test/misc/tnew_tdup.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 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 | 17 | -------------------------------------------------------------------------------- /test/misc/tonumber_tostring.lua: -------------------------------------------------------------------------------- 1 | 2 | do 3 | local x = 0 4 | for i=1,100 do x = x + tonumber(i) end 5 | assert(x == 5050) 6 | end 7 | 8 | do 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 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 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 31 | for i=1,100 do assert(tonumber({}) == nil) end 32 | end 33 | 34 | do 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 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 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 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 75 | assert(tonumber(111, 2) == 7) 76 | end 77 | 78 | do 79 | local t = setmetatable({}, { __tostring = "" }) 80 | assert(pcall(function() tostring(t) end) == false) 81 | end 82 | 83 | -------------------------------------------------------------------------------- /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/unordered.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 x,y = 0/0,1 9 | 10 | check(xx, false) 13 | check(x>=x, false) 14 | check(x==x, false) 15 | check(x~=x, true) 16 | 17 | check(xy, false) 20 | check(x>=y, false) 21 | check(x==y, false) 22 | check(x~=y, true) 23 | 24 | check(yx, false) 27 | check(y>=x, false) 28 | check(y==x, false) 29 | check(y~=x, true) 30 | 31 | check(x<1, false) 32 | check(x<=1, false) 33 | check(x>1, false) 34 | check(x>=1, false) 35 | check(x==1, false) 36 | check(x~=1, true) 37 | 38 | check(1x, false) 41 | check(1>=x, false) 42 | check(1==x, false) 43 | check(1~=x, true) 44 | 45 | check(not (xx), true) 48 | check(not (x>=x), true) 49 | check(not (x==x), true) 50 | check(not (x~=x), false) 51 | 52 | check(not (xy), true) 55 | check(not (x>=y), true) 56 | check(not (x==y), true) 57 | check(not (x~=y), false) 58 | 59 | check(not (yx), true) 62 | check(not (y>=x), true) 63 | check(not (y==x), true) 64 | check(not (y~=x), false) 65 | 66 | check(not (x<1), true) 67 | check(not (x<=1), true) 68 | check(not (x>1), true) 69 | check(not (x>=1), true) 70 | check(not (x==1), true) 71 | check(not (x~=1), false) 72 | 73 | check(not (1x), true) 76 | check(not (1>=x), true) 77 | check(not (1==x), true) 78 | check(not (1~=x), false) 79 | 80 | -------------------------------------------------------------------------------- /test/misc/unordered_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | local nan = 0/0 3 | local t = {} 4 | for i=1,100 do t[i] = i+0.5 end 5 | for i=101,200 do t[i] = nan end 6 | 7 | do 8 | local z = 0 9 | for i=1,200 do if t[i] > 1000 then z=i end end 10 | assert(z == 0) 11 | end 12 | 13 | do 14 | local z = 0 15 | for i=1,200 do if not (t[i] < 1000) then z=i end end 16 | assert(z == 200) 17 | end 18 | 19 | do 20 | local z = 0 21 | for i=1,200 do if t[i] <= 1000 then z=i end end 22 | assert(z == 100) 23 | end 24 | 25 | do 26 | local z = 0 27 | for i=1,200 do if not (t[i] >= 1000) then z=i end end 28 | assert(z == 200) 29 | end 30 | 31 | do 32 | local z = 0 33 | for i=1,200 do if t[i] > 0 then z=i end end 34 | assert(z == 100) 35 | end 36 | 37 | do 38 | local z = 0 39 | for i=1,200 do if not (t[i] < 0) then z=i end end 40 | assert(z == 200) 41 | end 42 | 43 | do 44 | local z = 0 45 | for i=1,200 do if t[i] <= 0 then z=i end end 46 | assert(z == 0) 47 | end 48 | 49 | do 50 | local z = 0 51 | for i=1,200 do if not (t[i] >= 0) then z=i end end 52 | assert(z == 200) 53 | end 54 | 55 | do local z; for i=1,100 do z = 0/0 end; assert(z ~= z) end 56 | 57 | do local z; for i=1,100 do z = nan == nan end; assert(z == false) end 58 | do local z; for i=1,100 do z = nan == 1 end; assert(z == false) end 59 | do local z; for i=1,100 do z = 1 == nan end; assert(z == false) end 60 | 61 | do local z; for i=1,100 do z = nan ~= nan end; assert(z == true) end 62 | do local z; for i=1,100 do z = nan ~= 1 end; assert(z == true) end 63 | do local z; for i=1,100 do z = 1 ~= nan end; assert(z == true) end 64 | 65 | do local z; for i=1,100 do z = nan < nan end; assert(z == false) end 66 | do local z; for i=1,100 do z = nan < 1 end; assert(z == false) end 67 | do local z; for i=1,100 do z = 1 < nan end; assert(z == false) end 68 | 69 | do local z; for i=1,100 do z = not (nan < nan) end; assert(z == true) end 70 | do local z; for i=1,100 do z = not (nan < 1) end; assert(z == true) end 71 | do local z; for i=1,100 do z = not (1 < nan) end; assert(z == true) end 72 | 73 | do local z; for i=1,100 do z = nan > nan end; assert(z == false) end 74 | do local z; for i=1,100 do z = nan > 1 end; assert(z == false) end 75 | do local z; for i=1,100 do z = 1 > nan end; assert(z == false) end 76 | 77 | do local z; for i=1,100 do z = not (nan > nan) end; assert(z == true) end 78 | do local z; for i=1,100 do z = not (nan > 1) end; assert(z == true) end 79 | do local z; for i=1,100 do z = not (1 > nan) end; assert(z == true) end 80 | 81 | do local z; for i=1,100 do z = nan <= nan end; assert(z == false) end 82 | do local z; for i=1,100 do z = nan <= 1 end; assert(z == false) end 83 | do local z; for i=1,100 do z = 1 <= nan end; assert(z == false) end 84 | 85 | do local z; for i=1,100 do z = not (nan <= nan) end; assert(z == true) end 86 | do local z; for i=1,100 do z = not (nan <= 1) end; assert(z == true) end 87 | do local z; for i=1,100 do z = not (1 <= nan) end; assert(z == true) end 88 | 89 | do local z; for i=1,100 do z = nan >= nan end; assert(z == false) end 90 | do local z; for i=1,100 do z = nan >= 1 end; assert(z == false) end 91 | do local z; for i=1,100 do z = 1 >= nan end; assert(z == false) end 92 | 93 | do local z; for i=1,100 do z = not (nan >= nan) end; assert(z == true) end 94 | do local z; for i=1,100 do z = not (nan >= 1) end; assert(z == true) end 95 | do local z; for i=1,100 do z = not (1 >= nan) end; assert(z == true) end 96 | 97 | -------------------------------------------------------------------------------- /test/misc/vararg_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | do 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 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 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 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 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 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 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/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/misc/xpcall_jit.lua: -------------------------------------------------------------------------------- 1 | 2 | local function tr(err) return "tr"..err end 3 | 4 | do 5 | local function f(x) return x*x end 6 | local x = 0 7 | for i=1,100 do 8 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 9 | if not ok1 or not ok2 or not ok3 then break end 10 | x = x + y 11 | end 12 | assert(x == 338350) 13 | end 14 | 15 | do 16 | local x = 0 17 | for i=1,100 do 18 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, math.sqrt, tr, i*i) 19 | if not ok1 or not ok2 or not ok3 then break end 20 | x = x + y 21 | end 22 | assert(x == 5050) 23 | end 24 | 25 | do 26 | local function f(x) 27 | if x >= 150 then error("test", 0) end 28 | return x end 29 | local x = 0 30 | for i=1,200 do 31 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 32 | if not ok1 or not ok2 or not ok3 then 33 | assert(ok1 and ok2 and not ok3) 34 | assert(y == "trtest") 35 | break 36 | end 37 | x = x + y 38 | end 39 | assert(x == 11175) 40 | end 41 | 42 | do 43 | local function f(x) 44 | if x >= 150 then return x*x end 45 | return x 46 | end 47 | local x = 0 48 | for i=1,200 do 49 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 50 | if not ok1 or not ok2 or not ok3 then break end 51 | x = x + y 52 | end 53 | assert(x == 1584100) 54 | end 55 | 56 | do 57 | local function f(x) 58 | if x >= 150 then 59 | if x >= 175 then error("test", 0) end 60 | return x*x 61 | end 62 | return x 63 | end 64 | local x = 0 65 | for i=1,200 do 66 | local ok1, ok2, ok3, y = xpcall(xpcall, tr, xpcall, tr, f, tr, i) 67 | if not ok1 or not ok2 or not ok3 then 68 | assert(ok1 and ok2 and not ok3) 69 | assert(y == "trtest") 70 | -- note: no break, so we get an exit to interpreter 71 | else 72 | x = x + y 73 | end 74 | end 75 | assert(x == 668575) 76 | end 77 | 78 | do 79 | local x = 0 80 | for i=1,100 do 81 | -- Test xpcall swap after recorder error. 82 | local ok1, ok2, ok3, err = xpcall(xpcall, tr, xpcall, tr, error, tr, "test", 0) 83 | assert(ok1 and ok2 and not ok3 and err == "trtest") 84 | end 85 | end 86 | 87 | -------------------------------------------------------------------------------- /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 | local jit = require("jit") 3 | 4 | dofile("../common/ffi_util.inc") 5 | 6 | do 7 | local fp = assert(io.open("/tmp/__tmp.c", "w")) 8 | fp:write[[ 9 | #define __float128 double 10 | 11 | #define _Float32 float 12 | #define _Float32x float 13 | #define _Float64 double 14 | #define _Float64x double 15 | #define _Float128 long double 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | ]] 36 | fp:close() 37 | 38 | local flags 39 | if jit.arch == "arm64" then 40 | flags = "" 41 | else 42 | flags = ffi.abi("32bit") and "-m32" or "-m64" 43 | end 44 | fp = assert(io.popen("cc -E -P -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE /tmp/__tmp.c "..flags)) 45 | local s = fp:read("*a") 46 | fp:close() 47 | os.remove("/tmp/__tmp.c") 48 | s = s:gsub("__uint128_t", "unsigned long long") 49 | ffi.cdef(s) 50 | end 51 | 52 | -------------------------------------------------------------------------------- /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/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, ...) 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 | local hit 17 | for i = 1, select('#', ...) do 18 | local expected = select(i, ...) 19 | if got == expected then 20 | hit = true 21 | break 22 | end 23 | end 24 | if not hit then 25 | error("got: \""..got.."\"\nexpected: \""..table.concat({...}, "\", \"").."\"", 2) 26 | end 27 | end 28 | 29 | check(function(x) return x end, "+0 -0 +0.5 -0.5 +1 -1 +inf -inf nan") 30 | 31 | local powcheck = { 32 | "+1 +1 +1 +1 +1 +1 +1 +1 +1", 33 | "+1 +1 +1 +1 +1 +1 +1 +1 +1", 34 | "+0 +0 +0.70711 nan +1 nan +inf +inf nan", 35 | "+inf +inf +1.4142 nan +1 nan +0 +0 nan", 36 | "+0 -0 +0.5 -0.5 +1 -1 +inf -inf nan", 37 | "+inf -inf +2 -2 +1 -1 +0 -0 nan", 38 | "+0 +0 +0 +0 +1 +1 +inf +inf nan", 39 | "+inf +inf +inf +inf +1 +1 +0 +0 nan", 40 | "nan nan nan nan +1 nan nan nan nan", 41 | } 42 | for j=1,#inp do 43 | local y = inp[j] 44 | check(function(x) return x^y end, powcheck[j]) 45 | end 46 | 47 | check(math.abs, "+0 +0 +0.5 +0.5 +1 +1 +inf +inf nan") 48 | check(math.floor, "+0 +0 +0 -1 +1 -1 +inf -inf nan", "+0 -0 +0 -1 +1 -1 +inf -inf nan") 49 | check(math.ceil, "+0 +0 +1 +0 +1 -1 +inf -inf nan", "+0 -0 +1 -0 +1 -1 +inf -inf nan") 50 | check(math.sqrt, "+0 -0 +0.70711 nan +1 nan +inf nan nan") 51 | check(math.sin, "+0 -0 +0.47943 -0.47943 +0.84147 -0.84147 nan nan nan") 52 | check(math.cos, "+1 +1 +0.87758 +0.87758 +0.5403 +0.5403 nan nan nan") 53 | check(math.tan, "+0 -0 +0.5463 -0.5463 +1.5574 -1.5574 nan nan nan") 54 | check(math.asin, "+0 -0 +0.5236 -0.5236 +1.5708 -1.5708 nan nan nan") 55 | check(math.acos, "+1.5708 +1.5708 +1.0472 +2.0944 +0 +3.1416 nan nan nan") 56 | check(math.atan, "+0 -0 +0.46365 -0.46365 +0.7854 -0.7854 +1.5708 -1.5708 nan") 57 | check(math.log, "-inf -inf -0.69315 nan +0 nan +inf nan nan") 58 | check(math.log10, "-inf -inf -0.30103 nan +0 nan +inf nan nan") 59 | check(math.exp, "+1 +1 +1.6487 +0.60653 +2.7183 +0.36788 +inf +0 nan") 60 | 61 | -- Pointless: deg, rad, min, max, pow 62 | -- LATER: %, fmod, frexp, ldexp, modf, sinh, cosh, tanh 63 | 64 | -------------------------------------------------------------------------------- /valgrind.suppress: -------------------------------------------------------------------------------- 1 | { 2 | 3 | Memcheck:Cond 4 | fun:lj_tab_newkey 5 | fun:lj_tab_set 6 | fun:expr_table 7 | fun:expr_simple 8 | fun:expr_unop 9 | fun:expr_binop 10 | fun:expr 11 | fun:expr_list 12 | fun:parse_local 13 | fun:parse_stmt 14 | fun:parse_chunk 15 | fun:parse_block 16 | fun:parse_stmt 17 | fun:parse_chunk 18 | fun:lj_parse 19 | fun:cpparser 20 | fun:lj_vm_cpcall 21 | fun:lua_loadx 22 | fun:luaL_loadfilex 23 | fun:luaL_loadfile 24 | fun:handle_script 25 | fun:pmain 26 | fun:lj_BC_FUNCC 27 | fun:lua_cpcall 28 | } 29 | { 30 | 31 | Memcheck:Cond 32 | fun:lj_obj_equal 33 | fun:lj_tab_get 34 | fun:lj_meta_tget 35 | fun:lj_vmeta_tgetv 36 | fun:lua_pcall 37 | fun:docall 38 | fun:handle_script 39 | fun:pmain 40 | fun:lj_BC_FUNCC 41 | fun:lua_cpcall 42 | fun:main 43 | } 44 | { 45 | 46 | Memcheck:Cond 47 | fun:lj_tab_newkey 48 | fun:expr_table 49 | fun:expr_binop 50 | fun:expr_list 51 | fun:parse_local 52 | fun:parse_stmt 53 | fun:parse_chunk 54 | fun:parse_block 55 | fun:parse_stmt 56 | fun:parse_chunk 57 | fun:lj_parse 58 | fun:cpparser 59 | fun:lj_vm_cpcall 60 | fun:lua_loadx 61 | fun:luaL_loadfilex 62 | fun:handle_script 63 | fun:pmain 64 | fun:lj_BC_FUNCC 65 | fun:lua_cpcall 66 | fun:main 67 | } 68 | --------------------------------------------------------------------------------