├── .gitattributes ├── .gitignore ├── .relver ├── .travis.yml ├── COPYRIGHT ├── Makefile ├── README ├── README.md ├── doc ├── bluequad-print.css ├── bluequad.css ├── contact.html ├── ext_buffer.html ├── ext_c_api.html ├── ext_ffi.html ├── ext_ffi_api.html ├── ext_ffi_semantics.html ├── ext_ffi_tutorial.html ├── ext_jit.html ├── ext_profiler.html ├── extensions.html ├── img │ └── contact.png ├── install.html ├── luajit.html └── running.html ├── dynasm ├── Examples │ ├── run.sh │ └── test_z_inst.c ├── dasm_arm.h ├── dasm_arm.lua ├── dasm_arm64.h ├── dasm_arm64.lua ├── dasm_mips.h ├── dasm_mips.lua ├── dasm_mips64.lua ├── dasm_ppc.h ├── dasm_ppc.lua ├── dasm_proto.h ├── dasm_s390x.h ├── dasm_s390x.lua ├── dasm_x64.lua ├── dasm_x86.h ├── dasm_x86.lua └── dynasm.lua ├── etc ├── luajit.1 └── luajit.pc ├── src ├── .gitignore ├── Makefile ├── Makefile.dep ├── host │ ├── .gitignore │ ├── README │ ├── buildvm.c │ ├── buildvm.h │ ├── buildvm_asm.c │ ├── buildvm_fold.c │ ├── buildvm_lib.c │ ├── buildvm_libbc.h │ ├── buildvm_peobj.c │ ├── genlibbc.lua │ ├── genminilua.lua │ ├── genversion.lua │ └── minilua.c ├── jit │ ├── .gitignore │ ├── bc.lua │ ├── bcsave.lua │ ├── dis_arm.lua │ ├── dis_arm64.lua │ ├── dis_arm64be.lua │ ├── dis_mips.lua │ ├── dis_mips64.lua │ ├── dis_mips64el.lua │ ├── dis_mips64r6.lua │ ├── dis_mips64r6el.lua │ ├── dis_mipsel.lua │ ├── dis_ppc.lua │ ├── dis_s390x.lua │ ├── dis_x64.lua │ ├── dis_x86.lua │ ├── dump.lua │ ├── p.lua │ ├── v.lua │ └── zone.lua ├── lauxlib.h ├── lib_aux.c ├── lib_base.c ├── lib_bit.c ├── lib_buffer.c ├── lib_debug.c ├── lib_ffi.c ├── lib_init.c ├── lib_io.c ├── lib_jit.c ├── lib_math.c ├── lib_os.c ├── lib_package.c ├── lib_string.c ├── lib_table.c ├── lj_alloc.c ├── lj_alloc.h ├── lj_api.c ├── lj_arch.h ├── lj_asm.c ├── lj_asm.h ├── lj_asm_arm.h ├── lj_asm_arm64.h ├── lj_asm_mips.h ├── lj_asm_ppc.h ├── lj_asm_x86.h ├── lj_assert.c ├── lj_bc.c ├── lj_bc.h ├── lj_bcdump.h ├── lj_bcread.c ├── lj_bcwrite.c ├── lj_buf.c ├── lj_buf.h ├── lj_carith.c ├── lj_carith.h ├── lj_ccall.c ├── lj_ccall.h ├── lj_ccallback.c ├── lj_ccallback.h ├── lj_cconv.c ├── lj_cconv.h ├── lj_cdata.c ├── lj_cdata.h ├── lj_char.c ├── lj_char.h ├── lj_clib.c ├── lj_clib.h ├── lj_cparse.c ├── lj_cparse.h ├── lj_crecord.c ├── lj_crecord.h ├── lj_ctype.c ├── lj_ctype.h ├── lj_debug.c ├── lj_debug.h ├── lj_def.h ├── lj_dispatch.c ├── lj_dispatch.h ├── lj_emit_arm.h ├── lj_emit_arm64.h ├── lj_emit_mips.h ├── lj_emit_ppc.h ├── lj_emit_x86.h ├── lj_err.c ├── lj_err.h ├── lj_errmsg.h ├── lj_ff.h ├── lj_ffrecord.c ├── lj_ffrecord.h ├── lj_frame.h ├── lj_func.c ├── lj_func.h ├── lj_gc.c ├── lj_gc.h ├── lj_gdbjit.c ├── lj_gdbjit.h ├── lj_init.c ├── lj_ir.c ├── lj_ir.h ├── lj_ircall.h ├── lj_iropt.h ├── lj_jit.h ├── lj_lex.c ├── lj_lex.h ├── lj_lib.c ├── lj_lib.h ├── lj_load.c ├── lj_mcode.c ├── lj_mcode.h ├── lj_meta.c ├── lj_meta.h ├── lj_obj.c ├── lj_obj.h ├── lj_opt_dce.c ├── lj_opt_fold.c ├── lj_opt_loop.c ├── lj_opt_mem.c ├── lj_opt_narrow.c ├── lj_opt_sink.c ├── lj_opt_split.c ├── lj_parse.c ├── lj_parse.h ├── lj_prng.c ├── lj_prng.h ├── lj_profile.c ├── lj_profile.h ├── lj_record.c ├── lj_record.h ├── lj_serialize.c ├── lj_serialize.h ├── lj_snap.c ├── lj_snap.h ├── lj_state.c ├── lj_state.h ├── lj_str.c ├── lj_str.h ├── lj_str_hash.c ├── lj_strfmt.c ├── lj_strfmt.h ├── lj_strfmt_num.c ├── lj_strscan.c ├── lj_strscan.h ├── lj_tab.c ├── lj_tab.h ├── lj_target.h ├── lj_target_arm.h ├── lj_target_arm64.h ├── lj_target_mips.h ├── lj_target_ppc.h ├── lj_target_s390x.h ├── lj_target_x86.h ├── lj_trace.c ├── lj_trace.h ├── lj_traceerr.h ├── lj_udata.c ├── lj_udata.h ├── lj_vm.h ├── lj_vmevent.c ├── lj_vmevent.h ├── lj_vmmath.c ├── ljamalg.c ├── lua.h ├── lua.hpp ├── luaconf.h ├── luajit.c ├── luajit_rolling.h ├── lualib.h ├── msvcbuild.bat ├── nxbuild.bat ├── ps4build.bat ├── ps5build.bat ├── psvitabuild.bat ├── vm_arm.dasc ├── vm_arm64.dasc ├── vm_mips.dasc ├── vm_mips64.dasc ├── vm_ppc.dasc ├── vm_s390x.dasc ├── vm_x64.dasc ├── vm_x86.dasc ├── x64 │ ├── Makefile │ └── test │ │ ├── Makefile │ │ ├── benchmark.cxx │ │ ├── test.cpp │ │ ├── test_str_comp.lua │ │ ├── test_util.cxx │ │ ├── test_util.d │ │ └── test_util.hpp ├── xb1build.bat └── xedkbuild.bat └── t ├── TestLJ.pm ├── exdata.t ├── exdata2.t ├── isarr-interp.t ├── isarr-jit.t ├── isempty.t ├── iter.t ├── nkeys.t ├── prngstate.t └── table-clone.t /.gitattributes: -------------------------------------------------------------------------------- 1 | /.relver export-subst 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oa] 2 | *.so 3 | *.obj 4 | *.lib 5 | *.exp 6 | *.dll 7 | *.exe 8 | *.manifest 9 | *.dmp 10 | *.swp 11 | .tags 12 | *~ 13 | tags 14 | *.swo 15 | -------------------------------------------------------------------------------- /.relver: -------------------------------------------------------------------------------- 1 | 1748495995 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: focal 3 | 4 | branches: 5 | only: 6 | - "v2.1-agentzh" 7 | 8 | os: linux 9 | arch: 10 | - amd64 11 | - arm64 12 | - s390x 13 | - ppc64le 14 | 15 | language: c 16 | 17 | compiler: 18 | - gcc 19 | 20 | addons: 21 | apt: 22 | packages: 23 | - axel 24 | - cpanminus 25 | - libtest-base-perl 26 | - libtext-diff-perl 27 | - libtest-longstring-perl 28 | - liblist-moreutils-perl 29 | - libparallel-forkmanager-perl 30 | - libgd-dev 31 | - libmpc-dev 32 | - build-essential 33 | - libgtk2.0-dev 34 | - valgrind 35 | 36 | env: 37 | global: 38 | - JOBS=3 39 | - LUAJIT_PREFIX=/opt/luajit21 40 | - LUAJIT_SYSM_PREFIX=/opt/luajit21-sysm 41 | - LUAJIT_COMMON_XCFLAGS="-DLUA_USE_APICHECK -DLUA_USE_ASSERT -DLUAJIT_NUMMODE=2 -O1" 42 | - LUAJIT_COMMON_XCFLAGS=$( [ ${TRAVIS_CPU_ARCH} == "amd64" ] && echo "$LUAJIT_COMMON_XCFLAGS -msse4.2" || echo "$LUAJIT_COMMON_XCFLAGS" ) 43 | 44 | matrix: 45 | - LUAJIT_XCFLAGS="$LUAJIT_COMMON_XCFLAGS" 46 | - LUAJIT_XCFLAGS="-DLUAJIT_ENABLE_LUA52COMPAT $LUAJIT_COMMON_XCFLAGS" LUA52=1 47 | - LUAJIT_XCFLAGS="-DLUAJIT_USE_VALGRIND -DLUAJIT_USE_SYSMALLOC -DLUAJIT_ENABLE_LUA52COMPAT $LUAJIT_COMMON_XCFLAGS" LUA52=1 FLAGS=$( [ ${TRAVIS_CPU_ARCH} != "s390x" ] && echo '-v' ) 48 | - LUAJIT_XCFLAGS="-DLUAJIT_DISABLE_GC64 -DLUAJIT_ENABLE_LUA52COMPAT $LUAJIT_COMMON_XCFLAGS" LUA52=1 49 | 50 | install: 51 | - git clone https://github.com/openresty/luajit2-test-suite.git ../luajit2-test-suite 52 | 53 | script: 54 | - echo ${LUAJIT_COMMON_XCFLAGS} 55 | - valgrind --version 56 | - /usr/bin/env perl $(command -v cpanm) --sudo --notest IPC::Run3 Test::Base Test::LongString Parallel::ForkManager > build.log 2>&1 || (cat build.log && exit 1) 57 | - cd ../luajit2 58 | - make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS="$LUAJIT_XCFLAGS" > build.log 2>&1 || (cat build.log && exit 1) 59 | - sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1) 60 | - if [ ${TRAVIS_CPU_ARCH} == "amd64" ]; then PATH=/opt/luajit21/bin:$PATH prove -I. t; fi 61 | - cd ../luajit2-test-suite 62 | - ./run-tests -j 1 $FLAGS $LUAJIT_PREFIX 63 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | =============================================================================== 2 | LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/ 3 | 4 | Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | 6 | Copyright (C) 2017-2018 Yichun Zhang. All rights reserved. 7 | 8 | Copyright (C) 2017-2018 OpenResty Inc. All rights reserved. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | 28 | [ MIT license: https://www.opensource.org/licenses/mit-license.php ] 29 | 30 | =============================================================================== 31 | [ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ] 32 | 33 | Copyright (C) 1994-2012 Lua.org, PUC-Rio. 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy 36 | of this software and associated documentation files (the "Software"), to deal 37 | in the Software without restriction, including without limitation the rights 38 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 | copies of the Software, and to permit persons to whom the Software is 40 | furnished to do so, subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in 43 | all copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 51 | THE SOFTWARE. 52 | 53 | =============================================================================== 54 | [ LuaJIT includes code from dlmalloc, which has this license statement: ] 55 | 56 | This is a version (aka dlmalloc) of malloc/free/realloc written by 57 | Doug Lea and released to the public domain, as explained at 58 | https://creativecommons.org/licenses/publicdomain 59 | 60 | =============================================================================== 61 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README for LuaJIT 2.1 2 | --------------------- 3 | 4 | LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language. 5 | 6 | Project Homepage: https://luajit.org/ 7 | 8 | LuaJIT is Copyright (C) 2005-2025 Mike Pall. 9 | LuaJIT is free software, released under the MIT license. 10 | See full Copyright Notice in the COPYRIGHT file or in luajit.h. 11 | 12 | Documentation for LuaJIT is available in HTML format. 13 | Please point your favorite browser to: 14 | 15 | doc/luajit.html 16 | 17 | -------------------------------------------------------------------------------- /doc/bluequad-print.css: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2004-2025 Mike Pall. 2 | * 3 | * You are welcome to use the general ideas of this design for your own sites. 4 | * But please do not steal the stylesheet, the layout or the color scheme. 5 | */ 6 | body { 7 | font-family: serif; 8 | font-size: 11pt; 9 | margin: 0 3em; 10 | padding: 0; 11 | border: none; 12 | } 13 | a:link, a:visited, a:hover, a:active { 14 | text-decoration: none; 15 | background: transparent; 16 | color: #0000ff; 17 | } 18 | h1, h2, h3 { 19 | font-family: sans-serif; 20 | font-weight: bold; 21 | text-align: left; 22 | margin: 0.5em 0; 23 | padding: 0; 24 | } 25 | h1 { 26 | font-size: 200%; 27 | } 28 | h2 { 29 | font-size: 150%; 30 | } 31 | h3 { 32 | font-size: 125%; 33 | } 34 | p { 35 | margin: 0 0 0.5em 0; 36 | padding: 0; 37 | } 38 | ul, ol { 39 | margin: 0.5em 0; 40 | padding: 0 0 0 2em; 41 | } 42 | ul { 43 | list-style: outside square; 44 | } 45 | ol { 46 | list-style: outside decimal; 47 | } 48 | li { 49 | margin: 0; 50 | padding: 0; 51 | } 52 | dl { 53 | margin: 1em 0; 54 | padding: 1em; 55 | border: 1px solid black; 56 | } 57 | dt { 58 | font-weight: bold; 59 | margin: 0; 60 | padding: 0; 61 | } 62 | dt sup { 63 | float: right; 64 | margin-left: 1em; 65 | } 66 | dd { 67 | margin: 0.5em 0 0 2em; 68 | padding: 0; 69 | } 70 | table { 71 | table-layout: fixed; 72 | width: 100%; 73 | margin: 1em 0; 74 | padding: 0; 75 | border: 1px solid black; 76 | border-spacing: 0; 77 | border-collapse: collapse; 78 | } 79 | tr { 80 | margin: 0; 81 | padding: 0; 82 | border: none; 83 | } 84 | td { 85 | text-align: left; 86 | margin: 0; 87 | padding: 0.2em 0.5em; 88 | border-top: 1px solid black; 89 | border-bottom: 1px solid black; 90 | } 91 | tr.separate td { 92 | border-top: double; 93 | } 94 | tt, pre, code, kbd, samp { 95 | font-family: monospace; 96 | font-size: 75%; 97 | } 98 | kbd { 99 | font-weight: bolder; 100 | } 101 | blockquote, pre { 102 | margin: 1em 2em; 103 | padding: 0; 104 | } 105 | img { 106 | border: none; 107 | vertical-align: baseline; 108 | margin: 0; 109 | padding: 0; 110 | } 111 | img.left { 112 | float: left; 113 | margin: 0.5em 1em 0.5em 0; 114 | } 115 | img.right { 116 | float: right; 117 | margin: 0.5em 0 0.5em 1em; 118 | } 119 | .flush { 120 | clear: both; 121 | visibility: hidden; 122 | } 123 | .hide, .noprint, #nav { 124 | display: none !important; 125 | } 126 | .pagebreak { 127 | page-break-before: always; 128 | } 129 | #site { 130 | text-align: right; 131 | font-family: sans-serif; 132 | font-weight: bold; 133 | margin: 0 1em; 134 | border-bottom: 1pt solid black; 135 | } 136 | #site a { 137 | font-size: 1.2em; 138 | } 139 | #site a:link, #site a:visited { 140 | text-decoration: none; 141 | font-weight: bold; 142 | background: transparent; 143 | color: #ffffff; 144 | } 145 | #logo { 146 | color: #ff8000; 147 | } 148 | #head { 149 | clear: both; 150 | margin: 0 1em; 151 | } 152 | #main { 153 | line-height: 1.3; 154 | text-align: justify; 155 | margin: 1em; 156 | } 157 | #foot { 158 | clear: both; 159 | font-size: 80%; 160 | text-align: center; 161 | margin: 0 1.25em; 162 | padding: 0.5em 0 0 0; 163 | border-top: 1pt solid black; 164 | page-break-before: avoid; 165 | page-break-after: avoid; 166 | } 167 | -------------------------------------------------------------------------------- /doc/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Contact 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | Lua 14 |
15 | 18 | 56 |
57 |

58 | If you want to report bugs, propose fixes or suggest enhancements, 59 | please use the 60 | » GitHub issue tracker. 61 |

62 |

63 | Please send general questions to the 64 | » LuaJIT mailing list. 65 |

66 |

67 | You can also send any questions you have directly to me: 68 |

69 | 70 | 78 | 82 | 86 | 87 |

88 | Note: I cannot reply to GMail, Google Workplace, Outlook or Office365 89 | mail addresses, since they prefer to mindlessly filter out mails sent 90 | from small domains using independent mail servers, such as mine. If you 91 | don't like that, please complain to Google or Microsoft, not me. 92 |

93 | 94 |

Copyright

95 |

96 | All documentation is 97 | Copyright © 2005-2025 Mike Pall. 98 |

99 | 100 | 101 |
102 |
103 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /doc/img/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openresty/luajit2/afc74313c6f919f713e2a25003cf0066852bb24a/doc/img/contact.png -------------------------------------------------------------------------------- /dynasm/Examples/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # set -x 3 | 4 | # run test 5 | lua ../dynasm.lua test_z_inst.c | gcc -DDASM_CHECKS -std=gnu99 -Wall -Werror -g -x c -o test_z_inst - 6 | ./test_z_inst 7 | ec=$? 8 | 9 | # cleanup 10 | rm -f ./test_z_inst 11 | 12 | # exit 13 | exit $ec 14 | 15 | -------------------------------------------------------------------------------- /dynasm/dasm_mips64.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------ 2 | -- DynASM MIPS64 module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- See dynasm.lua for full copyright notice. 6 | ------------------------------------------------------------------------------ 7 | -- This module just sets 64 bit mode for the combined MIPS/MIPS64 module. 8 | -- All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | mips64 = true -- Using a global is an ugly, but effective solution. 12 | return require("dasm_mips") 13 | -------------------------------------------------------------------------------- /dynasm/dasm_proto.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** DynASM encoding engine prototypes. 3 | ** Copyright (C) 2005-2025 Mike Pall. All rights reserved. 4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. 5 | */ 6 | 7 | #ifndef _DASM_PROTO_H 8 | #define _DASM_PROTO_H 9 | 10 | #include 11 | #include 12 | 13 | #define DASM_IDENT "DynASM 1.5.0" 14 | #define DASM_VERSION 10500 /* 1.5.0 */ 15 | 16 | #ifndef Dst_DECL 17 | #define Dst_DECL dasm_State **Dst 18 | #endif 19 | 20 | #ifndef Dst_REF 21 | #define Dst_REF (*Dst) 22 | #endif 23 | 24 | #ifndef DASM_FDEF 25 | #define DASM_FDEF extern 26 | #endif 27 | 28 | #ifndef DASM_M_GROW 29 | #define DASM_M_GROW(ctx, t, p, sz, need) \ 30 | do { \ 31 | size_t _sz = (sz), _need = (need); \ 32 | if (_sz < _need) { \ 33 | if (_sz < 16) _sz = 16; \ 34 | while (_sz < _need) _sz += _sz; \ 35 | (p) = (t *)realloc((p), _sz); \ 36 | if ((p) == NULL) exit(1); \ 37 | (sz) = _sz; \ 38 | } \ 39 | } while(0) 40 | #endif 41 | 42 | #ifndef DASM_M_FREE 43 | #define DASM_M_FREE(ctx, p, sz) free(p) 44 | #endif 45 | 46 | /* Internal DynASM encoder state. */ 47 | typedef struct dasm_State dasm_State; 48 | 49 | 50 | /* Initialize and free DynASM state. */ 51 | DASM_FDEF void dasm_init(Dst_DECL, int maxsection); 52 | DASM_FDEF void dasm_free(Dst_DECL); 53 | 54 | /* Setup global array. Must be called before dasm_setup(). */ 55 | DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl); 56 | 57 | /* Grow PC label array. Can be called after dasm_setup(), too. */ 58 | DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc); 59 | 60 | /* Setup encoder. */ 61 | DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist); 62 | 63 | /* Feed encoder with actions. Calls are generated by pre-processor. */ 64 | DASM_FDEF void dasm_put(Dst_DECL, int start, ...); 65 | 66 | /* Link sections and return the resulting size. */ 67 | DASM_FDEF int dasm_link(Dst_DECL, size_t *szp); 68 | 69 | /* Encode sections into buffer. */ 70 | DASM_FDEF int dasm_encode(Dst_DECL, void *buffer); 71 | 72 | /* Get PC label offset. */ 73 | DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc); 74 | 75 | #ifdef DASM_CHECKS 76 | /* Optional sanity checker to call between isolated encoding steps. */ 77 | DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch); 78 | #else 79 | #define dasm_checkstep(a, b) 0 80 | #endif 81 | 82 | 83 | #endif /* _DASM_PROTO_H */ 84 | -------------------------------------------------------------------------------- /dynasm/dasm_x64.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------ 2 | -- DynASM x64 module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- See dynasm.lua for full copyright notice. 6 | ------------------------------------------------------------------------------ 7 | -- This module just sets 64 bit mode for the combined x86/x64 module. 8 | -- All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | x64 = true -- Using a global is an ugly, but effective solution. 12 | return require("dasm_x86") 13 | -------------------------------------------------------------------------------- /etc/luajit.1: -------------------------------------------------------------------------------- 1 | .TH luajit 1 "" "" "LuaJIT documentation" 2 | .SH NAME 3 | luajit \- Just-In-Time Compiler for the Lua Language 4 | \fB 5 | .SH SYNOPSIS 6 | .B luajit 7 | [\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...] 8 | .SH "WEB SITE" 9 | .IR https://luajit.org 10 | .SH DESCRIPTION 11 | .PP 12 | This is the command-line program to run Lua programs with \fBLuaJIT\fR. 13 | .PP 14 | \fBLuaJIT\fR is a just-in-time (JIT) compiler for the Lua language. 15 | The virtual machine (VM) is based on a fast interpreter combined with 16 | a trace compiler. It can significantly improve the performance of Lua programs. 17 | .PP 18 | \fBLuaJIT\fR is API\- and ABI-compatible with the VM of the standard 19 | Lua\ 5.1 interpreter. When embedding the VM into an application, 20 | the built library can be used as a drop-in replacement. 21 | .SH OPTIONS 22 | .TP 23 | .BI "\-e " chunk 24 | Run the given chunk of Lua code. 25 | .TP 26 | .BI "\-l " library 27 | Load the named library, just like \fBrequire("\fR\fIlibrary\fR\fB")\fR. 28 | .TP 29 | .BI "\-b " ... 30 | Save or list bytecode. Run without arguments to get help on options. 31 | .TP 32 | .BI "\-j " command 33 | Perform LuaJIT control command (optional space after \fB\-j\fR). 34 | .TP 35 | .BI "\-O" [opt] 36 | Control LuaJIT optimizations. 37 | .TP 38 | .B "\-i" 39 | Run in interactive mode. 40 | .TP 41 | .B "\-v" 42 | Show \fBLuaJIT\fR version. 43 | .TP 44 | .B "\-E" 45 | Ignore environment variables. 46 | .TP 47 | .B "\-\-" 48 | Stop processing options. 49 | .TP 50 | .B "\-" 51 | Read script from stdin instead. 52 | .PP 53 | After all options are processed, the given \fIscript\fR is run. 54 | The arguments are passed in the global \fIarg\fR table. 55 | .PP 56 | Interactive mode is only entered, if no \fIscript\fR and no \fB\-e\fR 57 | option is given. Interactive mode can be left with EOF (\fICtrl\-Z\fB). 58 | .SH EXAMPLES 59 | .TP 60 | luajit hello.lua world 61 | 62 | Prints "Hello world", assuming \fIhello.lua\fR contains: 63 | .br 64 | print("Hello", arg[1]) 65 | .TP 66 | luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)" 67 | 68 | Calculates the sum of the numbers from 1 to 1000000000. 69 | .br 70 | And finishes in a reasonable amount of time, too. 71 | .TP 72 | luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end" 73 | 74 | Runs some nested loops and shows the resulting traces. 75 | .SH COPYRIGHT 76 | .PP 77 | \fBLuaJIT\fR is Copyright \(co 2005-2025 Mike Pall. 78 | .br 79 | \fBLuaJIT\fR is open source software, released under the MIT license. 80 | .SH SEE ALSO 81 | .PP 82 | More details in the provided HTML docs or at: 83 | .IR https://luajit.org 84 | .br 85 | More about the Lua language can be found at: 86 | .IR https://lua.org/docs.html 87 | .PP 88 | lua(1) 89 | -------------------------------------------------------------------------------- /etc/luajit.pc: -------------------------------------------------------------------------------- 1 | # Package information for LuaJIT to be used by pkg-config. 2 | majver=2 3 | minver=1 4 | relver=ROLLING 5 | version=${majver}.${minver}.${relver} 6 | abiver=5.1 7 | 8 | prefix=/usr/local 9 | multilib=lib 10 | exec_prefix=${prefix} 11 | libdir=${exec_prefix}/${multilib} 12 | libname=luajit-${abiver} 13 | includedir=${prefix}/include/luajit-${majver}.${minver} 14 | 15 | INSTALL_LMOD=${prefix}/share/lua/${abiver} 16 | INSTALL_CMOD=${prefix}/${multilib}/lua/${abiver} 17 | 18 | Name: LuaJIT 19 | Description: Just-in-time compiler for Lua 20 | URL: https://luajit.org 21 | Version: ${version} 22 | Requires: 23 | Libs: -L${libdir} -l${libname} 24 | Libs.private: -Wl,-E -lm -ldl 25 | Cflags: -I${includedir} 26 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | luajit 2 | luajit.h 3 | luajit_relver.txt 4 | lj_bcdef.h 5 | lj_ffdef.h 6 | lj_libdef.h 7 | lj_recdef.h 8 | lj_folddef.h 9 | lj_vm.[sS] 10 | -------------------------------------------------------------------------------- /src/host/.gitignore: -------------------------------------------------------------------------------- 1 | minilua 2 | buildvm 3 | buildvm_arch.h 4 | -------------------------------------------------------------------------------- /src/host/README: -------------------------------------------------------------------------------- 1 | The files in this directory are only used during the build process of LuaJIT. 2 | For cross-compilation, they must be executed on the host, not on the target. 3 | 4 | These files should NOT be installed! 5 | -------------------------------------------------------------------------------- /src/host/buildvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** LuaJIT VM builder. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _BUILDVM_H 7 | #define _BUILDVM_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "lj_def.h" 16 | #include "lj_arch.h" 17 | 18 | /* Hardcoded limits. Increase as needed. */ 19 | #define BUILD_MAX_RELOC 200 /* Max. number of relocations. */ 20 | #define BUILD_MAX_FOLD 4096 /* Max. number of fold rules. */ 21 | 22 | /* Prefix for scanned library definitions. */ 23 | #define LIBDEF_PREFIX "LJLIB_" 24 | 25 | /* Prefix for scanned fold definitions. */ 26 | #define FOLDDEF_PREFIX "LJFOLD" 27 | 28 | /* Prefixes for generated labels. */ 29 | #define LABEL_PREFIX "lj_" 30 | #define LABEL_PREFIX_BC LABEL_PREFIX "BC_" 31 | #define LABEL_PREFIX_FF LABEL_PREFIX "ff_" 32 | #define LABEL_PREFIX_CF LABEL_PREFIX "cf_" 33 | #define LABEL_PREFIX_FFH LABEL_PREFIX "ffh_" 34 | #define LABEL_PREFIX_LIBCF LABEL_PREFIX "lib_cf_" 35 | #define LABEL_PREFIX_LIBINIT LABEL_PREFIX "lib_init_" 36 | 37 | /* Forward declaration. */ 38 | struct dasm_State; 39 | 40 | /* Build modes. */ 41 | #define BUILDDEF(_) \ 42 | _(elfasm) _(coffasm) _(machasm) _(peobj) _(raw) \ 43 | _(bcdef) _(ffdef) _(libdef) _(recdef) _(vmdef) \ 44 | _(folddef) 45 | 46 | typedef enum { 47 | #define BUILDENUM(name) BUILD_##name, 48 | BUILDDEF(BUILDENUM) 49 | #undef BUILDENUM 50 | BUILD__MAX 51 | } BuildMode; 52 | 53 | /* Code relocation. */ 54 | typedef struct BuildReloc { 55 | int32_t ofs; 56 | int sym; 57 | int type; 58 | } BuildReloc; 59 | 60 | typedef struct BuildSym { 61 | const char *name; 62 | int32_t ofs; 63 | } BuildSym; 64 | 65 | /* Build context structure. */ 66 | typedef struct BuildCtx { 67 | /* DynASM state pointer. Should be first member. */ 68 | struct dasm_State *D; 69 | /* Parsed command line. */ 70 | BuildMode mode; 71 | FILE *fp; 72 | const char *outname; 73 | char **args; 74 | /* Code and symbols generated by DynASM. */ 75 | uint8_t *code; 76 | size_t codesz; 77 | int npc, nglob, nsym, nreloc, nrelocsym; 78 | void **glob; 79 | BuildSym *sym; 80 | const char **relocsym; 81 | int32_t *bc_ofs; 82 | const char *beginsym; 83 | /* Strings generated by DynASM. */ 84 | const char *const *globnames; 85 | const char *const *extnames; 86 | const char *dasm_ident; 87 | const char *dasm_arch; 88 | /* Relocations. */ 89 | BuildReloc reloc[BUILD_MAX_RELOC]; 90 | } BuildCtx; 91 | 92 | extern void owrite(BuildCtx *ctx, const void *ptr, size_t sz); 93 | extern void emit_asm(BuildCtx *ctx); 94 | extern void emit_peobj(BuildCtx *ctx); 95 | extern void emit_lib(BuildCtx *ctx); 96 | extern void emit_fold(BuildCtx *ctx); 97 | 98 | extern const char *const bc_names[]; 99 | extern const char *const ir_names[]; 100 | extern const char *const irt_names[]; 101 | extern const char *const irfpm_names[]; 102 | extern const char *const irfield_names[]; 103 | extern const char *const ircall_names[]; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/host/buildvm_libbc.h: -------------------------------------------------------------------------------- 1 | /* This is a generated file. DO NOT EDIT! */ 2 | 3 | static const int libbc_endian = 0; 4 | 5 | static const uint8_t libbc_code[] = { 6 | #if LJ_FR2 7 | /* math.deg */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,241,135,158,166,3, 8 | 220,203,178,130,4, 9 | /* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20, 10 | 198,190,199,252,3, 11 | /* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0, 12 | /* table.foreachi */ 0,2,10,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0, 13 | BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0, 14 | BC_MOV,8,5,0,BC_TGETR,9,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128, 15 | BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0, 16 | /* table.foreach */ 0,2,11,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI, 17 | 2,0,0,BC_MOV,3,0,0,BC_KNUM,4,0,0,BC_JMP,5,7,128,BC_MOV,7,1,0,BC_MOV,9,5,0, 18 | BC_MOV,10,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0, 19 | BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15, 20 | /* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0, 21 | /* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0, 22 | 0,BC_JMP,3,7,128,BC_ISEQN,2,0,0,BC_JMP,3,23,128,BC_TGETR,3,2,0,BC_KPRI,4,0,0, 23 | BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0, 24 | BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0, 25 | BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7, 26 | BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0, 27 | BC_RET1,3,2,0,BC_RET0,0,1,0,0,2, 28 | /* table.move */ 0,5,12,0,0,0,35,BC_ISTYPE,0,12,0,BC_ISTYPE,1,14,0,BC_ISTYPE, 29 | 2,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE, 30 | 4,12,0,BC_ISGT,1,2,0,BC_JMP,5,24,128,BC_SUBVV,5,1,3,BC_ISLT,2,3,0,BC_JMP,6,4, 31 | 128,BC_ISLE,3,1,0,BC_JMP,6,2,128,BC_ISEQV,4,0,0,BC_JMP,6,9,128,BC_MOV,6,1,0, 32 | BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0, 33 | BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0, 34 | BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR, 35 | 11,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0, 36 | #else 37 | /* math.deg */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,241,135,158,166,3, 38 | 220,203,178,130,4, 39 | /* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20, 40 | 198,190,199,252,3, 41 | /* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0, 42 | /* table.foreachi */ 0,2,9,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0, 43 | BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0, 44 | BC_MOV,7,5,0,BC_TGETR,8,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128, 45 | BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0, 46 | /* table.foreach */ 0,2,10,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI, 47 | 2,0,0,BC_MOV,3,0,0,BC_KNUM,4,0,0,BC_JMP,5,7,128,BC_MOV,7,1,0,BC_MOV,8,5,0, 48 | BC_MOV,9,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0, 49 | BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15, 50 | /* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0, 51 | /* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0, 52 | 0,BC_JMP,3,7,128,BC_ISEQN,2,0,0,BC_JMP,3,23,128,BC_TGETR,3,2,0,BC_KPRI,4,0,0, 53 | BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0, 54 | BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0, 55 | BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7, 56 | BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0, 57 | BC_RET1,3,2,0,BC_RET0,0,1,0,0,2, 58 | /* table.move */ 0,5,12,0,0,0,35,BC_ISTYPE,0,12,0,BC_ISTYPE,1,14,0,BC_ISTYPE, 59 | 2,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE, 60 | 4,12,0,BC_ISGT,1,2,0,BC_JMP,5,24,128,BC_SUBVV,5,1,3,BC_ISLT,2,3,0,BC_JMP,6,4, 61 | 128,BC_ISLE,3,1,0,BC_JMP,6,2,128,BC_ISEQV,4,0,0,BC_JMP,6,9,128,BC_MOV,6,1,0, 62 | BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0, 63 | BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0, 64 | BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR, 65 | 11,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0, 66 | #endif 67 | 0 68 | }; 69 | 70 | static const struct { const char *name; int ofs; } libbc_map[] = { 71 | {"math_deg",0}, 72 | {"math_rad",25}, 73 | {"string_len",50}, 74 | {"table_foreachi",69}, 75 | {"table_foreach",136}, 76 | {"table_getn",213}, 77 | {"table_remove",232}, 78 | {"table_move",361}, 79 | {NULL,508} 80 | }; 81 | 82 | -------------------------------------------------------------------------------- /src/host/genversion.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- Lua script to embed the rolling release version in luajit.h. 3 | ---------------------------------------------------------------------------- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | 8 | local arg = {...} 9 | local FILE_ROLLING_H = arg[1] or "luajit_rolling.h" 10 | local FILE_RELVER_TXT = arg[2] or "luajit_relver.txt" 11 | local FILE_LUAJIT_H = arg[3] or "luajit.h" 12 | 13 | local function file_read(file) 14 | local fp = assert(io.open(file, "rb"), "run from the wrong directory") 15 | local data = assert(fp:read("*a")) 16 | fp:close() 17 | return data 18 | end 19 | 20 | local function file_write_mod(file, data) 21 | local fp = io.open(file, "rb") 22 | if fp then 23 | local odata = assert(fp:read("*a")) 24 | fp:close() 25 | if odata == data then return end 26 | end 27 | fp = assert(io.open(file, "wb")) 28 | assert(fp:write(data)) 29 | assert(fp:close()) 30 | end 31 | 32 | local text = file_read(FILE_ROLLING_H):gsub("#error.-\n", "") 33 | local relver = file_read(FILE_RELVER_TXT):match("(%d+)") 34 | 35 | if relver then 36 | text = text:gsub("ROLLING", relver) 37 | else 38 | io.stderr:write([[ 39 | **** WARNING Cannot determine rolling release version from git log. 40 | **** WARNING The 'git' command must be available during the build. 41 | ]]) 42 | file_write_mod(FILE_RELVER_TXT, "ROLLING\n") -- Fallback for install target. 43 | end 44 | 45 | file_write_mod(FILE_LUAJIT_H, text) 46 | -------------------------------------------------------------------------------- /src/jit/.gitignore: -------------------------------------------------------------------------------- 1 | vmdef.lua 2 | -------------------------------------------------------------------------------- /src/jit/dis_arm64be.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT ARM64BE disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- ARM64 instructions are always little-endian. So just forward to the 8 | -- common ARM64 disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | return require((string.match(..., ".*%.") or "").."dis_arm64") 12 | 13 | -------------------------------------------------------------------------------- /src/jit/dis_mips64.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPS64 disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the big-endian functions from the 8 | -- MIPS disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") 12 | return { 13 | create = dis_mips.create, 14 | disass = dis_mips.disass, 15 | regname = dis_mips.regname 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/jit/dis_mips64el.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPS64EL disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the little-endian functions from the 8 | -- MIPS disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") 12 | return { 13 | create = dis_mips.create_el, 14 | disass = dis_mips.disass_el, 15 | regname = dis_mips.regname 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/jit/dis_mips64r6.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPS64R6 disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the r6 big-endian functions from the 8 | -- MIPS disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") 12 | return { 13 | create = dis_mips.create_r6, 14 | disass = dis_mips.disass_r6, 15 | regname = dis_mips.regname 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/jit/dis_mips64r6el.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPS64R6EL disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the r6 little-endian functions from the 8 | -- MIPS disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") 12 | return { 13 | create = dis_mips.create_r6_el, 14 | disass = dis_mips.disass_r6_el, 15 | regname = dis_mips.regname 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/jit/dis_mipsel.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPSEL disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the little-endian functions from the 8 | -- MIPS disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") 12 | return { 13 | create = dis_mips.create_el, 14 | disass = dis_mips.disass_el, 15 | regname = dis_mips.regname 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/jit/dis_x64.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT x64 disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the 64 bit functions from the combined 8 | -- x86/x64 disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86") 12 | return { 13 | create = dis_x86.create64, 14 | disass = dis_x86.disass64, 15 | regname = dis_x86.regname64 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/jit/zone.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT profiler zones. 3 | -- 4 | -- Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- 8 | -- This module implements a simple hierarchical zone model. 9 | -- 10 | -- Example usage: 11 | -- 12 | -- local zone = require("jit.zone") 13 | -- zone("AI") 14 | -- ... 15 | -- zone("A*") 16 | -- ... 17 | -- print(zone:get()) --> "A*" 18 | -- ... 19 | -- zone() 20 | -- ... 21 | -- print(zone:get()) --> "AI" 22 | -- ... 23 | -- zone() 24 | -- 25 | ---------------------------------------------------------------------------- 26 | 27 | local remove = table.remove 28 | 29 | return setmetatable({ 30 | flush = function(t) 31 | for i=#t,1,-1 do t[i] = nil end 32 | end, 33 | get = function(t) 34 | return t[#t] 35 | end 36 | }, { 37 | __call = function(t, zone) 38 | if zone then 39 | t[#t+1] = zone 40 | else 41 | return (assert(remove(t), "empty zone stack")) 42 | end 43 | end 44 | }) 45 | 46 | -------------------------------------------------------------------------------- /src/lib_bit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Bit manipulation library. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lib_bit_c 7 | #define LUA_LIB 8 | 9 | #include "lua.h" 10 | #include "lauxlib.h" 11 | #include "lualib.h" 12 | 13 | #include "lj_obj.h" 14 | #include "lj_err.h" 15 | #include "lj_buf.h" 16 | #include "lj_strscan.h" 17 | #include "lj_strfmt.h" 18 | #if LJ_HASFFI 19 | #include "lj_ctype.h" 20 | #include "lj_cdata.h" 21 | #include "lj_cconv.h" 22 | #include "lj_carith.h" 23 | #endif 24 | #include "lj_ff.h" 25 | #include "lj_lib.h" 26 | 27 | /* ------------------------------------------------------------------------ */ 28 | 29 | #define LJLIB_MODULE_bit 30 | 31 | #if LJ_HASFFI 32 | static int bit_result64(lua_State *L, CTypeID id, uint64_t x) 33 | { 34 | GCcdata *cd = lj_cdata_new_(L, id, 8); 35 | *(uint64_t *)cdataptr(cd) = x; 36 | setcdataV(L, L->base-1-LJ_FR2, cd); 37 | return FFH_RES(1); 38 | } 39 | #else 40 | static int32_t bit_checkbit(lua_State *L, int narg) 41 | { 42 | TValue *o = L->base + narg-1; 43 | if (!(o < L->top && lj_strscan_numberobj(o))) 44 | lj_err_argt(L, narg, LUA_TNUMBER); 45 | if (LJ_LIKELY(tvisint(o))) { 46 | return intV(o); 47 | } else { 48 | int32_t i = lj_num2bit(numV(o)); 49 | if (LJ_DUALNUM) setintV(o, i); 50 | return i; 51 | } 52 | } 53 | #endif 54 | 55 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit) 56 | { 57 | #if LJ_HASFFI 58 | CTypeID id = 0; 59 | setintV(L->base-1-LJ_FR2, (int32_t)lj_carith_check64(L, 1, &id)); 60 | return FFH_RES(1); 61 | #else 62 | lj_lib_checknumber(L, 1); 63 | return FFH_RETRY; 64 | #endif 65 | } 66 | 67 | LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) 68 | { 69 | #if LJ_HASFFI 70 | CTypeID id = 0; 71 | uint64_t x = lj_carith_check64(L, 1, &id); 72 | return id ? bit_result64(L, id, ~x) : FFH_RETRY; 73 | #else 74 | lj_lib_checknumber(L, 1); 75 | return FFH_RETRY; 76 | #endif 77 | } 78 | 79 | LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) 80 | { 81 | #if LJ_HASFFI 82 | CTypeID id = 0; 83 | uint64_t x = lj_carith_check64(L, 1, &id); 84 | return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY; 85 | #else 86 | lj_lib_checknumber(L, 1); 87 | return FFH_RETRY; 88 | #endif 89 | } 90 | 91 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) 92 | { 93 | #if LJ_HASFFI 94 | CTypeID id = 0, id2 = 0; 95 | uint64_t x = lj_carith_check64(L, 1, &id); 96 | int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2); 97 | if (id) { 98 | x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift); 99 | return bit_result64(L, id, x); 100 | } 101 | setintV(L->base+1, sh); 102 | return FFH_RETRY; 103 | #else 104 | lj_lib_checknumber(L, 1); 105 | bit_checkbit(L, 2); 106 | return FFH_RETRY; 107 | #endif 108 | } 109 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) 110 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) 111 | LJLIB_ASM_(bit_rol) LJLIB_REC(bit_shift IR_BROL) 112 | LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR) 113 | 114 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) 115 | { 116 | #if LJ_HASFFI 117 | CTypeID id = 0; 118 | TValue *o = L->base, *top = L->top; 119 | int i = 0; 120 | do { lj_carith_check64(L, ++i, &id); } while (++o < top); 121 | if (id) { 122 | CTState *cts = ctype_cts(L); 123 | CType *ct = ctype_get(cts, id); 124 | int op = curr_func(L)->c.ffid - (int)FF_bit_bor; 125 | uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0; 126 | o = L->base; 127 | do { 128 | lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0); 129 | if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x; 130 | } while (++o < top); 131 | return bit_result64(L, id, y); 132 | } 133 | return FFH_RETRY; 134 | #else 135 | int i = 0; 136 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); 137 | return FFH_RETRY; 138 | #endif 139 | } 140 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) 141 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) 142 | 143 | /* ------------------------------------------------------------------------ */ 144 | 145 | LJLIB_CF(bit_tohex) LJLIB_REC(.) 146 | { 147 | #if LJ_HASFFI 148 | CTypeID id = 0, id2 = 0; 149 | uint64_t b = lj_carith_check64(L, 1, &id); 150 | int32_t n = L->base+1>=L->top ? (id ? 16 : 8) : 151 | (int32_t)lj_carith_check64(L, 2, &id2); 152 | #else 153 | uint32_t b = (uint32_t)bit_checkbit(L, 1); 154 | int32_t n = L->base+1>=L->top ? 8 : bit_checkbit(L, 2); 155 | #endif 156 | SBuf *sb = lj_buf_tmp_(L); 157 | SFormat sf = (STRFMT_UINT|STRFMT_T_HEX); 158 | if (n < 0) { n = (int32_t)(~(uint32_t)n+1u); sf |= STRFMT_F_UPPER; } 159 | if ((uint32_t)n > 254) n = 254; 160 | sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC); 161 | #if LJ_HASFFI 162 | if (n < 16) b &= ((uint64_t)1 << 4*n)-1; 163 | #else 164 | if (n < 8) b &= (1u << 4*n)-1; 165 | #endif 166 | sb = lj_strfmt_putfxint(sb, sf, b); 167 | setstrV(L, L->top-1, lj_buf_str(L, sb)); 168 | lj_gc_check(L); 169 | return 1; 170 | } 171 | 172 | /* ------------------------------------------------------------------------ */ 173 | 174 | #include "lj_libdef.h" 175 | 176 | LUALIB_API int luaopen_bit(lua_State *L) 177 | { 178 | LJ_LIB_REG(L, LUA_BITLIBNAME, bit); 179 | return 1; 180 | } 181 | 182 | -------------------------------------------------------------------------------- /src/lib_init.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Library initialization. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | ** 5 | ** Major parts taken verbatim from the Lua interpreter. 6 | ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h 7 | */ 8 | 9 | #define lib_init_c 10 | #define LUA_LIB 11 | 12 | #include "lua.h" 13 | #include "lauxlib.h" 14 | #include "lualib.h" 15 | 16 | #include "lj_arch.h" 17 | 18 | static const luaL_Reg lj_lib_load[] = { 19 | { "", luaopen_base }, 20 | { LUA_LOADLIBNAME, luaopen_package }, 21 | { LUA_TABLIBNAME, luaopen_table }, 22 | { LUA_IOLIBNAME, luaopen_io }, 23 | { LUA_OSLIBNAME, luaopen_os }, 24 | { LUA_STRLIBNAME, luaopen_string }, 25 | { LUA_MATHLIBNAME, luaopen_math }, 26 | { LUA_DBLIBNAME, luaopen_debug }, 27 | { LUA_BITLIBNAME, luaopen_bit }, 28 | { LUA_JITLIBNAME, luaopen_jit }, 29 | { NULL, NULL } 30 | }; 31 | 32 | static const luaL_Reg lj_lib_preload[] = { 33 | #if LJ_HASFFI 34 | { LUA_FFILIBNAME, luaopen_ffi }, 35 | #endif 36 | { NULL, NULL } 37 | }; 38 | 39 | LUALIB_API void luaL_openlibs(lua_State *L) 40 | { 41 | const luaL_Reg *lib; 42 | for (lib = lj_lib_load; lib->func; lib++) { 43 | lua_pushcfunction(L, lib->func); 44 | lua_pushstring(L, lib->name); 45 | lua_call(L, 1, 0); 46 | } 47 | luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 48 | sizeof(lj_lib_preload)/sizeof(lj_lib_preload[0])-1); 49 | for (lib = lj_lib_preload; lib->func; lib++) { 50 | lua_pushcfunction(L, lib->func); 51 | lua_setfield(L, -2, lib->name); 52 | } 53 | lua_pop(L, 1); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/lj_alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Bundled memory allocator. 3 | ** Donated to the public domain. 4 | */ 5 | 6 | #ifndef _LJ_ALLOC_H 7 | #define _LJ_ALLOC_H 8 | 9 | #include "lj_def.h" 10 | 11 | #ifndef LUAJIT_USE_SYSMALLOC 12 | LJ_FUNC void *lj_alloc_create(PRNGState *rs); 13 | LJ_FUNC void lj_alloc_setprng(void *msp, PRNGState *rs); 14 | LJ_FUNC void lj_alloc_destroy(void *msp); 15 | LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize); 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/lj_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** IR assembler (SSA IR -> machine code). 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_ASM_H 7 | #define _LJ_ASM_H 8 | 9 | #include "lj_jit.h" 10 | 11 | #if LJ_HASJIT 12 | LJ_FUNC void lj_asm_trace(jit_State *J, GCtrace *T); 13 | LJ_FUNC void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, 14 | MCode *target); 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/lj_assert.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Internal assertions. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lj_assert_c 7 | #define LUA_CORE 8 | 9 | #if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK) 10 | 11 | #include 12 | 13 | #include "lj_obj.h" 14 | 15 | void lj_assert_fail(global_State *g, const char *file, int line, 16 | const char *func, const char *fmt, ...) 17 | { 18 | va_list argp; 19 | va_start(argp, fmt); 20 | fprintf(stderr, "LuaJIT ASSERT %s:%d: %s: ", file, line, func); 21 | vfprintf(stderr, fmt, argp); 22 | fputc('\n', stderr); 23 | va_end(argp); 24 | UNUSED(g); /* May be NULL. TODO: optionally dump state. */ 25 | abort(); 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/lj_bc.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Bytecode instruction modes. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lj_bc_c 7 | #define LUA_CORE 8 | 9 | #include "lj_obj.h" 10 | #include "lj_bc.h" 11 | 12 | /* Bytecode offsets and bytecode instruction modes. */ 13 | #include "lj_bcdef.h" 14 | 15 | -------------------------------------------------------------------------------- /src/lj_bcdump.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Bytecode dump definitions. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_BCDUMP_H 7 | #define _LJ_BCDUMP_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_lex.h" 11 | 12 | /* -- Bytecode dump format ------------------------------------------------ */ 13 | 14 | /* 15 | ** dump = header proto+ 0U 16 | ** header = ESC 'L' 'J' versionB flagsU [namelenU nameB*] 17 | ** proto = lengthU pdata 18 | ** pdata = phead bcinsW* uvdataH* kgc* knum* [debugB*] 19 | ** phead = flagsB numparamsB framesizeB numuvB numkgcU numknU numbcU 20 | ** [debuglenU [firstlineU numlineU]] 21 | ** kgc = kgctypeU { ktab | (loU hiU) | (rloU rhiU iloU ihiU) | strB* } 22 | ** knum = intU0 | (loU1 hiU) 23 | ** ktab = narrayU nhashU karray* khash* 24 | ** karray = ktabk 25 | ** khash = ktabk ktabk 26 | ** ktabk = ktabtypeU { intU | (loU hiU) | strB* } 27 | ** 28 | ** B = 8 bit, H = 16 bit, W = 32 bit, U = ULEB128 of W, U0/U1 = ULEB128 of W+1 29 | */ 30 | 31 | /* Bytecode dump header. */ 32 | #define BCDUMP_HEAD1 0x1b 33 | #define BCDUMP_HEAD2 0x4c 34 | #define BCDUMP_HEAD3 0x4a 35 | 36 | /* If you perform *any* kind of private modifications to the bytecode itself 37 | ** or to the dump format, you *must* set BCDUMP_VERSION to 0x80 or higher. 38 | */ 39 | #define BCDUMP_VERSION 2 40 | 41 | /* Compatibility flags. */ 42 | #define BCDUMP_F_BE 0x01 43 | #define BCDUMP_F_STRIP 0x02 44 | #define BCDUMP_F_FFI 0x04 45 | #define BCDUMP_F_FR2 0x08 46 | 47 | #define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1) 48 | 49 | #define BCDUMP_F_DETERMINISTIC 0x80000000 50 | 51 | /* Type codes for the GC constants of a prototype. Plus length for strings. */ 52 | enum { 53 | BCDUMP_KGC_CHILD, BCDUMP_KGC_TAB, BCDUMP_KGC_I64, BCDUMP_KGC_U64, 54 | BCDUMP_KGC_COMPLEX, BCDUMP_KGC_STR 55 | }; 56 | 57 | /* Type codes for the keys/values of a constant table. */ 58 | enum { 59 | BCDUMP_KTAB_NIL, BCDUMP_KTAB_FALSE, BCDUMP_KTAB_TRUE, 60 | BCDUMP_KTAB_INT, BCDUMP_KTAB_NUM, BCDUMP_KTAB_STR 61 | }; 62 | 63 | /* -- Bytecode reader/writer ---------------------------------------------- */ 64 | 65 | LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, 66 | void *data, uint32_t flags); 67 | LJ_FUNC GCproto *lj_bcread_proto(LexState *ls); 68 | LJ_FUNC GCproto *lj_bcread(LexState *ls); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /src/lj_carith.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** C data arithmetic. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CARITH_H 7 | #define _LJ_CARITH_H 8 | 9 | #include "lj_obj.h" 10 | 11 | #if LJ_HASFFI 12 | 13 | LJ_FUNC int lj_carith_op(lua_State *L, MMS mm); 14 | 15 | #if LJ_32 16 | LJ_FUNC uint64_t lj_carith_shl64(uint64_t x, int32_t sh); 17 | LJ_FUNC uint64_t lj_carith_shr64(uint64_t x, int32_t sh); 18 | LJ_FUNC uint64_t lj_carith_sar64(uint64_t x, int32_t sh); 19 | LJ_FUNC uint64_t lj_carith_rol64(uint64_t x, int32_t sh); 20 | LJ_FUNC uint64_t lj_carith_ror64(uint64_t x, int32_t sh); 21 | #endif 22 | LJ_FUNC uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op); 23 | LJ_FUNC uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id); 24 | 25 | #if LJ_32 && LJ_HASJIT 26 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); 27 | #endif 28 | LJ_FUNC uint64_t lj_carith_divu64(uint64_t a, uint64_t b); 29 | LJ_FUNC int64_t lj_carith_divi64(int64_t a, int64_t b); 30 | LJ_FUNC uint64_t lj_carith_modu64(uint64_t a, uint64_t b); 31 | LJ_FUNC int64_t lj_carith_modi64(int64_t a, int64_t b); 32 | LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k); 33 | LJ_FUNC int64_t lj_carith_powi64(int64_t x, int64_t k); 34 | 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/lj_ccallback.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** FFI C callback handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CCALLBACK_H 7 | #define _LJ_CCALLBACK_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_ctype.h" 11 | 12 | #if LJ_HASFFI 13 | 14 | /* Really belongs to lj_vm.h. */ 15 | LJ_ASMF void lj_vm_ffi_callback(void); 16 | 17 | LJ_FUNC MSize lj_ccallback_ptr2slot(CTState *cts, void *p); 18 | LJ_FUNCA lua_State * LJ_FASTCALL lj_ccallback_enter(CTState *cts, void *cf); 19 | LJ_FUNCA void LJ_FASTCALL lj_ccallback_leave(CTState *cts, TValue *o); 20 | LJ_FUNC void *lj_ccallback_new(CTState *cts, CType *ct, GCfunc *fn); 21 | LJ_FUNC void lj_ccallback_mcode_free(CTState *cts); 22 | 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/lj_cconv.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** C type conversions. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CCONV_H 7 | #define _LJ_CCONV_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_ctype.h" 11 | 12 | #if LJ_HASFFI 13 | 14 | /* Compressed C type index. ORDER CCX. */ 15 | enum { 16 | CCX_B, /* Bool. */ 17 | CCX_I, /* Integer. */ 18 | CCX_F, /* Floating-point number. */ 19 | CCX_C, /* Complex. */ 20 | CCX_V, /* Vector. */ 21 | CCX_P, /* Pointer. */ 22 | CCX_A, /* Refarray. */ 23 | CCX_S /* Struct/union. */ 24 | }; 25 | 26 | /* Convert C type info to compressed C type index. ORDER CT. ORDER CCX. */ 27 | static LJ_AINLINE uint32_t cconv_idx(CTInfo info) 28 | { 29 | uint32_t idx = ((info >> 26) & 15u); /* Dispatch bits. */ 30 | lj_assertX(ctype_type(info) <= CT_MAYCONVERT, 31 | "cannot convert ctype %08x", info); 32 | #if LJ_64 33 | idx = ((uint32_t)(U64x(f436fff5,fff7f021) >> 4*idx) & 15u); 34 | #else 35 | idx = (((idx < 8 ? 0xfff7f021u : 0xf436fff5) >> 4*(idx & 7u)) & 15u); 36 | #endif 37 | lj_assertX(idx < 8, "cannot convert ctype %08x", info); 38 | return idx; 39 | } 40 | 41 | #define cconv_idx2(dinfo, sinfo) \ 42 | ((cconv_idx((dinfo)) << 3) + cconv_idx((sinfo))) 43 | 44 | #define CCX(dst, src) ((CCX_##dst << 3) + CCX_##src) 45 | 46 | /* Conversion flags. */ 47 | #define CCF_CAST 0x00000001u 48 | #define CCF_FROMTV 0x00000002u 49 | #define CCF_SAME 0x00000004u 50 | #define CCF_IGNQUAL 0x00000008u 51 | 52 | #define CCF_ARG_SHIFT 8 53 | #define CCF_ARG(n) ((n) << CCF_ARG_SHIFT) 54 | #define CCF_GETARG(f) ((f) >> CCF_ARG_SHIFT) 55 | 56 | LJ_FUNC int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags); 57 | LJ_FUNC void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s, 58 | uint8_t *dp, uint8_t *sp, CTInfo flags); 59 | LJ_FUNC int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, 60 | TValue *o, uint8_t *sp); 61 | LJ_FUNC int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp); 62 | LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d, 63 | uint8_t *dp, TValue *o, CTInfo flags); 64 | LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o); 65 | LJ_FUNC int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o); 66 | LJ_FUNC void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz, 67 | uint8_t *dp, TValue *o, MSize len); 68 | 69 | #endif 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/lj_cdata.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** C data management. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CDATA_H 7 | #define _LJ_CDATA_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_gc.h" 11 | #include "lj_ctype.h" 12 | 13 | #if LJ_HASFFI 14 | 15 | /* Get C data pointer. */ 16 | static LJ_AINLINE void *cdata_getptr(void *p, CTSize sz) 17 | { 18 | if (LJ_64 && sz == 4) { /* Support 32 bit pointers on 64 bit targets. */ 19 | return ((void *)(uintptr_t)*(uint32_t *)p); 20 | } else { 21 | lj_assertX(sz == CTSIZE_PTR, "bad pointer size %d", sz); 22 | return *(void **)p; 23 | } 24 | } 25 | 26 | /* Set C data pointer. */ 27 | static LJ_AINLINE void cdata_setptr(void *p, CTSize sz, const void *v) 28 | { 29 | if (LJ_64 && sz == 4) { /* Support 32 bit pointers on 64 bit targets. */ 30 | *(uint32_t *)p = (uint32_t)(uintptr_t)v; 31 | } else { 32 | lj_assertX(sz == CTSIZE_PTR, "bad pointer size %d", sz); 33 | *(void **)p = (void *)v; 34 | } 35 | } 36 | 37 | /* Allocate fixed-size C data object. */ 38 | static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz) 39 | { 40 | GCcdata *cd; 41 | #ifdef LUA_USE_ASSERT 42 | CType *ct = ctype_raw(cts, id); 43 | lj_assertCTS((ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR) == sz, 44 | "inconsistent size of fixed-size cdata alloc"); 45 | #endif 46 | cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz); 47 | cd->gct = ~LJ_TCDATA; 48 | cd->ctypeid = ctype_check(cts, id); 49 | return cd; 50 | } 51 | 52 | /* Variant which works without a valid CTState. */ 53 | static LJ_AINLINE GCcdata *lj_cdata_new_(lua_State *L, CTypeID id, CTSize sz) 54 | { 55 | GCcdata *cd = (GCcdata *)lj_mem_newgco(L, sizeof(GCcdata) + sz); 56 | cd->gct = ~LJ_TCDATA; 57 | cd->ctypeid = id; 58 | return cd; 59 | } 60 | 61 | LJ_FUNC GCcdata *lj_cdata_newref(CTState *cts, const void *pp, CTypeID id); 62 | LJ_FUNC GCcdata *lj_cdata_newv(lua_State *L, CTypeID id, CTSize sz, 63 | CTSize align); 64 | LJ_FUNC GCcdata *lj_cdata_newx(CTState *cts, CTypeID id, CTSize sz, 65 | CTInfo info); 66 | 67 | LJ_FUNC void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd); 68 | LJ_FUNC void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, 69 | uint32_t it); 70 | 71 | LJ_FUNC CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key, 72 | uint8_t **pp, CTInfo *qual); 73 | LJ_FUNC int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp); 74 | LJ_FUNC void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, 75 | CTInfo qual); 76 | 77 | #endif 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/lj_char.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Character types. 3 | ** Donated to the public domain. 4 | ** 5 | ** This is intended to replace the problematic libc single-byte NLS functions. 6 | ** These just don't make sense anymore with UTF-8 locales becoming the norm 7 | ** on POSIX systems. It never worked too well on Windows systems since hardly 8 | ** anyone bothered to call setlocale(). 9 | ** 10 | ** This table is hardcoded for ASCII. Identifiers include the characters 11 | ** 128-255, too. This allows for the use of all non-ASCII chars as identifiers 12 | ** in the lexer. This is a broad definition, but works well in practice 13 | ** for both UTF-8 locales and most single-byte locales (such as ISO-8859-*). 14 | ** 15 | ** If you really need proper character types for UTF-8 strings, please use 16 | ** an add-on library such as slnunicode: http://luaforge.net/projects/sln/ 17 | */ 18 | 19 | #define lj_char_c 20 | #define LUA_CORE 21 | 22 | #include "lj_char.h" 23 | 24 | LJ_DATADEF const uint8_t lj_char_bits[257] = { 25 | 0, 26 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 1, 1, 27 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28 | 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29 | 152,152,152,152,152,152,152,152,152,152, 4, 4, 4, 4, 4, 4, 30 | 4,176,176,176,176,176,176,160,160,160,160,160,160,160,160,160, 31 | 160,160,160,160,160,160,160,160,160,160,160, 4, 4, 4, 4,132, 32 | 4,208,208,208,208,208,208,192,192,192,192,192,192,192,192,192, 33 | 192,192,192,192,192,192,192,192,192,192,192, 4, 4, 4, 4, 1, 34 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 35 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 36 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 37 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 38 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 39 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 40 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 41 | 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /src/lj_char.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Character types. 3 | ** Donated to the public domain. 4 | */ 5 | 6 | #ifndef _LJ_CHAR_H 7 | #define _LJ_CHAR_H 8 | 9 | #include "lj_def.h" 10 | 11 | #define LJ_CHAR_CNTRL 0x01 12 | #define LJ_CHAR_SPACE 0x02 13 | #define LJ_CHAR_PUNCT 0x04 14 | #define LJ_CHAR_DIGIT 0x08 15 | #define LJ_CHAR_XDIGIT 0x10 16 | #define LJ_CHAR_UPPER 0x20 17 | #define LJ_CHAR_LOWER 0x40 18 | #define LJ_CHAR_IDENT 0x80 19 | #define LJ_CHAR_ALPHA (LJ_CHAR_LOWER|LJ_CHAR_UPPER) 20 | #define LJ_CHAR_ALNUM (LJ_CHAR_ALPHA|LJ_CHAR_DIGIT) 21 | #define LJ_CHAR_GRAPH (LJ_CHAR_ALNUM|LJ_CHAR_PUNCT) 22 | 23 | /* Only pass -1 or 0..255 to these macros. Never pass a signed char! */ 24 | #define lj_char_isa(c, t) ((lj_char_bits+1)[(c)] & t) 25 | #define lj_char_iscntrl(c) lj_char_isa((c), LJ_CHAR_CNTRL) 26 | #define lj_char_isspace(c) lj_char_isa((c), LJ_CHAR_SPACE) 27 | #define lj_char_ispunct(c) lj_char_isa((c), LJ_CHAR_PUNCT) 28 | #define lj_char_isdigit(c) lj_char_isa((c), LJ_CHAR_DIGIT) 29 | #define lj_char_isxdigit(c) lj_char_isa((c), LJ_CHAR_XDIGIT) 30 | #define lj_char_isupper(c) lj_char_isa((c), LJ_CHAR_UPPER) 31 | #define lj_char_islower(c) lj_char_isa((c), LJ_CHAR_LOWER) 32 | #define lj_char_isident(c) lj_char_isa((c), LJ_CHAR_IDENT) 33 | #define lj_char_isalpha(c) lj_char_isa((c), LJ_CHAR_ALPHA) 34 | #define lj_char_isalnum(c) lj_char_isa((c), LJ_CHAR_ALNUM) 35 | #define lj_char_isgraph(c) lj_char_isa((c), LJ_CHAR_GRAPH) 36 | 37 | #define lj_char_toupper(c) ((c) - (lj_char_islower(c) >> 1)) 38 | #define lj_char_tolower(c) ((c) + lj_char_isupper(c)) 39 | 40 | LJ_DATA const uint8_t lj_char_bits[257]; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/lj_clib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** FFI C library loader. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CLIB_H 7 | #define _LJ_CLIB_H 8 | 9 | #include "lj_obj.h" 10 | 11 | #if LJ_HASFFI 12 | 13 | /* Namespace for C library indexing. */ 14 | #define CLNS_INDEX ((1u<env. */ 20 | } CLibrary; 21 | 22 | LJ_FUNC TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name); 23 | LJ_FUNC void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global); 24 | LJ_FUNC void lj_clib_unload(CLibrary *cl); 25 | LJ_FUNC void lj_clib_default(lua_State *L, GCtab *mt); 26 | 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/lj_cparse.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** C declaration parser. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CPARSE_H 7 | #define _LJ_CPARSE_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_ctype.h" 11 | 12 | #if LJ_HASFFI 13 | 14 | /* C parser limits. */ 15 | #define CPARSE_MAX_BUF 32768 /* Max. token buffer size. */ 16 | #define CPARSE_MAX_DECLSTACK 100 /* Max. declaration stack depth. */ 17 | #define CPARSE_MAX_DECLDEPTH 20 /* Max. recursive declaration depth. */ 18 | #define CPARSE_MAX_PACKSTACK 7 /* Max. pack pragma stack depth. */ 19 | 20 | /* Flags for C parser mode. */ 21 | #define CPARSE_MODE_MULTI 1 /* Process multiple declarations. */ 22 | #define CPARSE_MODE_ABSTRACT 2 /* Accept abstract declarators. */ 23 | #define CPARSE_MODE_DIRECT 4 /* Accept direct declarators. */ 24 | #define CPARSE_MODE_FIELD 8 /* Accept field width in bits, too. */ 25 | #define CPARSE_MODE_NOIMPLICIT 16 /* Reject implicit declarations. */ 26 | #define CPARSE_MODE_SKIP 32 /* Skip definitions, ignore errors. */ 27 | 28 | typedef int CPChar; /* C parser character. Unsigned ext. from char. */ 29 | typedef int CPToken; /* C parser token. */ 30 | 31 | /* C parser internal value representation. */ 32 | typedef struct CPValue { 33 | union { 34 | int32_t i32; /* Value for CTID_INT32. */ 35 | uint32_t u32; /* Value for CTID_UINT32. */ 36 | }; 37 | CTypeID id; /* C Type ID of the value. */ 38 | } CPValue; 39 | 40 | /* C parser state. */ 41 | typedef struct CPState { 42 | CPChar c; /* Current character. */ 43 | CPToken tok; /* Current token. */ 44 | CPValue val; /* Token value. */ 45 | GCstr *str; /* Interned string of identifier/keyword. */ 46 | CType *ct; /* C type table entry. */ 47 | const char *p; /* Current position in input buffer. */ 48 | SBuf sb; /* String buffer for tokens. */ 49 | lua_State *L; /* Lua state. */ 50 | CTState *cts; /* C type state. */ 51 | TValue *param; /* C type parameters. */ 52 | const char *srcname; /* Current source name. */ 53 | BCLine linenumber; /* Input line counter. */ 54 | int depth; /* Recursive declaration depth. */ 55 | uint32_t tmask; /* Type mask for next identifier. */ 56 | uint32_t mode; /* C parser mode. */ 57 | uint8_t packstack[CPARSE_MAX_PACKSTACK]; /* Stack for pack pragmas. */ 58 | uint8_t curpack; /* Current position in pack pragma stack. */ 59 | } CPState; 60 | 61 | LJ_FUNC int lj_cparse(CPState *cp); 62 | 63 | LJ_FUNC int lj_cparse_case(GCstr *str, const char *match); 64 | 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/lj_crecord.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Trace recorder for C data operations. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_CRECORD_H 7 | #define _LJ_CRECORD_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_jit.h" 11 | #include "lj_ffrecord.h" 12 | 13 | #if LJ_HASJIT && LJ_HASFFI 14 | LJ_FUNC void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd); 15 | LJ_FUNC void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd); 16 | LJ_FUNC void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd); 17 | LJ_FUNC void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd); 18 | LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd); 19 | LJ_FUNC void LJ_FASTCALL recff_ffi_errno(jit_State *J, RecordFFData *rd); 20 | LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd); 21 | LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd); 22 | LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd); 23 | LJ_FUNC void LJ_FASTCALL recff_ffi_typeof(jit_State *J, RecordFFData *rd); 24 | LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd); 25 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); 26 | LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd); 27 | LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd); 28 | 29 | LJ_FUNC void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd); 30 | LJ_FUNC int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd); 31 | LJ_FUNC int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd); 32 | LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd); 33 | LJ_FUNC TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr); 34 | 35 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); 36 | LJ_FUNC TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o); 37 | #if LJ_HASBUFFER 38 | LJ_FUNC TRef lj_crecord_topcvoid(jit_State *J, TRef tr, cTValue *o); 39 | LJ_FUNC TRef lj_crecord_topuint8(jit_State *J, TRef tr); 40 | #endif 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/lj_debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Debugging and introspection. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_DEBUG_H 7 | #define _LJ_DEBUG_H 8 | 9 | #include "lj_obj.h" 10 | 11 | typedef struct lj_Debug { 12 | /* Common fields. Must be in the same order as in lua.h. */ 13 | int event; 14 | const char *name; 15 | const char *namewhat; 16 | const char *what; 17 | const char *source; 18 | int currentline; 19 | int nups; 20 | int linedefined; 21 | int lastlinedefined; 22 | char short_src[LUA_IDSIZE]; 23 | int i_ci; 24 | /* Extended fields. Only valid if lj_debug_getinfo() is called with ext = 1.*/ 25 | int nparams; 26 | int isvararg; 27 | } lj_Debug; 28 | 29 | LJ_FUNC BCPos lj_debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe); 30 | LJ_FUNC cTValue *lj_debug_frame(lua_State *L, int level, int *size); 31 | LJ_FUNC BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc); 32 | LJ_FUNC const char *lj_debug_uvname(GCproto *pt, uint32_t idx); 33 | LJ_FUNC const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp, 34 | GCobj **op); 35 | LJ_FUNC const char *lj_debug_slotname(GCproto *pt, const BCIns *pc, 36 | BCReg slot, const char **name); 37 | LJ_FUNC const char *lj_debug_funcname(lua_State *L, cTValue *frame, 38 | const char **name); 39 | LJ_FUNC void lj_debug_shortname(char *out, GCstr *str, BCLine line); 40 | LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg, 41 | cTValue *frame, cTValue *nextframe); 42 | LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc); 43 | LJ_FUNC int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, 44 | int ext); 45 | #if LJ_HASPROFILE 46 | LJ_FUNC void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, 47 | int depth); 48 | #endif 49 | 50 | /* Fixed internal variable names. */ 51 | #define VARNAMEDEF(_) \ 52 | _(FOR_IDX, "(for index)") \ 53 | _(FOR_STOP, "(for limit)") \ 54 | _(FOR_STEP, "(for step)") \ 55 | _(FOR_GEN, "(for generator)") \ 56 | _(FOR_STATE, "(for state)") \ 57 | _(FOR_CTL, "(for control)") 58 | 59 | enum { 60 | VARNAME_END, 61 | #define VARNAMEENUM(name, str) VARNAME_##name, 62 | VARNAMEDEF(VARNAMEENUM) 63 | #undef VARNAMEENUM 64 | VARNAME__MAX 65 | }; 66 | 67 | #ifdef LUA_USE_TRACE_LOGS 68 | LJ_FUNC void LJ_FASTCALL lj_log_trace_direct_exit(lua_State *L, 69 | int vmstate, const BCIns *pc); 70 | LJ_FUNC void LJ_FASTCALL lj_log_trace_normal_exit(lua_State *L, 71 | int vmstate, const BCIns *pc); 72 | LJ_FUNC void LJ_FASTCALL lj_log_trace_entry(lua_State *L, 73 | unsigned traceno, const BCIns *pc); 74 | LJ_FUNC void LJ_FASTCALL lj_log_trace_start_record(lua_State *L, unsigned traceno, 75 | const BCIns *pc, GCfunc *fn); 76 | #endif 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/lj_dispatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Instruction dispatch handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_DISPATCH_H 7 | #define _LJ_DISPATCH_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_bc.h" 11 | #if LJ_HASJIT 12 | #include "lj_jit.h" 13 | #endif 14 | 15 | #if LJ_TARGET_MIPS 16 | /* Need our own global offset table for the dreaded MIPS calling conventions. */ 17 | 18 | #ifndef _LJ_VM_H 19 | LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b); 20 | #endif 21 | 22 | #if LJ_SOFTFP 23 | #ifndef _LJ_IRCALL_H 24 | extern double __adddf3(double a, double b); 25 | extern double __subdf3(double a, double b); 26 | extern double __muldf3(double a, double b); 27 | extern double __divdf3(double a, double b); 28 | #endif 29 | #define SFGOTDEF(_) _(sqrt) _(__adddf3) _(__subdf3) _(__muldf3) _(__divdf3) 30 | #else 31 | #define SFGOTDEF(_) 32 | #endif 33 | #if LJ_HASJIT 34 | #define JITGOTDEF(_) _(lj_err_trace) _(lj_trace_exit) _(lj_trace_hot) 35 | #else 36 | #define JITGOTDEF(_) 37 | #endif 38 | #if LJ_HASFFI 39 | #define FFIGOTDEF(_) \ 40 | _(lj_meta_equal_cd) _(lj_ccallback_enter) _(lj_ccallback_leave) 41 | #else 42 | #define FFIGOTDEF(_) 43 | #endif 44 | #define GOTDEF(_) \ 45 | _(floor) _(ceil) _(trunc) _(log) _(log10) _(exp) _(sin) _(cos) _(tan) \ 46 | _(asin) _(acos) _(atan) _(sinh) _(cosh) _(tanh) _(frexp) _(modf) _(atan2) \ 47 | _(pow) _(fmod) _(ldexp) _(lj_vm_modi) \ 48 | _(lj_dispatch_call) _(lj_dispatch_ins) _(lj_dispatch_stitch) \ 49 | _(lj_dispatch_profile) _(lj_err_throw) \ 50 | _(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \ 51 | _(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \ 52 | _(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \ 53 | _(lj_meta_for) _(lj_meta_istype) _(lj_meta_len) _(lj_meta_tget) \ 54 | _(lj_meta_tset) _(lj_state_growstack) _(lj_strfmt_number) \ 55 | _(lj_str_new) _(lj_tab_dup) _(lj_tab_get) _(lj_tab_getinth) _(lj_tab_len) \ 56 | _(lj_tab_new) _(lj_tab_newkey) _(lj_tab_next) _(lj_tab_reasize) \ 57 | _(lj_tab_setinth) _(lj_buf_putstr_reverse) _(lj_buf_putstr_lower) \ 58 | _(lj_buf_putstr_upper) _(lj_buf_tostr) \ 59 | JITGOTDEF(_) FFIGOTDEF(_) SFGOTDEF(_) 60 | 61 | enum { 62 | #define GOTENUM(name) LJ_GOT_##name, 63 | GOTDEF(GOTENUM) 64 | #undef GOTENUM 65 | LJ_GOT__MAX 66 | }; 67 | #endif 68 | 69 | /* Type of hot counter. Must match the code in the assembler VM. */ 70 | /* 16 bits are sufficient. Only 0.0015% overhead with maximum slot penalty. */ 71 | typedef uint16_t HotCount; 72 | 73 | /* Number of hot counter hash table entries (must be a power of two). */ 74 | #define HOTCOUNT_SIZE 64 75 | #define HOTCOUNT_PCMASK ((HOTCOUNT_SIZE-1)*sizeof(HotCount)) 76 | 77 | /* Hotcount decrements. */ 78 | #define HOTCOUNT_LOOP 2 79 | #define HOTCOUNT_CALL 1 80 | 81 | /* This solves a circular dependency problem -- bump as needed. Sigh. */ 82 | #define GG_NUM_ASMFF 57 83 | 84 | #define GG_LEN_DDISP (BC__MAX + GG_NUM_ASMFF) 85 | #define GG_LEN_SDISP BC_FUNCF 86 | #define GG_LEN_DISP (GG_LEN_DDISP + GG_LEN_SDISP) 87 | 88 | /* Global state, main thread and extra fields are allocated together. */ 89 | typedef struct GG_State { 90 | lua_State L; /* Main thread. */ 91 | global_State g; /* Global state. */ 92 | #if LJ_TARGET_ARM && !LJ_TARGET_NX 93 | /* Make g reachable via K12 encoded DISPATCH-relative addressing. */ 94 | uint8_t align1[(16-sizeof(global_State))&15]; 95 | #endif 96 | #if LJ_TARGET_MIPS 97 | ASMFunction got[LJ_GOT__MAX]; /* Global offset table. */ 98 | #endif 99 | #if LJ_HASJIT 100 | jit_State J; /* JIT state. */ 101 | HotCount hotcount[HOTCOUNT_SIZE]; /* Hot counters. */ 102 | #if LJ_TARGET_ARM && !LJ_TARGET_NX 103 | /* Ditto for J. */ 104 | uint8_t align2[(16-sizeof(jit_State)-sizeof(HotCount)*HOTCOUNT_SIZE)&15]; 105 | #endif 106 | #endif 107 | ASMFunction dispatch[GG_LEN_DISP]; /* Instruction dispatch tables. */ 108 | BCIns bcff[GG_NUM_ASMFF]; /* Bytecode for ASM fast functions. */ 109 | } GG_State; 110 | 111 | #define GG_OFS(field) ((int)offsetof(GG_State, field)) 112 | #define G2GG(gl) ((GG_State *)((char *)(gl) - GG_OFS(g))) 113 | #define J2GG(j) ((GG_State *)((char *)(j) - GG_OFS(J))) 114 | #define L2GG(L) (G2GG(G(L))) 115 | #define J2G(J) (&J2GG(J)->g) 116 | #define G2J(gl) (&G2GG(gl)->J) 117 | #define L2J(L) (&L2GG(L)->J) 118 | #define GG_G2J (GG_OFS(J) - GG_OFS(g)) 119 | #define GG_G2DISP (GG_OFS(dispatch) - GG_OFS(g)) 120 | #define GG_DISP2G (GG_OFS(g) - GG_OFS(dispatch)) 121 | #define GG_DISP2J (GG_OFS(J) - GG_OFS(dispatch)) 122 | #define GG_DISP2HOT (GG_OFS(hotcount) - GG_OFS(dispatch)) 123 | #define GG_DISP2STATIC (GG_LEN_DDISP*(int)sizeof(ASMFunction)) 124 | 125 | #define hotcount_get(gg, pc) \ 126 | (gg)->hotcount[(u32ptr(pc)>>2) & (HOTCOUNT_SIZE-1)] 127 | #define hotcount_set(gg, pc, val) \ 128 | (hotcount_get((gg), (pc)) = (HotCount)(val)) 129 | 130 | /* Dispatch table management. */ 131 | LJ_FUNC void lj_dispatch_init(GG_State *GG); 132 | #if LJ_HASJIT 133 | LJ_FUNC void lj_dispatch_init_hotcount(global_State *g); 134 | #endif 135 | LJ_FUNC void lj_dispatch_update(global_State *g); 136 | 137 | /* Instruction dispatch callback for hooks or when recording. */ 138 | LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc); 139 | LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc); 140 | #if LJ_HASJIT 141 | LJ_FUNCA void LJ_FASTCALL lj_dispatch_stitch(jit_State *J, const BCIns *pc); 142 | #endif 143 | #if LJ_HASPROFILE 144 | LJ_FUNCA void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc); 145 | #endif 146 | 147 | #if LJ_HASFFI && !defined(_BUILDVM_H) 148 | /* Save/restore errno and GetLastError() around hooks, exits and recording. */ 149 | #include 150 | #if LJ_TARGET_WINDOWS 151 | #define WIN32_LEAN_AND_MEAN 152 | #include 153 | #define ERRNO_SAVE int olderr = errno; DWORD oldwerr = GetLastError(); 154 | #define ERRNO_RESTORE errno = olderr; SetLastError(oldwerr); 155 | #else 156 | #define ERRNO_SAVE int olderr = errno; 157 | #define ERRNO_RESTORE errno = olderr; 158 | #endif 159 | #else 160 | #define ERRNO_SAVE 161 | #define ERRNO_RESTORE 162 | #endif 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /src/lj_err.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Error handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_ERR_H 7 | #define _LJ_ERR_H 8 | 9 | #include 10 | 11 | #include "lj_obj.h" 12 | 13 | typedef enum { 14 | #define ERRDEF(name, msg) \ 15 | LJ_ERR_##name, LJ_ERR_##name##_ = LJ_ERR_##name + sizeof(msg)-1, 16 | #include "lj_errmsg.h" 17 | LJ_ERR__MAX 18 | } ErrMsg; 19 | 20 | LJ_DATA const char *lj_err_allmsg; 21 | #define err2msg(em) (lj_err_allmsg+(int)(em)) 22 | 23 | LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em); 24 | LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode); 25 | LJ_FUNC_NORET void lj_err_mem(lua_State *L); 26 | LJ_FUNC_NORET void LJ_FASTCALL lj_err_stkov(lua_State *L); 27 | LJ_FUNC_NORET void LJ_FASTCALL lj_err_run(lua_State *L); 28 | #if LJ_HASJIT 29 | LJ_FUNCA_NORET void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode); 30 | #endif 31 | LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em); 32 | LJ_FUNC_NORET void lj_err_lex(lua_State *L, GCstr *src, const char *tok, 33 | BCLine line, ErrMsg em, va_list argp); 34 | LJ_FUNC_NORET void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm); 35 | LJ_FUNC_NORET void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2); 36 | LJ_FUNC_NORET void lj_err_optype_call(lua_State *L, TValue *o); 37 | LJ_FUNC_NORET void lj_err_callermsg(lua_State *L, const char *msg); 38 | LJ_FUNC_NORET void lj_err_callerv(lua_State *L, ErrMsg em, ...); 39 | LJ_FUNC_NORET void lj_err_caller(lua_State *L, ErrMsg em); 40 | LJ_FUNC_NORET void lj_err_arg(lua_State *L, int narg, ErrMsg em); 41 | LJ_FUNC_NORET void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...); 42 | LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname); 43 | LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt); 44 | 45 | #if LJ_UNWIND_JIT && !LJ_ABI_WIN 46 | LJ_FUNC uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info); 47 | LJ_FUNC void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info); 48 | #else 49 | #define lj_err_register_mcode(base, sz, info) (info) 50 | #define lj_err_deregister_mcode(base, sz, info) UNUSED(base) 51 | #endif 52 | 53 | #if LJ_UNWIND_EXT && !LJ_ABI_WIN && defined(LUA_USE_ASSERT) 54 | LJ_FUNC void lj_err_verify(void); 55 | #else 56 | #define lj_err_verify() ((void)0) 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/lj_ff.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Fast function IDs. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_FF_H 7 | #define _LJ_FF_H 8 | 9 | /* Fast function ID. */ 10 | typedef enum { 11 | FF_LUA_ = FF_LUA, /* Lua function (must be 0). */ 12 | FF_C_ = FF_C, /* Regular C function (must be 1). */ 13 | #define FFDEF(name) FF_##name, 14 | #include "lj_ffdef.h" 15 | FF__MAX 16 | } FastFunc; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/lj_ffrecord.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Fast function call recorder. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_FFRECORD_H 7 | #define _LJ_FFRECORD_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_jit.h" 11 | 12 | #if LJ_HASJIT 13 | /* Data used by handlers to record a fast function. */ 14 | typedef struct RecordFFData { 15 | TValue *argv; /* Runtime argument values. */ 16 | ptrdiff_t nres; /* Number of returned results (defaults to 1). */ 17 | uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */ 18 | } RecordFFData; 19 | 20 | LJ_FUNC int32_t lj_ffrecord_select_mode(jit_State *J, TRef tr, TValue *tv); 21 | LJ_FUNC void lj_ffrecord_func(jit_State *J); 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lj_func.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Function handling (prototypes, functions and upvalues). 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_FUNC_H 7 | #define _LJ_FUNC_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Prototypes. */ 12 | LJ_FUNC void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt); 13 | 14 | /* Upvalues. */ 15 | LJ_FUNCA void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level); 16 | LJ_FUNC void LJ_FASTCALL lj_func_freeuv(global_State *g, GCupval *uv); 17 | 18 | /* Functions (closures). */ 19 | LJ_FUNC GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env); 20 | LJ_FUNC GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env); 21 | LJ_FUNCA GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent); 22 | LJ_FUNC void LJ_FASTCALL lj_func_free(global_State *g, GCfunc *c); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lj_gc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Garbage collector. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_GC_H 7 | #define _LJ_GC_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Garbage collector states. Order matters. */ 12 | enum { 13 | GCSpause, GCSpropagate, GCSatomic, GCSsweepstring, GCSsweep, GCSfinalize 14 | }; 15 | 16 | /* Bitmasks for marked field of GCobj. */ 17 | #define LJ_GC_WHITE0 0x01 18 | #define LJ_GC_WHITE1 0x02 19 | #define LJ_GC_BLACK 0x04 20 | #define LJ_GC_FINALIZED 0x08 21 | #define LJ_GC_WEAKKEY 0x08 22 | #define LJ_GC_WEAKVAL 0x10 23 | #define LJ_GC_CDATA_FIN 0x10 24 | #define LJ_GC_FIXED 0x20 25 | #define LJ_GC_SFIXED 0x40 26 | 27 | #define LJ_GC_WHITES (LJ_GC_WHITE0 | LJ_GC_WHITE1) 28 | #define LJ_GC_COLORS (LJ_GC_WHITES | LJ_GC_BLACK) 29 | #define LJ_GC_WEAK (LJ_GC_WEAKKEY | LJ_GC_WEAKVAL) 30 | 31 | /* Macros to test and set GCobj colors. */ 32 | #define iswhite(x) ((x)->gch.marked & LJ_GC_WHITES) 33 | #define isblack(x) ((x)->gch.marked & LJ_GC_BLACK) 34 | #define isgray(x) (!((x)->gch.marked & (LJ_GC_BLACK|LJ_GC_WHITES))) 35 | #define tviswhite(x) (tvisgcv(x) && iswhite(gcV(x))) 36 | #define otherwhite(g) (g->gc.currentwhite ^ LJ_GC_WHITES) 37 | #define isdead(g, v) ((v)->gch.marked & otherwhite(g) & LJ_GC_WHITES) 38 | 39 | #define curwhite(g) ((g)->gc.currentwhite & LJ_GC_WHITES) 40 | #define newwhite(g, x) (obj2gco(x)->gch.marked = (uint8_t)curwhite(g)) 41 | #define makewhite(g, x) \ 42 | ((x)->gch.marked = ((x)->gch.marked & (uint8_t)~LJ_GC_COLORS) | curwhite(g)) 43 | #define flipwhite(x) ((x)->gch.marked ^= LJ_GC_WHITES) 44 | #define black2gray(x) ((x)->gch.marked &= (uint8_t)~LJ_GC_BLACK) 45 | #define fixstring(s) ((s)->marked |= LJ_GC_FIXED) 46 | #define markfinalized(x) ((x)->gch.marked |= LJ_GC_FINALIZED) 47 | 48 | /* Collector. */ 49 | LJ_FUNC size_t lj_gc_separateudata(global_State *g, int all); 50 | LJ_FUNC void lj_gc_finalize_udata(lua_State *L); 51 | #if LJ_HASFFI 52 | LJ_FUNC void lj_gc_finalize_cdata(lua_State *L); 53 | #else 54 | #define lj_gc_finalize_cdata(L) UNUSED(L) 55 | #endif 56 | LJ_FUNC void lj_gc_freeall(global_State *g); 57 | LJ_FUNCA int LJ_FASTCALL lj_gc_step(lua_State *L); 58 | LJ_FUNCA void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L); 59 | #if LJ_HASJIT 60 | LJ_FUNC int LJ_FASTCALL lj_gc_step_jit(global_State *g, MSize steps); 61 | #endif 62 | LJ_FUNC void lj_gc_fullgc(lua_State *L); 63 | 64 | /* GC check: drive collector forward if the GC threshold has been reached. */ 65 | #define lj_gc_check(L) \ 66 | { if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \ 67 | lj_gc_step(L); } 68 | #define lj_gc_check_fixtop(L) \ 69 | { if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \ 70 | lj_gc_step_fixtop(L); } 71 | 72 | /* Write barriers. */ 73 | LJ_FUNC void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v); 74 | LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv); 75 | LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv); 76 | #if LJ_HASJIT 77 | LJ_FUNC void lj_gc_barriertrace(global_State *g, uint32_t traceno); 78 | #endif 79 | 80 | /* Move the GC propagation frontier back for tables (make it gray again). */ 81 | static LJ_AINLINE void lj_gc_barrierback(global_State *g, GCtab *t) 82 | { 83 | GCobj *o = obj2gco(t); 84 | lj_assertG(isblack(o) && !isdead(g, o), 85 | "bad object states for backward barrier"); 86 | lj_assertG(g->gc.state != GCSfinalize && g->gc.state != GCSpause, 87 | "bad GC state"); 88 | black2gray(o); 89 | setgcrefr(t->gclist, g->gc.grayagain); 90 | setgcref(g->gc.grayagain, o); 91 | } 92 | 93 | /* Barrier for stores to table objects. TValue and GCobj variant. */ 94 | #define lj_gc_anybarriert(L, t) \ 95 | { if (LJ_UNLIKELY(isblack(obj2gco(t)))) lj_gc_barrierback(G(L), (t)); } 96 | #define lj_gc_barriert(L, t, tv) \ 97 | { if (tviswhite(tv) && isblack(obj2gco(t))) \ 98 | lj_gc_barrierback(G(L), (t)); } 99 | #define lj_gc_objbarriert(L, t, o) \ 100 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) \ 101 | lj_gc_barrierback(G(L), (t)); } 102 | 103 | /* Barrier for stores to any other object. TValue and GCobj variant. */ 104 | #define lj_gc_barrier(L, p, tv) \ 105 | { if (tviswhite(tv) && isblack(obj2gco(p))) \ 106 | lj_gc_barrierf(G(L), obj2gco(p), gcV(tv)); } 107 | #define lj_gc_objbarrier(L, p, o) \ 108 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ 109 | lj_gc_barrierf(G(L), obj2gco(p), obj2gco(o)); } 110 | 111 | /* Allocator. */ 112 | LJ_FUNC void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz); 113 | LJ_FUNC void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size); 114 | LJ_FUNC void *lj_mem_grow(lua_State *L, void *p, 115 | MSize *szp, MSize lim, MSize esz); 116 | 117 | #define lj_mem_new(L, s) lj_mem_realloc(L, NULL, 0, (s)) 118 | 119 | static LJ_AINLINE void lj_mem_free(global_State *g, void *p, size_t osize) 120 | { 121 | g->gc.total -= (GCSize)osize; 122 | g->allocf(g->allocd, p, osize, 0); 123 | } 124 | 125 | #define lj_mem_newvec(L, n, t) ((t *)lj_mem_new(L, (GCSize)((n)*sizeof(t)))) 126 | #define lj_mem_reallocvec(L, p, on, n, t) \ 127 | ((p) = (t *)lj_mem_realloc(L, p, (on)*sizeof(t), (GCSize)((n)*sizeof(t)))) 128 | #define lj_mem_growvec(L, p, n, m, t) \ 129 | ((p) = (t *)lj_mem_grow(L, (p), &(n), (m), (MSize)sizeof(t))) 130 | #define lj_mem_freevec(g, p, n, t) lj_mem_free(g, (p), (n)*sizeof(t)) 131 | 132 | #define lj_mem_newobj(L, t) ((t *)lj_mem_newgco(L, sizeof(t))) 133 | #define lj_mem_newt(L, s, t) ((t *)lj_mem_new(L, (s))) 134 | #define lj_mem_freet(g, p) lj_mem_free(g, (p), sizeof(*(p))) 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/lj_gdbjit.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Client for the GDB JIT API. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_GDBJIT_H 7 | #define _LJ_GDBJIT_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_jit.h" 11 | 12 | #if LJ_HASJIT && defined(LUAJIT_USE_GDBJIT) 13 | 14 | LJ_FUNC void lj_gdbjit_addtrace(jit_State *J, GCtrace *T); 15 | LJ_FUNC void lj_gdbjit_deltrace(jit_State *J, GCtrace *T); 16 | 17 | #else 18 | #define lj_gdbjit_addtrace(J, T) UNUSED(T) 19 | #define lj_gdbjit_deltrace(J, T) UNUSED(T) 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/lj_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lj_arch.h" 3 | #include "lj_jit.h" 4 | #include "lj_vm.h" 5 | #include "lj_str.h" 6 | 7 | #if LJ_TARGET_ARM && LJ_TARGET_LINUX 8 | #include 9 | #endif 10 | 11 | #ifdef _MSC_VER 12 | /* 13 | ** Append a function pointer to the static constructor table executed by 14 | ** the C runtime. 15 | ** Based on https://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc 16 | ** see also https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization. 17 | */ 18 | #pragma section(".CRT$XCU",read) 19 | #define LJ_INITIALIZER2_(f,p) \ 20 | static void f(void); \ 21 | __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ 22 | __pragma(comment(linker,"/include:" p #f "_")) \ 23 | static void f(void) 24 | #ifdef _WIN64 25 | #define LJ_INITIALIZER(f) LJ_INITIALIZER2_(f,"") 26 | #else 27 | #define LJ_INITIALIZER(f) LJ_INITIALIZER2_(f,"_") 28 | #endif 29 | 30 | #else 31 | #define LJ_INITIALIZER(f) static void __attribute__((constructor)) f(void) 32 | #endif 33 | 34 | 35 | #ifdef LJ_HAS_OPTIMISED_HASH 36 | static void str_hash_init(uint32_t flags) 37 | { 38 | if (flags & JIT_F_SSE4_2) 39 | str_hash_init_sse42 (); 40 | } 41 | 42 | /* CPU detection for interpreter features such as string hash function 43 | selection. We choose to cherry-pick from lj_cpudetect and not have a single 44 | initializer to make sure that merges with LuaJIT/LuaJIT remain 45 | convenient. */ 46 | LJ_INITIALIZER(lj_init_cpuflags) 47 | { 48 | uint32_t flags = 0; 49 | #if LJ_TARGET_X86ORX64 50 | 51 | uint32_t vendor[4]; 52 | uint32_t features[4]; 53 | if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { 54 | flags |= ((features[2] >> 0)&1) * JIT_F_SSE3; 55 | flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; 56 | flags |= ((features[2] >> 20)&1) * JIT_F_SSE4_2; 57 | if (vendor[0] >= 7) { 58 | uint32_t xfeatures[4]; 59 | lj_vm_cpuid(7, xfeatures); 60 | flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2; 61 | } 62 | } 63 | 64 | #endif 65 | 66 | /* The reason why we initialized early: select our string hash functions. */ 67 | str_hash_init (flags); 68 | } 69 | #endif 70 | -------------------------------------------------------------------------------- /src/lj_lex.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Lexical analyzer. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_LEX_H 7 | #define _LJ_LEX_H 8 | 9 | #include 10 | 11 | #include "lj_obj.h" 12 | #include "lj_err.h" 13 | 14 | /* Lua lexer tokens. */ 15 | #define TKDEF(_, __) \ 16 | _(and) _(break) _(do) _(else) _(elseif) _(end) _(false) \ 17 | _(for) _(function) _(goto) _(if) _(in) _(local) _(nil) _(not) _(or) \ 18 | _(repeat) _(return) _(then) _(true) _(until) _(while) \ 19 | __(concat, ..) __(dots, ...) __(eq, ==) __(ge, >=) __(le, <=) __(ne, ~=) \ 20 | __(label, ::) __(number, ) __(name, ) __(string, ) \ 21 | __(eof, ) 22 | 23 | enum { 24 | TK_OFS = 256, 25 | #define TKENUM1(name) TK_##name, 26 | #define TKENUM2(name, sym) TK_##name, 27 | TKDEF(TKENUM1, TKENUM2) 28 | #undef TKENUM1 29 | #undef TKENUM2 30 | TK_RESERVED = TK_while - TK_OFS 31 | }; 32 | 33 | typedef int LexChar; /* Lexical character. Unsigned ext. from char. */ 34 | typedef int LexToken; /* Lexical token. */ 35 | 36 | /* Combined bytecode ins/line. Only used during bytecode generation. */ 37 | typedef struct BCInsLine { 38 | BCIns ins; /* Bytecode instruction. */ 39 | BCLine line; /* Line number for this bytecode. */ 40 | } BCInsLine; 41 | 42 | /* Info for local variables. Only used during bytecode generation. */ 43 | typedef struct VarInfo { 44 | GCRef name; /* Local variable name or goto/label name. */ 45 | BCPos startpc; /* First point where the local variable is active. */ 46 | BCPos endpc; /* First point where the local variable is dead. */ 47 | uint8_t slot; /* Variable slot. */ 48 | uint8_t info; /* Variable/goto/label info. */ 49 | } VarInfo; 50 | 51 | /* Lua lexer state. */ 52 | typedef struct LexState { 53 | struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */ 54 | struct lua_State *L; /* Lua state. */ 55 | TValue tokval; /* Current token value. */ 56 | TValue lookaheadval; /* Lookahead token value. */ 57 | const char *p; /* Current position in input buffer. */ 58 | const char *pe; /* End of input buffer. */ 59 | LexChar c; /* Current character. */ 60 | LexToken tok; /* Current token. */ 61 | LexToken lookahead; /* Lookahead token. */ 62 | SBuf sb; /* String buffer for tokens. */ 63 | lua_Reader rfunc; /* Reader callback. */ 64 | void *rdata; /* Reader callback data. */ 65 | BCLine linenumber; /* Input line counter. */ 66 | BCLine lastline; /* Line of last token. */ 67 | GCstr *chunkname; /* Current chunk name (interned string). */ 68 | const char *chunkarg; /* Chunk name argument. */ 69 | const char *mode; /* Allow loading bytecode (b) and/or source text (t). */ 70 | VarInfo *vstack; /* Stack for names and extents of local variables. */ 71 | MSize sizevstack; /* Size of variable stack. */ 72 | MSize vtop; /* Top of variable stack. */ 73 | BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */ 74 | MSize sizebcstack; /* Size of bytecode stack. */ 75 | uint32_t level; /* Syntactical nesting level. */ 76 | int endmark; /* Trust bytecode end marker, even if not at EOF. */ 77 | int fr2; /* Generate bytecode for LJ_FR2 mode. */ 78 | } LexState; 79 | 80 | LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); 81 | LJ_FUNC void lj_lex_cleanup(lua_State *L, LexState *ls); 82 | LJ_FUNC void lj_lex_next(LexState *ls); 83 | LJ_FUNC LexToken lj_lex_lookahead(LexState *ls); 84 | LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken tok); 85 | LJ_FUNC_NORET void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...); 86 | LJ_FUNC void lj_lex_init(lua_State *L); 87 | 88 | #ifdef LUA_USE_ASSERT 89 | #define lj_assertLS(c, ...) (lj_assertG_(G(ls->L), (c), __VA_ARGS__)) 90 | #else 91 | #define lj_assertLS(c, ...) ((void)ls) 92 | #endif 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/lj_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Library function support. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_LIB_H 7 | #define _LJ_LIB_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* 12 | ** A fallback handler is called by the assembler VM if the fast path fails: 13 | ** 14 | ** - too few arguments: unrecoverable. 15 | ** - wrong argument type: recoverable, if coercion succeeds. 16 | ** - bad argument value: unrecoverable. 17 | ** - stack overflow: recoverable, if stack reallocation succeeds. 18 | ** - extra handling: recoverable. 19 | ** 20 | ** The unrecoverable cases throw an error with lj_err_arg(), lj_err_argtype(), 21 | ** lj_err_caller() or lj_err_callermsg(). 22 | ** The recoverable cases return 0 or the number of results + 1. 23 | ** The assembler VM retries the fast path only if 0 is returned. 24 | ** This time the fallback must not be called again or it gets stuck in a loop. 25 | */ 26 | 27 | /* Return values from fallback handler. */ 28 | #define FFH_RETRY 0 29 | #define FFH_UNREACHABLE FFH_RETRY 30 | #define FFH_RES(n) ((n)+1) 31 | #define FFH_TAILCALL (-1) 32 | 33 | LJ_FUNC TValue *lj_lib_checkany(lua_State *L, int narg); 34 | LJ_FUNC GCstr *lj_lib_checkstr(lua_State *L, int narg); 35 | LJ_FUNC GCstr *lj_lib_optstr(lua_State *L, int narg); 36 | #if LJ_DUALNUM 37 | LJ_FUNC void lj_lib_checknumber(lua_State *L, int narg); 38 | #else 39 | #define lj_lib_checknumber(L, narg) lj_lib_checknum((L), (narg)) 40 | #endif 41 | LJ_FUNC lua_Number lj_lib_checknum(lua_State *L, int narg); 42 | LJ_FUNC int32_t lj_lib_checkint(lua_State *L, int narg); 43 | LJ_FUNC int32_t lj_lib_optint(lua_State *L, int narg, int32_t def); 44 | LJ_FUNC GCfunc *lj_lib_checkfunc(lua_State *L, int narg); 45 | LJ_FUNC GCproto *lj_lib_checkLproto(lua_State *L, int narg, int nolua); 46 | LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg); 47 | LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg); 48 | LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); 49 | LJ_FUNC GCcdata *lj_lib_checkcdata(lua_State *L, int narg); 50 | 51 | #if LJ_HASBUFFER 52 | LJ_FUNC GCstr *lj_lib_checkstrx(lua_State *L, int narg); 53 | LJ_FUNC int32_t lj_lib_checkintrange(lua_State *L, int narg, 54 | int32_t a, int32_t b); 55 | #endif 56 | 57 | /* Avoid including lj_frame.h. */ 58 | #if LJ_GC64 59 | #define lj_lib_upvalue(L, n) \ 60 | (&gcval(L->base-2)->fn.c.upvalue[(n)-1]) 61 | #elif LJ_FR2 62 | #define lj_lib_upvalue(L, n) \ 63 | (&gcref((L->base-2)->gcr)->fn.c.upvalue[(n)-1]) 64 | #else 65 | #define lj_lib_upvalue(L, n) \ 66 | (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1]) 67 | #endif 68 | 69 | #if LJ_TARGET_WINDOWS 70 | #define lj_lib_checkfpu(L) \ 71 | do { setnumV(L->top++, (lua_Number)1437217655); \ 72 | if (lua_tointeger(L, -1) != 1437217655) lj_err_caller(L, LJ_ERR_BADFPU); \ 73 | L->top--; } while (0) 74 | #else 75 | #define lj_lib_checkfpu(L) UNUSED(L) 76 | #endif 77 | 78 | LJ_FUNC GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n); 79 | #define lj_lib_pushcf(L, fn, id) (lj_lib_pushcc(L, (fn), (id), 0)) 80 | 81 | /* Library function declarations. Scanned by buildvm. */ 82 | #define LJLIB_CF(name) static int lj_cf_##name(lua_State *L) 83 | #define LJLIB_ASM(name) static int lj_ffh_##name(lua_State *L) 84 | #define LJLIB_ASM_(name) 85 | #define LJLIB_LUA(name) 86 | #define LJLIB_SET(name) 87 | #define LJLIB_PUSH(arg) 88 | #define LJLIB_REC(handler) 89 | #define LJLIB_NOREGUV 90 | #define LJLIB_NOREG 91 | 92 | #define LJ_LIB_REG(L, regname, name) \ 93 | lj_lib_register(L, regname, lj_lib_init_##name, lj_lib_cf_##name) 94 | 95 | LJ_FUNC void lj_lib_register(lua_State *L, const char *libname, 96 | const uint8_t *init, const lua_CFunction *cf); 97 | LJ_FUNC void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f, 98 | GCtab *env); 99 | LJ_FUNC int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, 100 | const char *name); 101 | 102 | /* Library init data tags. */ 103 | #define LIBINIT_LENMASK 0x3f 104 | #define LIBINIT_TAGMASK 0xc0 105 | #define LIBINIT_CF 0x00 106 | #define LIBINIT_ASM 0x40 107 | #define LIBINIT_ASM_ 0x80 108 | #define LIBINIT_STRING 0xc0 109 | #define LIBINIT_MAXSTR 0x38 110 | #define LIBINIT_LUA 0xf9 111 | #define LIBINIT_SET 0xfa 112 | #define LIBINIT_NUMBER 0xfb 113 | #define LIBINIT_COPY 0xfc 114 | #define LIBINIT_LASTCL 0xfd 115 | #define LIBINIT_FFID 0xfe 116 | #define LIBINIT_END 0xff 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/lj_load.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Load and dump code. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #define lj_load_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | #include "lauxlib.h" 14 | 15 | #include "lj_obj.h" 16 | #include "lj_gc.h" 17 | #include "lj_err.h" 18 | #include "lj_buf.h" 19 | #include "lj_func.h" 20 | #include "lj_frame.h" 21 | #include "lj_vm.h" 22 | #include "lj_lex.h" 23 | #include "lj_bcdump.h" 24 | #include "lj_parse.h" 25 | 26 | /* -- Load Lua source code and bytecode ----------------------------------- */ 27 | 28 | static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) 29 | { 30 | LexState *ls = (LexState *)ud; 31 | GCproto *pt; 32 | GCfunc *fn; 33 | int bc; 34 | UNUSED(dummy); 35 | cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ 36 | bc = lj_lex_setup(L, ls); 37 | if (ls->mode) { 38 | int xmode = 1; 39 | const char *mode = ls->mode; 40 | char c; 41 | while ((c = *mode++)) { 42 | if (c == (bc ? 'b' : 't')) xmode = 0; 43 | if (c == (LJ_FR2 ? 'W' : 'X')) ls->fr2 = !LJ_FR2; 44 | } 45 | if (xmode) { 46 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); 47 | lj_err_throw(L, LUA_ERRSYNTAX); 48 | } 49 | } 50 | pt = bc ? lj_bcread(ls) : lj_parse(ls); 51 | if (ls->fr2 == LJ_FR2) { 52 | fn = lj_func_newL_empty(L, pt, tabref(L->env)); 53 | /* Don't combine above/below into one statement. */ 54 | setfuncV(L, L->top++, fn); 55 | } else { 56 | /* Non-native generation returns a dumpable, but non-runnable prototype. */ 57 | setprotoV(L, L->top++, pt); 58 | } 59 | return NULL; 60 | } 61 | 62 | LUA_API int lua_loadx(lua_State *L, lua_Reader reader, void *data, 63 | const char *chunkname, const char *mode) 64 | { 65 | LexState ls; 66 | int status; 67 | ls.rfunc = reader; 68 | ls.rdata = data; 69 | ls.chunkarg = chunkname ? chunkname : "?"; 70 | ls.mode = mode; 71 | lj_buf_init(L, &ls.sb); 72 | status = lj_vm_cpcall(L, NULL, &ls, cpparser); 73 | lj_lex_cleanup(L, &ls); 74 | lj_gc_check(L); 75 | return status; 76 | } 77 | 78 | LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data, 79 | const char *chunkname) 80 | { 81 | return lua_loadx(L, reader, data, chunkname, NULL); 82 | } 83 | 84 | typedef struct FileReaderCtx { 85 | FILE *fp; 86 | char buf[LUAL_BUFFERSIZE]; 87 | } FileReaderCtx; 88 | 89 | static const char *reader_file(lua_State *L, void *ud, size_t *size) 90 | { 91 | FileReaderCtx *ctx = (FileReaderCtx *)ud; 92 | UNUSED(L); 93 | if (feof(ctx->fp)) return NULL; 94 | *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp); 95 | return *size > 0 ? ctx->buf : NULL; 96 | } 97 | 98 | LUALIB_API int luaL_loadfilex(lua_State *L, const char *filename, 99 | const char *mode) 100 | { 101 | FileReaderCtx ctx; 102 | int status; 103 | const char *chunkname; 104 | int err = 0; 105 | if (filename) { 106 | chunkname = lua_pushfstring(L, "@%s", filename); 107 | ctx.fp = fopen(filename, "rb"); 108 | if (ctx.fp == NULL) { 109 | L->top--; 110 | lua_pushfstring(L, "cannot open %s: %s", filename, strerror(errno)); 111 | return LUA_ERRFILE; 112 | } 113 | } else { 114 | ctx.fp = stdin; 115 | chunkname = "=stdin"; 116 | } 117 | status = lua_loadx(L, reader_file, &ctx, chunkname, mode); 118 | if (ferror(ctx.fp)) err = errno; 119 | if (filename) { 120 | fclose(ctx.fp); 121 | L->top--; 122 | copyTV(L, L->top-1, L->top); 123 | } 124 | if (err) { 125 | const char *fname = filename ? filename : "stdin"; 126 | L->top--; 127 | lua_pushfstring(L, "cannot read %s: %s", fname, strerror(err)); 128 | return LUA_ERRFILE; 129 | } 130 | return status; 131 | } 132 | 133 | LUALIB_API int luaL_loadfile(lua_State *L, const char *filename) 134 | { 135 | return luaL_loadfilex(L, filename, NULL); 136 | } 137 | 138 | typedef struct StringReaderCtx { 139 | const char *str; 140 | size_t size; 141 | } StringReaderCtx; 142 | 143 | static const char *reader_string(lua_State *L, void *ud, size_t *size) 144 | { 145 | StringReaderCtx *ctx = (StringReaderCtx *)ud; 146 | UNUSED(L); 147 | if (ctx->size == 0) return NULL; 148 | *size = ctx->size; 149 | ctx->size = 0; 150 | return ctx->str; 151 | } 152 | 153 | LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buf, size_t size, 154 | const char *name, const char *mode) 155 | { 156 | StringReaderCtx ctx; 157 | ctx.str = buf; 158 | ctx.size = size; 159 | return lua_loadx(L, reader_string, &ctx, name, mode); 160 | } 161 | 162 | LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size, 163 | const char *name) 164 | { 165 | return luaL_loadbufferx(L, buf, size, name, NULL); 166 | } 167 | 168 | LUALIB_API int luaL_loadstring(lua_State *L, const char *s) 169 | { 170 | return luaL_loadbuffer(L, s, strlen(s), s); 171 | } 172 | 173 | /* -- Dump bytecode ------------------------------------------------------- */ 174 | 175 | LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data) 176 | { 177 | cTValue *o = L->top-1; 178 | uint32_t flags = LJ_FR2*BCDUMP_F_FR2; /* Default mode for legacy C API. */ 179 | lj_checkapi(L->top > L->base, "top slot empty"); 180 | if (tvisfunc(o) && isluafunc(funcV(o))) 181 | return lj_bcwrite(L, funcproto(funcV(o)), writer, data, flags); 182 | else 183 | return 1; 184 | } 185 | 186 | -------------------------------------------------------------------------------- /src/lj_mcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Machine code management. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_MCODE_H 7 | #define _LJ_MCODE_H 8 | 9 | #include "lj_obj.h" 10 | 11 | #if LJ_HASJIT || LJ_HASFFI 12 | LJ_FUNC void lj_mcode_sync(void *start, void *end); 13 | #endif 14 | 15 | #if LJ_HASJIT 16 | 17 | #include "lj_jit.h" 18 | 19 | LJ_FUNC void lj_mcode_free(jit_State *J); 20 | LJ_FUNC MCode *lj_mcode_reserve(jit_State *J, MCode **lim); 21 | LJ_FUNC void lj_mcode_commit(jit_State *J, MCode *m); 22 | LJ_FUNC void lj_mcode_abort(jit_State *J); 23 | LJ_FUNC MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish); 24 | LJ_FUNC_NORET void lj_mcode_limiterr(jit_State *J, size_t need); 25 | 26 | #define lj_mcode_commitbot(J, m) (J->mcbot = (m)) 27 | 28 | #endif 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/lj_meta.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Metamethod handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_META_H 7 | #define _LJ_META_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Metamethod handling */ 12 | LJ_FUNC void lj_meta_init(lua_State *L); 13 | LJ_FUNC cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name); 14 | LJ_FUNC cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm); 15 | #if LJ_HASFFI 16 | LJ_FUNC int lj_meta_tailcall(lua_State *L, cTValue *tv); 17 | #endif 18 | 19 | #define lj_meta_fastg(g, mt, mm) \ 20 | ((mt) == NULL ? NULL : ((mt)->nomm & (1u<<(mm))) ? NULL : \ 21 | lj_meta_cache(mt, mm, mmname_str(g, mm))) 22 | #define lj_meta_fast(L, mt, mm) lj_meta_fastg(G(L), mt, mm) 23 | 24 | /* C helpers for some instructions, called from assembler VM. */ 25 | LJ_FUNCA cTValue *lj_meta_tget(lua_State *L, cTValue *o, cTValue *k); 26 | LJ_FUNCA TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k); 27 | LJ_FUNCA TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, 28 | cTValue *rc, BCReg op); 29 | LJ_FUNCA TValue *lj_meta_cat(lua_State *L, TValue *top, int left); 30 | LJ_FUNCA TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o); 31 | LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne); 32 | LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins); 33 | LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op); 34 | LJ_FUNCA void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp); 35 | LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top); 36 | LJ_FUNCA void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/lj_obj.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Miscellaneous object handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lj_obj_c 7 | #define LUA_CORE 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Object type names. */ 12 | LJ_DATADEF const char *const lj_obj_typename[] = { /* ORDER LUA_T */ 13 | "no value", "nil", "boolean", "userdata", "number", "string", 14 | "table", "function", "userdata", "thread", "proto", "cdata" 15 | }; 16 | 17 | LJ_DATADEF const char *const lj_obj_itypename[] = { /* ORDER LJ_T */ 18 | "nil", "boolean", "boolean", "userdata", "string", "upval", "thread", 19 | "proto", "function", "trace", "cdata", "table", "userdata", "number" 20 | }; 21 | 22 | /* Compare two objects without calling metamethods. */ 23 | int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2) 24 | { 25 | if (itype(o1) == itype(o2)) { 26 | if (tvispri(o1)) 27 | return 1; 28 | if (!tvisnum(o1)) 29 | return gcrefeq(o1->gcr, o2->gcr); 30 | } else if (!tvisnumber(o1) || !tvisnumber(o2)) { 31 | return 0; 32 | } 33 | return numberVnum(o1) == numberVnum(o2); 34 | } 35 | 36 | /* Return pointer to object or its object data. */ 37 | const void * LJ_FASTCALL lj_obj_ptr(global_State *g, cTValue *o) 38 | { 39 | UNUSED(g); 40 | if (tvisudata(o)) 41 | return uddata(udataV(o)); 42 | else if (tvislightud(o)) 43 | return lightudV(g, o); 44 | else if (LJ_HASFFI && tviscdata(o)) 45 | return cdataptr(cdataV(o)); 46 | else if (tvisgcv(o)) 47 | return gcV(o); 48 | else 49 | return NULL; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/lj_opt_dce.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** DCE: Dead Code Elimination. Pre-LOOP only -- ASM already performs DCE. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lj_opt_dce_c 7 | #define LUA_CORE 8 | 9 | #include "lj_obj.h" 10 | 11 | #if LJ_HASJIT 12 | 13 | #include "lj_ir.h" 14 | #include "lj_jit.h" 15 | #include "lj_iropt.h" 16 | 17 | /* Some local macros to save typing. Undef'd at the end. */ 18 | #define IR(ref) (&J->cur.ir[(ref)]) 19 | 20 | /* Scan through all snapshots and mark all referenced instructions. */ 21 | static void dce_marksnap(jit_State *J) 22 | { 23 | SnapNo i, nsnap = J->cur.nsnap; 24 | for (i = 0; i < nsnap; i++) { 25 | SnapShot *snap = &J->cur.snap[i]; 26 | SnapEntry *map = &J->cur.snapmap[snap->mapofs]; 27 | MSize n, nent = snap->nent; 28 | for (n = 0; n < nent; n++) { 29 | IRRef ref = snap_ref(map[n]); 30 | if (ref >= REF_FIRST) 31 | irt_setmark(IR(ref)->t); 32 | } 33 | } 34 | } 35 | 36 | /* Backwards propagate marks. Replace unused instructions with NOPs. */ 37 | static void dce_propagate(jit_State *J) 38 | { 39 | IRRef1 *pchain[IR__MAX]; 40 | IRRef ins; 41 | uint32_t i; 42 | for (i = 0; i < IR__MAX; i++) pchain[i] = &J->chain[i]; 43 | for (ins = J->cur.nins-1; ins >= REF_FIRST; ins--) { 44 | IRIns *ir = IR(ins); 45 | if (irt_ismarked(ir->t)) { 46 | irt_clearmark(ir->t); 47 | } else if (!ir_sideeff(ir)) { 48 | *pchain[ir->o] = ir->prev; /* Reroute original instruction chain. */ 49 | lj_ir_nop(ir); 50 | continue; 51 | } 52 | pchain[ir->o] = &ir->prev; 53 | if (ir->op1 >= REF_FIRST) irt_setmark(IR(ir->op1)->t); 54 | if (ir->op2 >= REF_FIRST) irt_setmark(IR(ir->op2)->t); 55 | } 56 | } 57 | 58 | /* Dead Code Elimination. 59 | ** 60 | ** First backpropagate marks for all used instructions. Then replace 61 | ** the unused ones with a NOP. Note that compressing the IR to eliminate 62 | ** the NOPs does not pay off. 63 | */ 64 | void lj_opt_dce(jit_State *J) 65 | { 66 | if ((J->flags & JIT_F_OPT_DCE)) { 67 | dce_marksnap(J); 68 | dce_propagate(J); 69 | memset(J->bpropcache, 0, sizeof(J->bpropcache)); /* Invalidate cache. */ 70 | } 71 | } 72 | 73 | #undef IR 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/lj_parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Lua parser (source code -> bytecode). 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_PARSE_H 7 | #define _LJ_PARSE_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_lex.h" 11 | 12 | LJ_FUNC GCproto *lj_parse(LexState *ls); 13 | LJ_FUNC GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t l); 14 | #if LJ_HASFFI 15 | LJ_FUNC void lj_parse_keepcdata(LexState *ls, TValue *tv, GCcdata *cd); 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/lj_prng.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Pseudo-random number generation. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_PRNG_H 7 | #define _LJ_PRNG_H 8 | 9 | #include "lj_def.h" 10 | 11 | LJ_FUNC int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs); 12 | LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs); 13 | LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs); 14 | 15 | /* This is just the precomputed result of lib_math.c:random_seed(rs, 0.0). */ 16 | static LJ_AINLINE void lj_prng_seed_fixed(PRNGState *rs) 17 | { 18 | rs->u[0] = U64x(a0d27757,0a345b8c); 19 | rs->u[1] = U64x(764a296c,5d4aa64f); 20 | rs->u[2] = U64x(51220704,070adeaa); 21 | rs->u[3] = U64x(2a2717b5,a7b7b927); 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lj_profile.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Low-overhead profiling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_PROFILE_H 7 | #define _LJ_PROFILE_H 8 | 9 | #include "lj_obj.h" 10 | 11 | #if LJ_HASPROFILE 12 | 13 | LJ_FUNC void LJ_FASTCALL lj_profile_interpreter(lua_State *L); 14 | #if !LJ_PROFILE_SIGPROF 15 | LJ_FUNC void LJ_FASTCALL lj_profile_hook_enter(global_State *g); 16 | LJ_FUNC void LJ_FASTCALL lj_profile_hook_leave(global_State *g); 17 | #endif 18 | 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/lj_record.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Trace recorder (bytecode -> SSA IR). 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_RECORD_H 7 | #define _LJ_RECORD_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_jit.h" 11 | 12 | #if LJ_HASJIT 13 | /* Context for recording an indexed load/store. */ 14 | typedef struct RecordIndex { 15 | TValue tabv; /* Runtime value of table (or indexed object). */ 16 | TValue keyv; /* Runtime value of key. */ 17 | TValue valv; /* Runtime value of stored value. */ 18 | TValue mobjv; /* Runtime value of metamethod object. */ 19 | GCtab *mtv; /* Runtime value of metatable object. */ 20 | cTValue *oldv; /* Runtime value of previously stored value. */ 21 | TRef tab; /* Table (or indexed object) reference. */ 22 | TRef key; /* Key reference. */ 23 | TRef val; /* Value reference for a store or 0 for a load. */ 24 | TRef mt; /* Metatable reference. */ 25 | TRef mobj; /* Metamethod object reference. */ 26 | int idxchain; /* Index indirections left or 0 for raw lookup. */ 27 | } RecordIndex; 28 | 29 | LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b, 30 | cTValue *av, cTValue *bv); 31 | LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk); 32 | LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o); 33 | LJ_FUNC TRef lj_record_vload(jit_State *J, TRef ref, MSize idx, IRType t); 34 | 35 | LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs); 36 | LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs); 37 | LJ_FUNC void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults); 38 | 39 | LJ_FUNC int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm); 40 | LJ_FUNC TRef lj_record_idx(jit_State *J, RecordIndex *ix); 41 | LJ_FUNC int lj_record_next(jit_State *J, RecordIndex *ix); 42 | 43 | LJ_FUNC void lj_record_ins(jit_State *J); 44 | LJ_FUNC void lj_record_setup(jit_State *J); 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/lj_serialize.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Object de/serialization. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_SERIALIZE_H 7 | #define _LJ_SERIALIZE_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_buf.h" 11 | 12 | #if LJ_HASBUFFER 13 | 14 | #define LJ_SERIALIZE_DEPTH 100 /* Default depth. */ 15 | 16 | LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep_str(lua_State *L, GCtab *dict); 17 | LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep_mt(lua_State *L, GCtab *dict); 18 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); 19 | LJ_FUNC char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); 20 | LJ_FUNC GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o); 21 | LJ_FUNC void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str); 22 | #if LJ_HASJIT 23 | LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx); 24 | #endif 25 | 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/lj_snap.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Snapshot handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_SNAP_H 7 | #define _LJ_SNAP_H 8 | 9 | #include "lj_obj.h" 10 | #include "lj_jit.h" 11 | 12 | #if LJ_HASJIT 13 | LJ_FUNC void lj_snap_add(jit_State *J); 14 | LJ_FUNC void lj_snap_purge(jit_State *J); 15 | LJ_FUNC void lj_snap_shrink(jit_State *J); 16 | LJ_FUNC IRIns *lj_snap_regspmap(jit_State *J, GCtrace *T, SnapNo snapno, 17 | IRIns *ir); 18 | LJ_FUNC void lj_snap_replay(jit_State *J, GCtrace *T); 19 | LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr); 20 | LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need); 21 | LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need); 22 | 23 | static LJ_AINLINE void lj_snap_grow_buf(jit_State *J, MSize need) 24 | { 25 | if (LJ_UNLIKELY(need > J->sizesnap)) lj_snap_grow_buf_(J, need); 26 | } 27 | 28 | static LJ_AINLINE void lj_snap_grow_map(jit_State *J, MSize need) 29 | { 30 | if (LJ_UNLIKELY(need > J->sizesnapmap)) lj_snap_grow_map_(J, need); 31 | } 32 | 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/lj_state.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** State and stack handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_STATE_H 7 | #define _LJ_STATE_H 8 | 9 | #include "lj_obj.h" 10 | 11 | #define incr_top(L) \ 12 | (++L->top >= tvref(L->maxstack) && (lj_state_growstack1(L), 0)) 13 | 14 | #define savestack(L, p) ((char *)(p) - mref(L->stack, char)) 15 | #define restorestack(L, n) ((TValue *)(mref(L->stack, char) + (n))) 16 | 17 | LJ_FUNC void lj_state_relimitstack(lua_State *L); 18 | LJ_FUNC void lj_state_shrinkstack(lua_State *L, MSize used); 19 | LJ_FUNCA void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need); 20 | LJ_FUNC void LJ_FASTCALL lj_state_growstack1(lua_State *L); 21 | LJ_FUNC int LJ_FASTCALL lj_state_cpgrowstack(lua_State *L, MSize need); 22 | 23 | static LJ_AINLINE void lj_state_checkstack(lua_State *L, MSize need) 24 | { 25 | if ((mref(L->maxstack, char) - (char *)L->top) <= 26 | (ptrdiff_t)need*(ptrdiff_t)sizeof(TValue)) 27 | lj_state_growstack(L, need); 28 | } 29 | 30 | LJ_FUNC lua_State *lj_state_new(lua_State *L); 31 | LJ_FUNC void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L); 32 | #if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) 33 | LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud); 34 | #endif 35 | 36 | #define LJ_ALLOCF_INTERNAL ((lua_Alloc)(void *)(uintptr_t)(1237<<4)) 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/lj_str.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** String handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_STR_H 7 | #define _LJ_STR_H 8 | 9 | #include 10 | 11 | #include "lj_obj.h" 12 | 13 | /* String helpers. */ 14 | LJ_FUNC int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b); 15 | LJ_FUNC const char *lj_str_find(const char *s, const char *f, 16 | MSize slen, MSize flen); 17 | LJ_FUNC int lj_str_haspattern(GCstr *s); 18 | 19 | /* String interning. */ 20 | LJ_FUNC void lj_str_resize(lua_State *L, MSize newmask); 21 | LJ_FUNCA GCstr *lj_str_new(lua_State *L, const char *str, size_t len); 22 | LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s); 23 | LJ_FUNC void LJ_FASTCALL lj_str_init(lua_State *L); 24 | #define lj_str_freetab(g) \ 25 | (lj_mem_freevec(g, g->str.tab, g->str.mask+1, GCRef)) 26 | 27 | #define lj_str_newz(L, s) (lj_str_new(L, s, strlen(s))) 28 | #define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1)) 29 | #define lj_str_size(len) (sizeof(GCstr) + (((len)+4) & ~(MSize)3)) 30 | 31 | #ifdef LJ_HAS_OPTIMISED_HASH 32 | typedef StrHash (*str_sparse_hashfn) (uint64_t, const char *, MSize); 33 | extern str_sparse_hashfn hash_sparse; 34 | 35 | #if LUAJIT_SECURITY_STRHASH 36 | typedef StrHash (*str_dense_hashfn) (uint64_t, StrHash, const char *, MSize); 37 | extern str_dense_hashfn hash_dense; 38 | #endif 39 | 40 | extern void str_hash_init_sse42 (void); 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/lj_strfmt.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** String formatting. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_STRFMT_H 7 | #define _LJ_STRFMT_H 8 | 9 | #include "lj_obj.h" 10 | 11 | typedef uint32_t SFormat; /* Format indicator. */ 12 | 13 | /* Format parser state. */ 14 | typedef struct FormatState { 15 | const uint8_t *p; /* Current format string pointer. */ 16 | const uint8_t *e; /* End of format string. */ 17 | const char *str; /* Returned literal string. */ 18 | MSize len; /* Size of literal string. */ 19 | } FormatState; 20 | 21 | /* Format types (max. 16). */ 22 | typedef enum FormatType { 23 | STRFMT_EOF, STRFMT_ERR, STRFMT_LIT, 24 | STRFMT_INT, STRFMT_UINT, STRFMT_NUM, STRFMT_STR, STRFMT_CHAR, STRFMT_PTR 25 | } FormatType; 26 | 27 | /* Format subtypes (bits are reused). */ 28 | #define STRFMT_T_HEX 0x0010 /* STRFMT_UINT */ 29 | #define STRFMT_T_OCT 0x0020 /* STRFMT_UINT */ 30 | #define STRFMT_T_FP_A 0x0000 /* STRFMT_NUM */ 31 | #define STRFMT_T_FP_E 0x0010 /* STRFMT_NUM */ 32 | #define STRFMT_T_FP_F 0x0020 /* STRFMT_NUM */ 33 | #define STRFMT_T_FP_G 0x0030 /* STRFMT_NUM */ 34 | #define STRFMT_T_QUOTED 0x0010 /* STRFMT_STR */ 35 | 36 | /* Format flags. */ 37 | #define STRFMT_F_LEFT 0x0100 38 | #define STRFMT_F_PLUS 0x0200 39 | #define STRFMT_F_ZERO 0x0400 40 | #define STRFMT_F_SPACE 0x0800 41 | #define STRFMT_F_ALT 0x1000 42 | #define STRFMT_F_UPPER 0x2000 43 | 44 | /* Format indicator fields. */ 45 | #define STRFMT_SH_WIDTH 16 46 | #define STRFMT_SH_PREC 24 47 | 48 | #define STRFMT_TYPE(sf) ((FormatType)((sf) & 15)) 49 | #define STRFMT_WIDTH(sf) (((sf) >> STRFMT_SH_WIDTH) & 255u) 50 | #define STRFMT_PREC(sf) ((((sf) >> STRFMT_SH_PREC) & 255u) - 1u) 51 | #define STRFMT_FP(sf) (((sf) >> 4) & 3) 52 | 53 | /* Formats for conversion characters. */ 54 | #define STRFMT_A (STRFMT_NUM|STRFMT_T_FP_A) 55 | #define STRFMT_C (STRFMT_CHAR) 56 | #define STRFMT_D (STRFMT_INT) 57 | #define STRFMT_E (STRFMT_NUM|STRFMT_T_FP_E) 58 | #define STRFMT_F (STRFMT_NUM|STRFMT_T_FP_F) 59 | #define STRFMT_G (STRFMT_NUM|STRFMT_T_FP_G) 60 | #define STRFMT_I STRFMT_D 61 | #define STRFMT_O (STRFMT_UINT|STRFMT_T_OCT) 62 | #define STRFMT_P (STRFMT_PTR) 63 | #define STRFMT_Q (STRFMT_STR|STRFMT_T_QUOTED) 64 | #define STRFMT_S (STRFMT_STR) 65 | #define STRFMT_U (STRFMT_UINT) 66 | #define STRFMT_X (STRFMT_UINT|STRFMT_T_HEX) 67 | #define STRFMT_G14 (STRFMT_G | ((14+1) << STRFMT_SH_PREC)) 68 | 69 | /* Maximum buffer sizes for conversions. */ 70 | #define STRFMT_MAXBUF_XINT (1+22) /* '0' prefix + uint64_t in octal. */ 71 | #define STRFMT_MAXBUF_INT (1+10) /* Sign + int32_t in decimal. */ 72 | #define STRFMT_MAXBUF_NUM 32 /* Must correspond with STRFMT_G14. */ 73 | #define STRFMT_MAXBUF_PTR (2+2*sizeof(ptrdiff_t)) /* "0x" + hex ptr. */ 74 | 75 | /* Format parser. */ 76 | LJ_FUNC SFormat LJ_FASTCALL lj_strfmt_parse(FormatState *fs); 77 | 78 | static LJ_AINLINE void lj_strfmt_init(FormatState *fs, const char *p, MSize len) 79 | { 80 | fs->p = (const uint8_t *)p; 81 | fs->e = (const uint8_t *)p + len; 82 | /* Must be NUL-terminated. May have NULs inside, too. */ 83 | lj_assertX(*fs->e == 0, "format not NUL-terminated"); 84 | } 85 | 86 | /* Raw conversions. */ 87 | LJ_FUNC char * LJ_FASTCALL lj_strfmt_wint(char *p, int32_t k); 88 | LJ_FUNC char * LJ_FASTCALL lj_strfmt_wptr(char *p, const void *v); 89 | LJ_FUNC char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v); 90 | LJ_FUNC const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp); 91 | 92 | /* Unformatted conversions to buffer. */ 93 | LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k); 94 | #if LJ_HASJIT 95 | LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o); 96 | #endif 97 | LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putptr(SBuf *sb, const void *v); 98 | #if LJ_HASJIT 99 | LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str); 100 | #endif 101 | 102 | /* Formatted conversions to buffer. */ 103 | LJ_FUNC SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k); 104 | LJ_FUNC SBuf *lj_strfmt_putfnum_int(SBuf *sb, SFormat sf, lua_Number n); 105 | LJ_FUNC SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n); 106 | LJ_FUNC SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat, lua_Number n); 107 | LJ_FUNC SBuf *lj_strfmt_putfchar(SBuf *sb, SFormat, int32_t c); 108 | #if LJ_HASJIT 109 | LJ_FUNC SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat, GCstr *str); 110 | #endif 111 | LJ_FUNC int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry); 112 | 113 | /* Conversions to strings. */ 114 | LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_int(lua_State *L, int32_t k); 115 | LJ_FUNCA GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o); 116 | LJ_FUNCA GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o); 117 | #if LJ_HASJIT 118 | LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_char(lua_State *L, int c); 119 | #endif 120 | LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_obj(lua_State *L, cTValue *o); 121 | 122 | /* Internal string formatting. */ 123 | LJ_FUNC const char *lj_strfmt_pushvf(lua_State *L, const char *fmt, 124 | va_list argp); 125 | LJ_FUNC const char *lj_strfmt_pushf(lua_State *L, const char *fmt, ...) 126 | #if defined(__GNUC__) || defined(__clang__) 127 | __attribute__ ((format (printf, 2, 3))) 128 | #endif 129 | ; 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/lj_strscan.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** String scanning. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_STRSCAN_H 7 | #define _LJ_STRSCAN_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Options for accepted/returned formats. */ 12 | #define STRSCAN_OPT_TOINT 0x01 /* Convert to int32_t, if possible. */ 13 | #define STRSCAN_OPT_TONUM 0x02 /* Always convert to double. */ 14 | #define STRSCAN_OPT_IMAG 0x04 15 | #define STRSCAN_OPT_LL 0x08 16 | #define STRSCAN_OPT_C 0x10 17 | 18 | /* Returned format. */ 19 | typedef enum { 20 | STRSCAN_ERROR, 21 | STRSCAN_NUM, STRSCAN_IMAG, 22 | STRSCAN_INT, STRSCAN_U32, STRSCAN_I64, STRSCAN_U64, 23 | } StrScanFmt; 24 | 25 | LJ_FUNC StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o, 26 | uint32_t opt); 27 | LJ_FUNC int LJ_FASTCALL lj_strscan_num(GCstr *str, TValue *o); 28 | #if LJ_DUALNUM 29 | LJ_FUNC int LJ_FASTCALL lj_strscan_number(GCstr *str, TValue *o); 30 | #else 31 | #define lj_strscan_number(s, o) lj_strscan_num((s), (o)) 32 | #endif 33 | 34 | /* Check for number or convert string to number/int in-place (!). */ 35 | static LJ_AINLINE int lj_strscan_numberobj(TValue *o) 36 | { 37 | return tvisnumber(o) || (tvisstr(o) && lj_strscan_number(strV(o), o)); 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/lj_tab.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Table handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_TAB_H 7 | #define _LJ_TAB_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Hash constants. Tuned using a brute force search. */ 12 | #define HASH_BIAS (-0x04c11db7) 13 | #define HASH_ROT1 14 14 | #define HASH_ROT2 5 15 | #define HASH_ROT3 13 16 | 17 | /* Scramble the bits of numbers and pointers. */ 18 | static LJ_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi) 19 | { 20 | #if LJ_TARGET_X86ORX64 21 | /* Prefer variant that compiles well for a 2-operand CPU. */ 22 | lo ^= hi; hi = lj_rol(hi, HASH_ROT1); 23 | lo -= hi; hi = lj_rol(hi, HASH_ROT2); 24 | hi ^= lo; hi -= lj_rol(lo, HASH_ROT3); 25 | #else 26 | lo ^= hi; 27 | lo = lo - lj_rol(hi, HASH_ROT1); 28 | hi = lo ^ lj_rol(hi, HASH_ROT1 + HASH_ROT2); 29 | hi = hi - lj_rol(lo, HASH_ROT3); 30 | #endif 31 | return hi; 32 | } 33 | 34 | /* Hash values are masked with the table hash mask and used as an index. */ 35 | static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash) 36 | { 37 | Node *n = noderef(t->node); 38 | return &n[hash & t->hmask]; 39 | } 40 | 41 | /* String IDs are generated when a string is interned. */ 42 | #define hashstr(t, s) hashmask(t, (s)->sid) 43 | 44 | #define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi))) 45 | #define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1)) 46 | #if LJ_GC64 47 | #define hashgcref(t, r) \ 48 | hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32)) 49 | #else 50 | #define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS) 51 | #endif 52 | 53 | #define hsize2hbits(s) ((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0) 54 | 55 | LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits); 56 | LJ_FUNC GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h); 57 | #if LJ_HASJIT 58 | LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize); 59 | #endif 60 | LJ_FUNCA GCtab * lj_tab_dup_helper(lua_State *L, const GCtab *kt, int is_tab_clone); 61 | LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt); 62 | LJ_FUNC void LJ_FASTCALL lj_tab_clear(GCtab *t); 63 | LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t); 64 | LJ_FUNC void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits); 65 | LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize); 66 | 67 | /* Caveat: all getters except lj_tab_get() can return NULL! */ 68 | 69 | LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key); 70 | LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, const GCstr *key); 71 | LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key); 72 | 73 | /* Caveat: all setters require a write barrier for the stored value. */ 74 | 75 | LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); 76 | LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); 77 | LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key); 78 | LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); 79 | 80 | #define inarray(t, key) ((MSize)(key) < (MSize)(t)->asize) 81 | #define arrayslot(t, i) (&tvref((t)->array)[(i)]) 82 | #define lj_tab_getint(t, key) \ 83 | (inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_getinth((t), (key))) 84 | #define lj_tab_setint(L, t, key) \ 85 | (inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_setinth(L, (t), (key))) 86 | 87 | LJ_FUNC uint32_t LJ_FASTCALL lj_tab_keyindex(GCtab *t, cTValue *key); 88 | LJ_FUNCA int lj_tab_next(GCtab *t, cTValue *key, TValue *o); 89 | LJ_FUNCA MSize LJ_FASTCALL lj_tab_len(GCtab *t); 90 | #if LJ_HASJIT 91 | LJ_FUNC MSize LJ_FASTCALL lj_tab_len_hint(GCtab *t, size_t hint); 92 | #endif 93 | 94 | LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_clone(lua_State *L, const GCtab *src); 95 | LJ_FUNCA int LJ_FASTCALL lj_tab_isarray(const GCtab *src); 96 | LJ_FUNCA MSize LJ_FASTCALL lj_tab_nkeys(const GCtab *src); 97 | LJ_FUNCA int LJ_FASTCALL lj_tab_isempty(const GCtab *t); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/lj_target_s390x.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Definitions for IBM z/Architecture (s390x) CPUs. 3 | ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_TARGET_S390X_H 7 | #define _LJ_TARGET_S390X_H 8 | 9 | /* -- Registers IDs ------------------------------------------------------- */ 10 | 11 | #define GPRDEF(_) \ 12 | _(R0) _(R1) _(R2) _(R3) _(R4) _(R5) _(R6) _(R7) \ 13 | _(R8) _(R9) _(R10) _(R11) _(R12) _(R13) _(R14) _(R15) 14 | #define FPRDEF(_) \ 15 | _(F0) _(F1) _(F2) _(F3) \ 16 | _(F4) _(F5) _(F6) _(F7) \ 17 | _(F8) _(F9) _(F10) _(F11) \ 18 | _(F12) _(F13) _(F14) _(F15) 19 | // TODO: VREG? 20 | 21 | #define RIDENUM(name) RID_##name, 22 | 23 | enum { 24 | GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */ 25 | FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */ 26 | RID_MAX, 27 | 28 | /* Calling conventions. */ 29 | RID_SP = RID_R15, 30 | RID_RET = RID_R2, 31 | RID_FPRET = RID_F0, 32 | 33 | /* These definitions must match with the *.dasc file(s): */ 34 | RID_BASE = RID_R7, /* Interpreter BASE. */ 35 | RID_LPC = RID_R9, /* Interpreter PC. */ 36 | RID_DISPATCH = RID_R10, /* Interpreter DISPATCH table. */ 37 | 38 | /* Register ranges [min, max) and number of registers. */ 39 | RID_MIN_GPR = RID_R0, 40 | RID_MIN_FPR = RID_F0, 41 | RID_MAX_GPR = RID_MIN_FPR, 42 | RID_MAX_FPR = RID_MAX, 43 | RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR, 44 | RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR, 45 | }; 46 | 47 | /* -- Register sets ------------------------------------------------------- */ 48 | 49 | /* -- Spill slots --------------------------------------------------------- */ 50 | 51 | /* Spill slots are 32 bit wide. An even/odd pair is used for FPRs. 52 | ** 53 | ** SPS_FIXED: Available fixed spill slots in interpreter frame. 54 | ** This definition must match with the *.dasc file(s). 55 | ** 56 | ** SPS_FIRST: First spill slot for general use. Reserve min. two 32 bit slots. 57 | */ 58 | #define SPS_FIXED 2 59 | #define SPS_FIRST 2 60 | 61 | #define SPOFS_TMP 0 62 | 63 | #define sps_scale(slot) (4 * (int32_t)(slot)) 64 | #define sps_align(slot) (((slot) - SPS_FIXED + 1) & ~1) 65 | 66 | /* -- Exit state ---------------------------------------------------------- */ 67 | 68 | /* This definition must match with the *.dasc file(s). */ 69 | typedef struct { 70 | lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */ 71 | int32_t gpr[RID_NUM_GPR]; /* General-purpose registers. */ 72 | int32_t spill[256]; /* Spill slots. */ 73 | } ExitState; 74 | 75 | #define EXITSTUB_SPACING 4 76 | #define EXITSTUBS_PER_GROUP 32 77 | 78 | /* -- Instructions -------------------------------------------------------- */ 79 | 80 | #endif 81 | 82 | -------------------------------------------------------------------------------- /src/lj_trace.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Trace management. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_TRACE_H 7 | #define _LJ_TRACE_H 8 | 9 | #include "lj_obj.h" 10 | 11 | #if LJ_HASJIT 12 | #include "lj_jit.h" 13 | #include "lj_dispatch.h" 14 | 15 | /* Trace errors. */ 16 | typedef enum { 17 | #define TREDEF(name, msg) LJ_TRERR_##name, 18 | #include "lj_traceerr.h" 19 | LJ_TRERR__MAX 20 | } TraceError; 21 | 22 | LJ_FUNC_NORET void lj_trace_err(jit_State *J, TraceError e); 23 | LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e); 24 | 25 | /* Trace management. */ 26 | LJ_FUNC GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T); 27 | LJ_FUNC void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T); 28 | LJ_FUNC void lj_trace_reenableproto(GCproto *pt); 29 | LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt); 30 | LJ_FUNC void lj_trace_flush(jit_State *J, TraceNo traceno); 31 | LJ_FUNC int lj_trace_flushall(lua_State *L); 32 | LJ_FUNC void lj_trace_initstate(global_State *g); 33 | LJ_FUNC void lj_trace_freestate(global_State *g); 34 | 35 | /* Event handling. */ 36 | LJ_FUNC void lj_trace_ins(jit_State *J, const BCIns *pc); 37 | LJ_FUNCA void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc); 38 | LJ_FUNCA void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc); 39 | LJ_FUNCA int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr); 40 | #if LJ_UNWIND_EXT 41 | LJ_FUNC uintptr_t LJ_FASTCALL lj_trace_unwind(jit_State *J, uintptr_t addr, ExitNo *ep); 42 | #endif 43 | 44 | /* Signal asynchronous abort of trace or end of trace. */ 45 | #define lj_trace_abort(g) (G2J(g)->state &= ~LJ_TRACE_ACTIVE) 46 | #define lj_trace_end(J) (J->state = LJ_TRACE_END) 47 | 48 | #else 49 | 50 | #define lj_trace_flushall(L) (UNUSED(L), 0) 51 | #define lj_trace_initstate(g) UNUSED(g) 52 | #define lj_trace_freestate(g) UNUSED(g) 53 | #define lj_trace_abort(g) UNUSED(g) 54 | #define lj_trace_end(J) UNUSED(J) 55 | 56 | #endif 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/lj_traceerr.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Trace compiler error messages. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | /* This file may be included multiple times with different TREDEF macros. */ 7 | 8 | /* Recording. */ 9 | TREDEF(RECERR, "error thrown or hook called during recording") 10 | TREDEF(TRACEUV, "trace too short") 11 | TREDEF(TRACEOV, "trace too long") 12 | TREDEF(STACKOV, "trace too deep") 13 | TREDEF(SNAPOV, "too many snapshots") 14 | TREDEF(BLACKL, "blacklisted") 15 | TREDEF(RETRY, "retry recording") 16 | TREDEF(NYIBC, "NYI: bytecode %s") 17 | 18 | /* Recording loop ops. */ 19 | TREDEF(LLEAVE, "leaving loop in root trace") 20 | TREDEF(LINNER, "inner loop in root trace") 21 | TREDEF(LUNROLL, "loop unroll limit reached") 22 | 23 | /* Recording calls/returns. */ 24 | TREDEF(BADTYPE, "bad argument type") 25 | TREDEF(CJITOFF, "JIT compilation disabled for function") 26 | TREDEF(CUNROLL, "call unroll limit reached") 27 | TREDEF(DOWNREC, "down-recursion, restarting") 28 | TREDEF(NYIFFU, "NYI: unsupported variant of FastFunc %s") 29 | TREDEF(NYIRETL, "NYI: return to lower frame") 30 | 31 | /* Recording indexed load/store. */ 32 | TREDEF(STORENN, "store with nil or NaN key") 33 | TREDEF(NOMM, "missing metamethod") 34 | TREDEF(IDXLOOP, "looping index lookup") 35 | TREDEF(NYITMIX, "NYI: mixed sparse/dense table") 36 | 37 | /* Recording C data operations. */ 38 | TREDEF(NOCACHE, "symbol not in cache") 39 | TREDEF(NYICONV, "NYI: unsupported C type conversion") 40 | TREDEF(NYICALL, "NYI: unsupported C function type") 41 | 42 | /* Optimizations. */ 43 | TREDEF(GFAIL, "guard would always fail") 44 | TREDEF(PHIOV, "too many PHIs") 45 | TREDEF(TYPEINS, "persistent type instability") 46 | 47 | /* Assembler. */ 48 | TREDEF(MCODEAL, "failed to allocate mcode memory") 49 | TREDEF(MCODEOV, "machine code too long") 50 | TREDEF(MCODELM, "hit mcode limit (retrying)") 51 | TREDEF(SPILLOV, "too many spill slots") 52 | TREDEF(BADRA, "inconsistent register allocation") 53 | TREDEF(NYIIR, "NYI: cannot assemble IR instruction %d") 54 | TREDEF(NYIPHI, "NYI: PHI shuffling too complex") 55 | TREDEF(NYICOAL, "NYI: register coalescing too complex") 56 | 57 | #undef TREDEF 58 | 59 | /* Detecting unused error messages: 60 | awk -F, '/^TREDEF/ { gsub(/TREDEF./, ""); printf "grep -q LJ_TRERR_%s *.[ch] || echo %s\n", $1, $1}' lj_traceerr.h | sh 61 | */ 62 | -------------------------------------------------------------------------------- /src/lj_udata.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Userdata handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lj_udata_c 7 | #define LUA_CORE 8 | 9 | #include "lj_obj.h" 10 | #include "lj_gc.h" 11 | #include "lj_err.h" 12 | #include "lj_udata.h" 13 | 14 | GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env) 15 | { 16 | GCudata *ud = lj_mem_newt(L, sizeof(GCudata) + sz, GCudata); 17 | global_State *g = G(L); 18 | newwhite(g, ud); /* Not finalized. */ 19 | ud->gct = ~LJ_TUDATA; 20 | ud->udtype = UDTYPE_USERDATA; 21 | ud->len = sz; 22 | /* NOBARRIER: The GCudata is new (marked white). */ 23 | setgcrefnull(ud->metatable); 24 | setgcref(ud->env, obj2gco(env)); 25 | /* Chain to userdata list (after main thread). */ 26 | setgcrefr(ud->nextgc, mainthread(g)->nextgc); 27 | setgcref(mainthread(g)->nextgc, obj2gco(ud)); 28 | return ud; 29 | } 30 | 31 | void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud) 32 | { 33 | lj_mem_free(g, ud, sizeudata(ud)); 34 | } 35 | 36 | #if LJ_64 37 | void *lj_lightud_intern(lua_State *L, void *p) 38 | { 39 | global_State *g = G(L); 40 | uint64_t u = (uint64_t)p; 41 | uint32_t up = lightudup(u); 42 | uint32_t *segmap = mref(g->gc.lightudseg, uint32_t); 43 | MSize segnum = g->gc.lightudnum; 44 | if (segmap) { 45 | MSize seg; 46 | for (seg = 0; seg <= segnum; seg++) 47 | if (segmap[seg] == up) /* Fast path. */ 48 | return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); 49 | segnum++; 50 | /* Leave last segment unused to avoid clash with ITERN key. */ 51 | if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)-1) lj_err_msg(L, LJ_ERR_BADLU); 52 | } 53 | if (!((segnum-1) & segnum) && segnum != 1) { 54 | lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t); 55 | setmref(g->gc.lightudseg, segmap); 56 | } 57 | g->gc.lightudnum = segnum; 58 | segmap[segnum] = up; 59 | return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); 60 | } 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /src/lj_udata.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Userdata handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_UDATA_H 7 | #define _LJ_UDATA_H 8 | 9 | #include "lj_obj.h" 10 | 11 | LJ_FUNC GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env); 12 | LJ_FUNC void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud); 13 | #if LJ_64 14 | LJ_FUNC void * LJ_FASTCALL lj_lightud_intern(lua_State *L, void *p); 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/lj_vm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Assembler VM interface definitions. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_VM_H 7 | #define _LJ_VM_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Entry points for ASM parts of VM. */ 12 | LJ_ASMF void lj_vm_call(lua_State *L, TValue *base, int nres1); 13 | LJ_ASMF int lj_vm_pcall(lua_State *L, TValue *base, int nres1, ptrdiff_t ef); 14 | typedef TValue *(*lua_CPFunction)(lua_State *L, lua_CFunction func, void *ud); 15 | LJ_ASMF int lj_vm_cpcall(lua_State *L, lua_CFunction func, void *ud, 16 | lua_CPFunction cp); 17 | LJ_ASMF int lj_vm_resume(lua_State *L, TValue *base, int nres1, ptrdiff_t ef); 18 | LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_c(void *cframe, int errcode); 19 | LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_ff(void *cframe); 20 | #if LJ_ABI_WIN && LJ_TARGET_X86 21 | LJ_ASMF_NORET void LJ_FASTCALL lj_vm_rtlunwind(void *cframe, void *excptrec, 22 | void *unwinder, int errcode); 23 | #endif 24 | LJ_ASMF void lj_vm_unwind_c_eh(void); 25 | LJ_ASMF void lj_vm_unwind_ff_eh(void); 26 | #if LJ_TARGET_X86ORX64 27 | LJ_ASMF void lj_vm_unwind_rethrow(void); 28 | #endif 29 | #if LJ_TARGET_MIPS 30 | LJ_ASMF void lj_vm_unwind_stub(void); 31 | #endif 32 | 33 | /* Miscellaneous functions. */ 34 | #if LJ_TARGET_X86ORX64 35 | LJ_ASMF int lj_vm_cpuid(uint32_t f, uint32_t res[4]); 36 | #endif 37 | #if LJ_TARGET_PPC 38 | void lj_vm_cachesync(void *start, void *end); 39 | #endif 40 | LJ_ASMF double lj_vm_foldarith(double x, double y, int op); 41 | #if LJ_HASJIT 42 | LJ_ASMF double lj_vm_foldfpm(double x, int op); 43 | #endif 44 | #if !LJ_ARCH_HASFPU 45 | /* Declared in lj_obj.h: LJ_ASMF int32_t lj_vm_tobit(double x); */ 46 | #endif 47 | 48 | /* Dispatch targets for recording and hooks. */ 49 | LJ_ASMF void lj_vm_record(void); 50 | LJ_ASMF void lj_vm_inshook(void); 51 | LJ_ASMF void lj_vm_rethook(void); 52 | LJ_ASMF void lj_vm_callhook(void); 53 | LJ_ASMF void lj_vm_profhook(void); 54 | LJ_ASMF void lj_vm_IITERN(void); 55 | 56 | /* Trace exit handling. */ 57 | LJ_ASMF char lj_vm_exit_handler[]; 58 | LJ_ASMF char lj_vm_exit_interp[]; 59 | 60 | /* Internal math helper functions. */ 61 | #if LJ_TARGET_PPC || LJ_TARGET_ARM64 || (LJ_TARGET_MIPS && LJ_ABI_SOFTFP) 62 | #define lj_vm_floor floor 63 | #define lj_vm_ceil ceil 64 | #else 65 | LJ_ASMF double lj_vm_floor(double); 66 | LJ_ASMF double lj_vm_ceil(double); 67 | #if LJ_TARGET_ARM 68 | LJ_ASMF double lj_vm_floor_sf(double); 69 | LJ_ASMF double lj_vm_ceil_sf(double); 70 | #endif 71 | #endif 72 | #ifdef LUAJIT_NO_LOG2 73 | LJ_ASMF double lj_vm_log2(double); 74 | #else 75 | #define lj_vm_log2 log2 76 | #endif 77 | #if !(defined(_LJ_DISPATCH_H) && LJ_TARGET_MIPS) 78 | LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t, int32_t); 79 | #endif 80 | 81 | #if LJ_HASJIT 82 | #if LJ_TARGET_X86ORX64 83 | LJ_ASMF void lj_vm_floor_sse(void); 84 | LJ_ASMF void lj_vm_ceil_sse(void); 85 | LJ_ASMF void lj_vm_trunc_sse(void); 86 | #endif 87 | #if LJ_TARGET_PPC || LJ_TARGET_ARM64 88 | #define lj_vm_trunc trunc 89 | #else 90 | LJ_ASMF double lj_vm_trunc(double); 91 | #if LJ_TARGET_ARM 92 | LJ_ASMF double lj_vm_trunc_sf(double); 93 | #endif 94 | #endif 95 | #if LJ_HASFFI 96 | LJ_ASMF int lj_vm_errno(void); 97 | #endif 98 | LJ_ASMF TValue *lj_vm_next(GCtab *t, uint32_t idx); 99 | #endif 100 | 101 | /* Continuations for metamethods. */ 102 | LJ_ASMF void lj_cont_cat(void); /* Continue with concatenation. */ 103 | LJ_ASMF void lj_cont_ra(void); /* Store result in RA from instruction. */ 104 | LJ_ASMF void lj_cont_nop(void); /* Do nothing, just continue execution. */ 105 | LJ_ASMF void lj_cont_condt(void); /* Branch if result is true. */ 106 | LJ_ASMF void lj_cont_condf(void); /* Branch if result is false. */ 107 | LJ_ASMF void lj_cont_hook(void); /* Continue from hook yield. */ 108 | LJ_ASMF void lj_cont_stitch(void); /* Trace stitching. */ 109 | 110 | /* Start of the ASM code. */ 111 | LJ_ASMF char lj_vm_asm_begin[]; 112 | 113 | /* Bytecode offsets are relative to lj_vm_asm_begin. */ 114 | #define makeasmfunc(ofs) lj_ptr_sign((ASMFunction)(lj_vm_asm_begin + (ofs)), 0) 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /src/lj_vmevent.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** VM event handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #include 7 | 8 | #define lj_vmevent_c 9 | #define LUA_CORE 10 | 11 | #include "lj_obj.h" 12 | #include "lj_str.h" 13 | #include "lj_tab.h" 14 | #include "lj_state.h" 15 | #include "lj_dispatch.h" 16 | #include "lj_vm.h" 17 | #include "lj_vmevent.h" 18 | 19 | ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev) 20 | { 21 | global_State *g = G(L); 22 | GCstr *s = lj_str_newlit(L, LJ_VMEVENTS_REGKEY); 23 | cTValue *tv = lj_tab_getstr(tabV(registry(L)), s); 24 | if (tvistab(tv)) { 25 | int hash = VMEVENT_HASH(ev); 26 | tv = lj_tab_getint(tabV(tv), hash); 27 | if (tv && tvisfunc(tv)) { 28 | lj_state_checkstack(L, LUA_MINSTACK); 29 | setfuncV(L, L->top++, funcV(tv)); 30 | if (LJ_FR2) setnilV(L->top++); 31 | return savestack(L, L->top); 32 | } 33 | } 34 | g->vmevmask &= ~VMEVENT_MASK(ev); /* No handler: cache this fact. */ 35 | return 0; 36 | } 37 | 38 | void lj_vmevent_call(lua_State *L, ptrdiff_t argbase) 39 | { 40 | global_State *g = G(L); 41 | uint8_t oldmask = g->vmevmask; 42 | uint8_t oldh = hook_save(g); 43 | int status; 44 | g->vmevmask = 0; /* Disable all events. */ 45 | hook_vmevent(g); 46 | status = lj_vm_pcall(L, restorestack(L, argbase), 0+1, 0); 47 | if (LJ_UNLIKELY(status)) { 48 | /* Really shouldn't use stderr here, but where else to complain? */ 49 | L->top--; 50 | fputs("VM handler failed: ", stderr); 51 | fputs(tvisstr(L->top) ? strVdata(L->top) : "?", stderr); 52 | fputc('\n', stderr); 53 | } 54 | hook_restore(g, oldh); 55 | if (g->vmevmask != VMEVENT_NOCACHE) 56 | g->vmevmask = oldmask; /* Restore event mask, but not if not modified. */ 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/lj_vmevent.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** VM event handling. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LJ_VMEVENT_H 7 | #define _LJ_VMEVENT_H 8 | 9 | #include "lj_obj.h" 10 | 11 | /* Registry key for VM event handler table. */ 12 | #define LJ_VMEVENTS_REGKEY "_VMEVENTS" 13 | #define LJ_VMEVENTS_HSIZE 4 14 | 15 | #define VMEVENT_MASK(ev) ((uint8_t)1 << ((int)(ev) & 7)) 16 | #define VMEVENT_HASH(ev) ((int)(ev) & ~7) 17 | #define VMEVENT_HASHIDX(h) ((int)(h) << 3) 18 | #define VMEVENT_NOCACHE 255 19 | 20 | #define VMEVENT_DEF(name, hash) \ 21 | LJ_VMEVENT_##name##_, \ 22 | LJ_VMEVENT_##name = ((LJ_VMEVENT_##name##_) & 7)|((hash) << 3) 23 | 24 | /* VM event IDs. */ 25 | typedef enum { 26 | VMEVENT_DEF(BC, 0x00003883), 27 | VMEVENT_DEF(TRACE, 0x12d91467), 28 | VMEVENT_DEF(RECORD, 0x1284bf4f), 29 | VMEVENT_DEF(TEXIT, 0x129df2b0), 30 | VMEVENT_DEF(ERRFIN, 0x12d93888), 31 | LJ_VMEVENT__MAX 32 | } VMEvent; 33 | 34 | #ifdef LUAJIT_DISABLE_VMEVENT 35 | #define lj_vmevent_send(L, ev, args) UNUSED(L) 36 | #define lj_vmevent_send_(L, ev, args, post) UNUSED(L) 37 | #else 38 | #define lj_vmevent_send(L, ev, args) \ 39 | if (G(L)->vmevmask & VMEVENT_MASK(LJ_VMEVENT_##ev)) { \ 40 | ptrdiff_t argbase = lj_vmevent_prepare(L, LJ_VMEVENT_##ev); \ 41 | if (argbase) { \ 42 | args \ 43 | lj_vmevent_call(L, argbase); \ 44 | } \ 45 | } 46 | #define lj_vmevent_send_(L, ev, args, post) \ 47 | if (G(L)->vmevmask & VMEVENT_MASK(LJ_VMEVENT_##ev)) { \ 48 | ptrdiff_t argbase = lj_vmevent_prepare(L, LJ_VMEVENT_##ev); \ 49 | if (argbase) { \ 50 | args \ 51 | lj_vmevent_call(L, argbase); \ 52 | post \ 53 | } \ 54 | } 55 | 56 | LJ_FUNC ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev); 57 | LJ_FUNC void lj_vmevent_call(lua_State *L, ptrdiff_t argbase); 58 | #endif 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/lj_vmmath.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Math helper functions for assembler VM. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define lj_vmmath_c 7 | #define LUA_CORE 8 | 9 | #include 10 | #include 11 | 12 | #include "lj_obj.h" 13 | #include "lj_ir.h" 14 | #include "lj_vm.h" 15 | 16 | /* -- Wrapper functions --------------------------------------------------- */ 17 | 18 | #if LJ_TARGET_X86 && __ELF__ && __PIC__ 19 | /* Wrapper functions to deal with the ELF/x86 PIC disaster. */ 20 | LJ_FUNCA double lj_wrap_log(double x) { return log(x); } 21 | LJ_FUNCA double lj_wrap_log10(double x) { return log10(x); } 22 | LJ_FUNCA double lj_wrap_exp(double x) { return exp(x); } 23 | LJ_FUNCA double lj_wrap_sin(double x) { return sin(x); } 24 | LJ_FUNCA double lj_wrap_cos(double x) { return cos(x); } 25 | LJ_FUNCA double lj_wrap_tan(double x) { return tan(x); } 26 | LJ_FUNCA double lj_wrap_asin(double x) { return asin(x); } 27 | LJ_FUNCA double lj_wrap_acos(double x) { return acos(x); } 28 | LJ_FUNCA double lj_wrap_atan(double x) { return atan(x); } 29 | LJ_FUNCA double lj_wrap_sinh(double x) { return sinh(x); } 30 | LJ_FUNCA double lj_wrap_cosh(double x) { return cosh(x); } 31 | LJ_FUNCA double lj_wrap_tanh(double x) { return tanh(x); } 32 | LJ_FUNCA double lj_wrap_atan2(double x, double y) { return atan2(x, y); } 33 | LJ_FUNCA double lj_wrap_pow(double x, double y) { return pow(x, y); } 34 | LJ_FUNCA double lj_wrap_fmod(double x, double y) { return fmod(x, y); } 35 | #endif 36 | 37 | /* -- Helper functions ---------------------------------------------------- */ 38 | 39 | /* Required to prevent the C compiler from applying FMA optimizations. 40 | ** 41 | ** Yes, there's -ffp-contract and the FP_CONTRACT pragma ... in theory. 42 | ** But the current state of C compilers is a mess in this regard. 43 | ** Also, this function is not performance sensitive at all. 44 | */ 45 | LJ_NOINLINE static double lj_vm_floormul(double x, double y) 46 | { 47 | return lj_vm_floor(x / y) * y; 48 | } 49 | 50 | double lj_vm_foldarith(double x, double y, int op) 51 | { 52 | switch (op) { 53 | case IR_ADD - IR_ADD: return x+y; break; 54 | case IR_SUB - IR_ADD: return x-y; break; 55 | case IR_MUL - IR_ADD: return x*y; break; 56 | case IR_DIV - IR_ADD: return x/y; break; 57 | case IR_MOD - IR_ADD: return x-lj_vm_floormul(x, y); break; 58 | case IR_POW - IR_ADD: return pow(x, y); break; 59 | case IR_NEG - IR_ADD: return -x; break; 60 | case IR_ABS - IR_ADD: return fabs(x); break; 61 | #if LJ_HASJIT 62 | case IR_LDEXP - IR_ADD: return ldexp(x, (int)y); break; 63 | case IR_MIN - IR_ADD: return x < y ? x : y; break; 64 | case IR_MAX - IR_ADD: return x > y ? x : y; break; 65 | #endif 66 | default: return x; 67 | } 68 | } 69 | 70 | /* -- Helper functions for generated machine code ------------------------- */ 71 | 72 | #if (LJ_HASJIT && !(LJ_TARGET_ARM || LJ_TARGET_ARM64 || LJ_TARGET_PPC)) || LJ_TARGET_MIPS 73 | int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b) 74 | { 75 | uint32_t y, ua, ub; 76 | /* This must be checked before using this function. */ 77 | lj_assertX(b != 0, "modulo with zero divisor"); 78 | ua = a < 0 ? ~(uint32_t)a+1u : (uint32_t)a; 79 | ub = b < 0 ? ~(uint32_t)b+1u : (uint32_t)b; 80 | y = ua % ub; 81 | if (y != 0 && (a^b) < 0) y = y - ub; 82 | if (((int32_t)y^b) < 0) y = ~y+1u; 83 | return (int32_t)y; 84 | } 85 | #endif 86 | 87 | #if LJ_HASJIT 88 | 89 | #ifdef LUAJIT_NO_LOG2 90 | double lj_vm_log2(double a) 91 | { 92 | return log(a) * 1.4426950408889634074; 93 | } 94 | #endif 95 | 96 | /* Computes fpm(x) for extended math functions. */ 97 | double lj_vm_foldfpm(double x, int fpm) 98 | { 99 | switch (fpm) { 100 | case IRFPM_FLOOR: return lj_vm_floor(x); 101 | case IRFPM_CEIL: return lj_vm_ceil(x); 102 | case IRFPM_TRUNC: return lj_vm_trunc(x); 103 | case IRFPM_SQRT: return sqrt(x); 104 | case IRFPM_LOG: return log(x); 105 | case IRFPM_LOG2: return lj_vm_log2(x); 106 | default: lj_assertX(0, "bad fpm %d", fpm); 107 | } 108 | return 0; 109 | } 110 | 111 | #if LJ_HASFFI 112 | int lj_vm_errno(void) 113 | { 114 | return errno; 115 | } 116 | #endif 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/ljamalg.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** LuaJIT core and libraries amalgamation. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #define ljamalg_c 7 | #define LUA_CORE 8 | 9 | /* To get the mremap prototype. Must be defined before any system includes. */ 10 | #if defined(__linux__) && !defined(_GNU_SOURCE) 11 | #define _GNU_SOURCE 12 | #endif 13 | 14 | #ifndef WINVER 15 | #define WINVER 0x0501 16 | #endif 17 | 18 | #include "lua.h" 19 | #include "lauxlib.h" 20 | 21 | #include "lj_assert.c" 22 | #include "lj_gc.c" 23 | #include "lj_err.c" 24 | #include "lj_char.c" 25 | #include "lj_bc.c" 26 | #include "lj_obj.c" 27 | #include "lj_buf.c" 28 | #include "lj_str.c" 29 | #include "lj_tab.c" 30 | #include "lj_func.c" 31 | #include "lj_udata.c" 32 | #include "lj_meta.c" 33 | #include "lj_debug.c" 34 | #include "lj_prng.c" 35 | #include "lj_state.c" 36 | #include "lj_dispatch.c" 37 | #include "lj_vmevent.c" 38 | #include "lj_vmmath.c" 39 | #include "lj_strscan.c" 40 | #include "lj_strfmt.c" 41 | #include "lj_strfmt_num.c" 42 | #include "lj_serialize.c" 43 | #include "lj_api.c" 44 | #include "lj_profile.c" 45 | #include "lj_lex.c" 46 | #include "lj_parse.c" 47 | #include "lj_bcread.c" 48 | #include "lj_bcwrite.c" 49 | #include "lj_load.c" 50 | #include "lj_ctype.c" 51 | #include "lj_cdata.c" 52 | #include "lj_cconv.c" 53 | #include "lj_ccall.c" 54 | #include "lj_ccallback.c" 55 | #include "lj_carith.c" 56 | #include "lj_clib.c" 57 | #include "lj_cparse.c" 58 | #include "lj_lib.c" 59 | #include "lj_ir.c" 60 | #include "lj_opt_mem.c" 61 | #include "lj_opt_fold.c" 62 | #include "lj_opt_narrow.c" 63 | #include "lj_opt_dce.c" 64 | #include "lj_opt_loop.c" 65 | #include "lj_opt_split.c" 66 | #include "lj_opt_sink.c" 67 | #include "lj_mcode.c" 68 | #include "lj_snap.c" 69 | #include "lj_record.c" 70 | #include "lj_crecord.c" 71 | #include "lj_ffrecord.c" 72 | #include "lj_asm.c" 73 | #include "lj_trace.c" 74 | #include "lj_gdbjit.c" 75 | #include "lj_alloc.c" 76 | 77 | #include "lib_aux.c" 78 | #include "lib_base.c" 79 | #include "lib_math.c" 80 | #include "lib_string.c" 81 | #include "lib_table.c" 82 | #include "lib_io.c" 83 | #include "lib_os.c" 84 | #include "lib_package.c" 85 | #include "lib_debug.c" 86 | #include "lib_bit.c" 87 | #include "lib_jit.c" 88 | #include "lib_ffi.c" 89 | #include "lib_buffer.c" 90 | #include "lib_init.c" 91 | -------------------------------------------------------------------------------- /src/lua.hpp: -------------------------------------------------------------------------------- 1 | // C++ wrapper for LuaJIT header files. 2 | 3 | extern "C" { 4 | #include "lua.h" 5 | #include "lauxlib.h" 6 | #include "lualib.h" 7 | #include "luajit.h" 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/luaconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Configuration header. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef luaconf_h 7 | #define luaconf_h 8 | 9 | #ifndef WINVER 10 | #define WINVER 0x0501 11 | #endif 12 | #include 13 | 14 | /* Default path for loading Lua and C modules with require(). */ 15 | #if defined(_WIN32) 16 | /* 17 | ** In Windows, any exclamation mark ('!') in the path is replaced by the 18 | ** path of the directory of the executable file of the current process. 19 | */ 20 | #define LUA_LDIR "!\\lua\\" 21 | #define LUA_CDIR "!\\" 22 | #define LUA_PATH_DEFAULT \ 23 | ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" 24 | #define LUA_CPATH_DEFAULT \ 25 | ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" 26 | #else 27 | /* 28 | ** Note to distribution maintainers: do NOT patch the following lines! 29 | ** Please read ../doc/install.html#distro and pass PREFIX=/usr instead. 30 | */ 31 | #ifndef LUA_MULTILIB 32 | #define LUA_MULTILIB "lib" 33 | #endif 34 | #ifndef LUA_LMULTILIB 35 | #define LUA_LMULTILIB "lib" 36 | #endif 37 | #define LUA_LROOT "/usr/local" 38 | #define LUA_LUADIR "/lua/5.1/" 39 | 40 | #ifdef LUA_ROOT 41 | #define LUA_JROOT LUA_ROOT 42 | #define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR 43 | #define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR 44 | #define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua" 45 | #define LUA_RCPATH ";" LUA_RCDIR "?.so" 46 | #else 47 | #define LUA_JROOT LUA_LROOT 48 | #define LUA_RLPATH 49 | #define LUA_RCPATH 50 | #endif 51 | 52 | #ifndef LUA_LJDIR 53 | #define LUA_LJDIR LUA_JROOT "/share/luajit-2.1" 54 | #endif 55 | 56 | #define LUA_JPATH ";" LUA_LJDIR "/?.lua" 57 | #define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR 58 | #define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR 59 | #define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua" 60 | #define LUA_LCPATH1 ";" LUA_LCDIR "?.so" 61 | #define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so" 62 | 63 | #define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH 64 | #define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2 65 | #endif 66 | 67 | /* Environment variable names for path overrides and initialization code. */ 68 | #define LUA_PATH "LUA_PATH" 69 | #define LUA_CPATH "LUA_CPATH" 70 | #define LUA_INIT "LUA_INIT" 71 | 72 | /* Special file system characters. */ 73 | #if defined(_WIN32) 74 | #define LUA_DIRSEP "\\" 75 | #else 76 | #define LUA_DIRSEP "/" 77 | #endif 78 | #define LUA_PATHSEP ";" 79 | #define LUA_PATH_MARK "?" 80 | #define LUA_EXECDIR "!" 81 | #define LUA_IGMARK "-" 82 | #define LUA_PATH_CONFIG \ 83 | LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \ 84 | LUA_EXECDIR "\n" LUA_IGMARK "\n" 85 | 86 | /* Quoting in error messages. */ 87 | #define LUA_QL(x) "'" x "'" 88 | #define LUA_QS LUA_QL("%s") 89 | 90 | /* Various tunables. */ 91 | #define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */ 92 | #define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */ 93 | #define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */ 94 | #define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */ 95 | #define LUA_MAXCAPTURES 32 /* Max. pattern captures. */ 96 | 97 | /* Configuration for the frontend (the luajit executable). */ 98 | #if defined(luajit_c) 99 | #define LUA_PROGNAME "luajit" /* Fallback frontend name. */ 100 | #define LUA_PROMPT "> " /* Interactive prompt. */ 101 | #define LUA_PROMPT2 ">> " /* Continuation prompt. */ 102 | #define LUA_MAXINPUT 512 /* Max. input line length. */ 103 | #endif 104 | 105 | /* Note: changing the following defines breaks the Lua 5.1 ABI. */ 106 | #define LUA_INTEGER ptrdiff_t 107 | #define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */ 108 | /* 109 | ** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using 110 | ** unreasonable amounts of stack space, but still retain ABI compatibility. 111 | ** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it. 112 | */ 113 | #define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ) 114 | 115 | /* The following defines are here only for compatibility with luaconf.h 116 | ** from the standard Lua distribution. They must not be changed for LuaJIT. 117 | */ 118 | #define LUA_NUMBER_DOUBLE 119 | #define LUA_NUMBER double 120 | #define LUAI_UACNUMBER double 121 | #define LUA_NUMBER_SCAN "%lf" 122 | #define LUA_NUMBER_FMT "%.14g" 123 | #define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n)) 124 | #define LUAI_MAXNUMBER2STR 32 125 | #define LUA_INTFRMLEN "l" 126 | #define LUA_INTFRM_T long 127 | 128 | /* Linkage of public API functions. */ 129 | #if defined(LUA_BUILD_AS_DLL) 130 | #if defined(LUA_CORE) || defined(LUA_LIB) 131 | #define LUA_API __declspec(dllexport) 132 | #else 133 | #define LUA_API __declspec(dllimport) 134 | #endif 135 | #else 136 | #define LUA_API extern 137 | #endif 138 | 139 | #define LUALIB_API LUA_API 140 | 141 | /* Compatibility support for assertions. */ 142 | #if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK) 143 | #include 144 | #endif 145 | #ifdef LUA_USE_ASSERT 146 | #define lua_assert(x) assert(x) 147 | #endif 148 | #ifdef LUA_USE_APICHECK 149 | #define luai_apicheck(L, o) { (void)L; assert(o); } 150 | #else 151 | #define luai_apicheck(L, o) { (void)L; } 152 | #endif 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /src/luajit_rolling.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/ 3 | ** 4 | ** Copyright (C) 2005-2025 Mike Pall. All rights reserved. 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining 7 | ** a copy of this software and associated documentation files (the 8 | ** "Software"), to deal in the Software without restriction, including 9 | ** without limitation the rights to use, copy, modify, merge, publish, 10 | ** distribute, sublicense, and/or sell copies of the Software, and to 11 | ** permit persons to whom the Software is furnished to do so, subject to 12 | ** the following conditions: 13 | ** 14 | ** The above copyright notice and this permission notice shall be 15 | ** included in all copies or substantial portions of the Software. 16 | ** 17 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | ** 25 | ** [ MIT license: https://www.opensource.org/licenses/mit-license.php ] 26 | */ 27 | 28 | #ifndef _LUAJIT_H 29 | #define _LUAJIT_H 30 | 31 | #include "lua.h" 32 | 33 | #define OPENRESTY_LUAJIT 34 | 35 | #define LUAJIT_VERSION "LuaJIT 2.1.ROLLING" 36 | #define LUAJIT_VERSION_NUM 20199 /* Deprecated. */ 37 | #define LUAJIT_VERSION_SYM luaJIT_version_2_1_ROLLING 38 | #define LUAJIT_COPYRIGHT "Copyright (C) 2005-2025 Mike Pall" 39 | #define LUAJIT_URL "https://luajit.org/" 40 | 41 | /* Modes for luaJIT_setmode. */ 42 | #define LUAJIT_MODE_MASK 0x00ff 43 | 44 | enum { 45 | LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */ 46 | LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */ 47 | 48 | LUAJIT_MODE_FUNC, /* Change mode for a function. */ 49 | LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */ 50 | LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */ 51 | 52 | LUAJIT_MODE_TRACE, /* Flush a compiled trace. */ 53 | 54 | LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */ 55 | 56 | LUAJIT_MODE_MAX 57 | }; 58 | 59 | /* Flags or'ed in to the mode. */ 60 | #define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */ 61 | #define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */ 62 | #define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */ 63 | 64 | /* LuaJIT public C API. */ 65 | 66 | /* Control the JIT engine. */ 67 | LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode); 68 | 69 | /* Low-overhead profiling API. */ 70 | typedef void (*luaJIT_profile_callback)(void *data, lua_State *L, 71 | int samples, int vmstate); 72 | LUA_API void luaJIT_profile_start(lua_State *L, const char *mode, 73 | luaJIT_profile_callback cb, void *data); 74 | LUA_API void luaJIT_profile_stop(lua_State *L); 75 | LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt, 76 | int depth, size_t *len); 77 | 78 | /* Enforce (dynamic) linker error for version mismatches. Call from main. */ 79 | LUA_API void LUAJIT_VERSION_SYM(void); 80 | 81 | #error "DO NOT USE luajit_rolling.h -- only include build-generated luajit.h" 82 | #endif 83 | -------------------------------------------------------------------------------- /src/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Standard library header. 3 | ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 4 | */ 5 | 6 | #ifndef _LUALIB_H 7 | #define _LUALIB_H 8 | 9 | #include "lua.h" 10 | 11 | #define LUA_FILEHANDLE "FILE*" 12 | 13 | #define LUA_COLIBNAME "coroutine" 14 | #define LUA_MATHLIBNAME "math" 15 | #define LUA_STRLIBNAME "string" 16 | #define LUA_TABLIBNAME "table" 17 | #define LUA_IOLIBNAME "io" 18 | #define LUA_OSLIBNAME "os" 19 | #define LUA_LOADLIBNAME "package" 20 | #define LUA_DBLIBNAME "debug" 21 | #define LUA_BITLIBNAME "bit" 22 | #define LUA_JITLIBNAME "jit" 23 | #define LUA_FFILIBNAME "ffi" 24 | #define LUA_THRLIBNAME "thread" 25 | 26 | LUALIB_API int luaopen_base(lua_State *L); 27 | LUALIB_API int luaopen_math(lua_State *L); 28 | LUALIB_API int luaopen_string(lua_State *L); 29 | LUALIB_API int luaopen_table(lua_State *L); 30 | LUALIB_API int luaopen_io(lua_State *L); 31 | LUALIB_API int luaopen_os(lua_State *L); 32 | LUALIB_API int luaopen_package(lua_State *L); 33 | LUALIB_API int luaopen_debug(lua_State *L); 34 | LUALIB_API int luaopen_bit(lua_State *L); 35 | LUALIB_API int luaopen_jit(lua_State *L); 36 | LUALIB_API int luaopen_ffi(lua_State *L); 37 | LUALIB_API int luaopen_string_buffer(lua_State *L); 38 | 39 | LUALIB_API void luaL_openlibs(lua_State *L); 40 | 41 | #ifndef lua_assert 42 | #define lua_assert(x) ((void)0) 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/msvcbuild.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build LuaJIT with MSVC. 2 | @rem Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h 3 | @rem 4 | @rem Open a "Visual Studio Command Prompt" (either x86 or x64). 5 | @rem Then cd to this directory and run this script. Use the following 6 | @rem options (in order), if needed. The default is a dynamic release build. 7 | @rem 8 | @rem nogc64 disable LJ_GC64 mode for x64 9 | @rem debug emit debug symbols 10 | @rem amalg amalgamated build 11 | @rem static create static lib to statically link into your project 12 | @rem mixed create static lib to build a DLL in your project 13 | 14 | @if not defined INCLUDE goto :FAIL 15 | 16 | @setlocal 17 | @rem Add more debug flags here, e.g. DEBUGCFLAGS=/DLUA_USE_ASSERT 18 | @set DEBUGCFLAGS= 19 | @set LJCOMPILE=cl /nologo /c /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_STDIO_INLINE=__declspec(dllexport)__inline 20 | @set LJDYNBUILD=/DLUA_BUILD_AS_DLL /MD 21 | @set LJDYNBUILD_DEBUG=/DLUA_BUILD_AS_DLL /MDd 22 | @set LJCOMPILETARGET=/Zi 23 | @set LJLINKTYPE=/DEBUG /RELEASE 24 | @set LJLINKTYPE_DEBUG=/DEBUG 25 | @set LJLINKTARGET=/OPT:REF /OPT:ICF /INCREMENTAL:NO 26 | @set LJLINK=link /nologo 27 | @set LJMT=mt /nologo 28 | @set LJLIB=lib /nologo /nodefaultlib 29 | @set DASMDIR=..\dynasm 30 | @set DASM=%DASMDIR%\dynasm.lua 31 | @set DASC=vm_x64.dasc 32 | @set LJDLLNAME=lua51.dll 33 | @set LJLIBNAME=lua51.lib 34 | @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c 35 | 36 | @setlocal 37 | @call :SETHOSTVARS 38 | %LJCOMPILE% host\minilua.c 39 | @if errorlevel 1 goto :BAD 40 | %LJLINK% /out:minilua.exe minilua.obj 41 | @if errorlevel 1 goto :BAD 42 | if exist minilua.exe.manifest^ 43 | %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe 44 | @endlocal 45 | 46 | @set DASMFLAGS=-D WIN -D JIT -D FFI -D ENDIAN_LE -D FPU -D P64 47 | @set LJARCH=x64 48 | @minilua 49 | @if errorlevel 8 goto :NO32 50 | @set DASC=vm_x86.dasc 51 | @set DASMFLAGS=-D WIN -D JIT -D FFI -D ENDIAN_LE -D FPU 52 | @set LJARCH=x86 53 | @set LJCOMPILE=%LJCOMPILE% /arch:SSE2 54 | @goto :DA 55 | :NO32 56 | @if "%VSCMD_ARG_TGT_ARCH%" neq "arm64" goto :X64 57 | @set DASC=vm_arm64.dasc 58 | @set DASMTARGET=-D LUAJIT_TARGET=LUAJIT_ARCH_ARM64 59 | @set LJARCH=arm64 60 | @goto :DA 61 | :X64 62 | @if "%1" neq "nogc64" goto :DA 63 | @shift 64 | @set DASC=vm_x86.dasc 65 | @set LJCOMPILE=%LJCOMPILE% /DLUAJIT_DISABLE_GC64 66 | :DA 67 | minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h %DASC% 68 | @if errorlevel 1 goto :BAD 69 | 70 | if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt ) 71 | minilua host\genversion.lua 72 | 73 | @setlocal 74 | @call :SETHOSTVARS 75 | %LJCOMPILE% /I "." /I %DASMDIR% %DASMTARGET% host\buildvm*.c 76 | @if errorlevel 1 goto :BAD 77 | %LJLINK% /out:buildvm.exe buildvm*.obj 78 | @if errorlevel 1 goto :BAD 79 | if exist buildvm.exe.manifest^ 80 | %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe 81 | @endlocal 82 | 83 | buildvm -m peobj -o lj_vm.obj 84 | @if errorlevel 1 goto :BAD 85 | buildvm -m bcdef -o lj_bcdef.h %ALL_LIB% 86 | @if errorlevel 1 goto :BAD 87 | buildvm -m ffdef -o lj_ffdef.h %ALL_LIB% 88 | @if errorlevel 1 goto :BAD 89 | buildvm -m libdef -o lj_libdef.h %ALL_LIB% 90 | @if errorlevel 1 goto :BAD 91 | buildvm -m recdef -o lj_recdef.h %ALL_LIB% 92 | @if errorlevel 1 goto :BAD 93 | buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB% 94 | @if errorlevel 1 goto :BAD 95 | buildvm -m folddef -o lj_folddef.h lj_opt_fold.c 96 | @if errorlevel 1 goto :BAD 97 | 98 | @if "%1" neq "debug" goto :NODEBUG 99 | @shift 100 | @set LJCOMPILE=%LJCOMPILE% %DEBUGCFLAGS% 101 | @set LJDYNBUILD=%LJDYNBUILD_DEBUG% 102 | @set LJLINKTYPE=%LJLINKTYPE_DEBUG% 103 | :NODEBUG 104 | @set LJCOMPILE=%LJCOMPILE% %LJCOMPILETARGET% 105 | @set LJLINK=%LJLINK% %LJLINKTYPE% %LJLINKTARGET% 106 | @if "%1"=="amalg" goto :AMALGDLL 107 | @if "%1"=="static" goto :STATIC 108 | %LJCOMPILE% %LJDYNBUILD% lj_*.c lib_*.c 109 | @if errorlevel 1 goto :BAD 110 | @if "%1"=="mixed" goto :STATICLIB 111 | %LJLINK% /DLL /OUT:%LJDLLNAME% lj_*.obj lib_*.obj 112 | @if errorlevel 1 goto :BAD 113 | @goto :MTDLL 114 | :STATIC 115 | %LJCOMPILE% lj_*.c lib_*.c 116 | @if errorlevel 1 goto :BAD 117 | :STATICLIB 118 | %LJLIB% /OUT:%LJLIBNAME% lj_*.obj lib_*.obj 119 | @if errorlevel 1 goto :BAD 120 | @goto :MTDLL 121 | :AMALGDLL 122 | @if "%2"=="static" goto :AMALGSTATIC 123 | %LJCOMPILE% %LJDYNBUILD% ljamalg.c 124 | @if errorlevel 1 goto :BAD 125 | @if "%2"=="mixed" goto :AMALGSTATICLIB 126 | %LJLINK% /DLL /OUT:%LJDLLNAME% ljamalg.obj lj_vm.obj 127 | @if errorlevel 1 goto :BAD 128 | @goto :MTDLL 129 | :AMALGSTATIC 130 | %LJCOMPILE% ljamalg.c 131 | @if errorlevel 1 goto :BAD 132 | :AMALGSTATICLIB 133 | %LJLIB% /OUT:%LJLIBNAME% ljamalg.obj lj_vm.obj 134 | @if errorlevel 1 goto :BAD 135 | :MTDLL 136 | if exist %LJDLLNAME%.manifest^ 137 | %LJMT% -manifest %LJDLLNAME%.manifest -outputresource:%LJDLLNAME%;2 138 | 139 | %LJCOMPILE% luajit.c 140 | @if errorlevel 1 goto :BAD 141 | %LJLINK% /OUT:luajit.exe luajit.obj %LJLIBNAME% 142 | @if errorlevel 1 goto :BAD 143 | if exist luajit.exe.manifest^ 144 | %LJMT% -manifest luajit.exe.manifest -outputresource:luajit.exe 145 | 146 | @del *.obj *.manifest minilua.exe buildvm.exe 147 | @del host\buildvm_arch.h 148 | @del lj_bcdef.h lj_ffdef.h lj_libdef.h lj_recdef.h lj_folddef.h 149 | @echo. 150 | @echo === Successfully built LuaJIT for Windows/%LJARCH% === 151 | 152 | @goto :END 153 | :SETHOSTVARS 154 | @if "%VSCMD_ARG_HOST_ARCH%_%VSCMD_ARG_TGT_ARCH%" equ "x64_arm64" ( 155 | call "%VSINSTALLDIR%Common7\Tools\VsDevCmd.bat" -arch=%VSCMD_ARG_HOST_ARCH% -no_logo 156 | echo on 157 | ) 158 | @goto :END 159 | :BAD 160 | @echo. 161 | @echo ******************************************************* 162 | @echo *** Build FAILED -- Please check the error messages *** 163 | @echo ******************************************************* 164 | @goto :END 165 | :FAIL 166 | @echo You must open a "Visual Studio Command Prompt" to run this script 167 | :END 168 | -------------------------------------------------------------------------------- /src/ps4build.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build LuaJIT with the PS4 SDK. 2 | @rem Donated to the public domain. 3 | @rem 4 | @rem Open a "Visual Studio .NET Command Prompt" (64 bit host compiler) 5 | @rem or "VS2015 x64 Native Tools Command Prompt". 6 | @rem 7 | @rem Then cd to this directory and run this script. 8 | @rem 9 | @rem Recommended invocation: 10 | @rem 11 | @rem ps4build release build, amalgamated, 64-bit GC 12 | @rem ps4build debug debug build, amalgamated, 64-bit GC 13 | @rem 14 | @rem Additional command-line options (not generally recommended): 15 | @rem 16 | @rem gc32 (before debug) 32-bit GC 17 | @rem noamalg (after debug) non-amalgamated build 18 | 19 | @if not defined INCLUDE goto :FAIL 20 | @if not defined SCE_ORBIS_SDK_DIR goto :FAIL 21 | 22 | @setlocal 23 | @rem ---- Host compiler ---- 24 | @set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE 25 | @set LJLINK=link /nologo 26 | @set LJMT=mt /nologo 27 | @set DASMDIR=..\dynasm 28 | @set DASM=%DASMDIR%\dynasm.lua 29 | @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c 30 | @set GC64= 31 | @set DASC=vm_x64.dasc 32 | 33 | @if "%1" neq "gc32" goto :NOGC32 34 | @shift 35 | @set GC64=-DLUAJIT_DISABLE_GC64 36 | @set DASC=vm_x86.dasc 37 | :NOGC32 38 | 39 | %LJCOMPILE% host\minilua.c 40 | @if errorlevel 1 goto :BAD 41 | %LJLINK% /out:minilua.exe minilua.obj 42 | @if errorlevel 1 goto :BAD 43 | if exist minilua.exe.manifest^ 44 | %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe 45 | 46 | @rem Check for 64 bit host compiler. 47 | @minilua 48 | @if not errorlevel 8 goto :FAIL 49 | 50 | @set DASMFLAGS=-D P64 -D NO_UNWIND 51 | minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h %DASC% 52 | @if errorlevel 1 goto :BAD 53 | 54 | if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt ) 55 | minilua host\genversion.lua 56 | 57 | %LJCOMPILE% /I "." /I %DASMDIR% %GC64% -DLUAJIT_TARGET=LUAJIT_ARCH_X64 -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI -DLUAJIT_USE_SYSMALLOC -DLUAJIT_NO_UNWIND host\buildvm*.c 58 | 59 | @if errorlevel 1 goto :BAD 60 | %LJLINK% /out:buildvm.exe buildvm*.obj 61 | @if errorlevel 1 goto :BAD 62 | if exist buildvm.exe.manifest^ 63 | %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe 64 | 65 | buildvm -m elfasm -o lj_vm.s 66 | @if errorlevel 1 goto :BAD 67 | buildvm -m bcdef -o lj_bcdef.h %ALL_LIB% 68 | @if errorlevel 1 goto :BAD 69 | buildvm -m ffdef -o lj_ffdef.h %ALL_LIB% 70 | @if errorlevel 1 goto :BAD 71 | buildvm -m libdef -o lj_libdef.h %ALL_LIB% 72 | @if errorlevel 1 goto :BAD 73 | buildvm -m recdef -o lj_recdef.h %ALL_LIB% 74 | @if errorlevel 1 goto :BAD 75 | buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB% 76 | @if errorlevel 1 goto :BAD 77 | buildvm -m folddef -o lj_folddef.h lj_opt_fold.c 78 | @if errorlevel 1 goto :BAD 79 | 80 | @rem ---- Cross compiler ---- 81 | @set LJCOMPILE="%SCE_ORBIS_SDK_DIR%\host_tools\bin\orbis-clang" -c -Wall -DLUAJIT_DISABLE_FFI %GC64% 82 | @set LJLIB="%SCE_ORBIS_SDK_DIR%\host_tools\bin\orbis-ar" rcus 83 | @set INCLUDE="" 84 | 85 | "%SCE_ORBIS_SDK_DIR%\host_tools\bin\orbis-as" -o lj_vm.o lj_vm.s 86 | 87 | @if "%1" neq "debug" goto :NODEBUG 88 | @shift 89 | @set LJCOMPILE=%LJCOMPILE% -g -O0 90 | @set TARGETLIB=libluajitD_ps4.a 91 | goto :BUILD 92 | :NODEBUG 93 | @set LJCOMPILE=%LJCOMPILE% -O2 94 | @set TARGETLIB=libluajit_ps4.a 95 | :BUILD 96 | del %TARGETLIB% 97 | @if "%1" neq "noamalg" goto :AMALG 98 | for %%f in (lj_*.c lib_*.c) do ( 99 | %LJCOMPILE% %%f 100 | @if errorlevel 1 goto :BAD 101 | ) 102 | 103 | %LJLIB% %TARGETLIB% lj_*.o lib_*.o 104 | @if errorlevel 1 goto :BAD 105 | @goto :NOAMALG 106 | :AMALG 107 | %LJCOMPILE% ljamalg.c 108 | @if errorlevel 1 goto :BAD 109 | %LJLIB% %TARGETLIB% ljamalg.o lj_vm.o 110 | @if errorlevel 1 goto :BAD 111 | :NOAMALG 112 | 113 | @del *.o *.obj *.manifest minilua.exe buildvm.exe 114 | @echo. 115 | @echo === Successfully built LuaJIT for PS4 === 116 | 117 | @goto :END 118 | :BAD 119 | @echo. 120 | @echo ******************************************************* 121 | @echo *** Build FAILED -- Please check the error messages *** 122 | @echo ******************************************************* 123 | @goto :END 124 | :FAIL 125 | @echo To run this script you must open a "Visual Studio .NET Command Prompt" 126 | @echo (64 bit host compiler). The PS4 Orbis SDK must be installed, too. 127 | :END 128 | -------------------------------------------------------------------------------- /src/ps5build.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build LuaJIT with the PS5 SDK. 2 | @rem Donated to the public domain. 3 | @rem 4 | @rem Open a "Visual Studio .NET Command Prompt" (64 bit host compiler) 5 | @rem or "VS20xx x64 Native Tools Command Prompt". 6 | @rem 7 | @rem Then cd to this directory and run this script. 8 | @rem 9 | @rem Recommended invocation: 10 | @rem 11 | @rem ps5build release build, amalgamated, 64-bit GC 12 | @rem ps5build debug debug build, amalgamated, 64-bit GC 13 | @rem 14 | @rem Additional command-line options (not generally recommended): 15 | @rem 16 | @rem gc32 (before debug) 32-bit GC 17 | @rem noamalg (after debug) non-amalgamated build 18 | 19 | @if not defined INCLUDE goto :FAIL 20 | @if not defined SCE_PROSPERO_SDK_DIR goto :FAIL 21 | 22 | @setlocal 23 | @rem ---- Host compiler ---- 24 | @set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE 25 | @set LJLINK=link /nologo 26 | @set LJMT=mt /nologo 27 | @set DASMDIR=..\dynasm 28 | @set DASM=%DASMDIR%\dynasm.lua 29 | @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c 30 | @set GC64= 31 | @set DASC=vm_x64.dasc 32 | 33 | @if "%1" neq "gc32" goto :NOGC32 34 | @shift 35 | @set GC64=-DLUAJIT_DISABLE_GC64 36 | @set DASC=vm_x86.dasc 37 | :NOGC32 38 | 39 | %LJCOMPILE% host\minilua.c 40 | @if errorlevel 1 goto :BAD 41 | %LJLINK% /out:minilua.exe minilua.obj 42 | @if errorlevel 1 goto :BAD 43 | if exist minilua.exe.manifest^ 44 | %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe 45 | 46 | @rem Check for 64 bit host compiler. 47 | @minilua 48 | @if not errorlevel 8 goto :FAIL 49 | 50 | @set DASMFLAGS=-D P64 -D NO_UNWIND 51 | minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h %DASC% 52 | @if errorlevel 1 goto :BAD 53 | 54 | if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt ) 55 | minilua host\genversion.lua 56 | 57 | %LJCOMPILE% /I "." /I %DASMDIR% %GC64% -DLUAJIT_TARGET=LUAJIT_ARCH_X64 -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI -DLUAJIT_NO_UNWIND host\buildvm*.c 58 | @if errorlevel 1 goto :BAD 59 | %LJLINK% /out:buildvm.exe buildvm*.obj 60 | @if errorlevel 1 goto :BAD 61 | if exist buildvm.exe.manifest^ 62 | %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe 63 | 64 | buildvm -m elfasm -o lj_vm.s 65 | @if errorlevel 1 goto :BAD 66 | buildvm -m bcdef -o lj_bcdef.h %ALL_LIB% 67 | @if errorlevel 1 goto :BAD 68 | buildvm -m ffdef -o lj_ffdef.h %ALL_LIB% 69 | @if errorlevel 1 goto :BAD 70 | buildvm -m libdef -o lj_libdef.h %ALL_LIB% 71 | @if errorlevel 1 goto :BAD 72 | buildvm -m recdef -o lj_recdef.h %ALL_LIB% 73 | @if errorlevel 1 goto :BAD 74 | buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB% 75 | @if errorlevel 1 goto :BAD 76 | buildvm -m folddef -o lj_folddef.h lj_opt_fold.c 77 | @if errorlevel 1 goto :BAD 78 | 79 | @rem ---- Cross compiler ---- 80 | @set LJCOMPILE="%SCE_PROSPERO_SDK_DIR%\host_tools\bin\prospero-clang" -c -Wall -DLUAJIT_DISABLE_FFI -DLUAJIT_USE_SYSMALLOC %GC64% 81 | @set LJLIB="%SCE_PROSPERO_SDK_DIR%\host_tools\bin\prospero-llvm-ar" rcus 82 | @set INCLUDE="" 83 | 84 | "%SCE_PROSPERO_SDK_DIR%\host_tools\bin\prospero-clang" -c -o lj_vm.o lj_vm.s 85 | 86 | @if "%1" neq "debug" goto :NODEBUG 87 | @shift 88 | @set LJCOMPILE=%LJCOMPILE% -g -O0 89 | @set TARGETLIB=libluajitD_ps5.a 90 | goto :BUILD 91 | :NODEBUG 92 | @set LJCOMPILE=%LJCOMPILE% -O2 93 | @set TARGETLIB=libluajit_ps5.a 94 | :BUILD 95 | del %TARGETLIB% 96 | @if "%1" neq "noamalg" goto :AMALG 97 | for %%f in (lj_*.c lib_*.c) do ( 98 | %LJCOMPILE% %%f 99 | @if errorlevel 1 goto :BAD 100 | ) 101 | 102 | %LJLIB% %TARGETLIB% lj_*.o lib_*.o 103 | @if errorlevel 1 goto :BAD 104 | @goto :NOAMALG 105 | :AMALG 106 | %LJCOMPILE% ljamalg.c 107 | @if errorlevel 1 goto :BAD 108 | %LJLIB% %TARGETLIB% ljamalg.o lj_vm.o 109 | @if errorlevel 1 goto :BAD 110 | :NOAMALG 111 | 112 | @del *.o *.obj *.manifest minilua.exe buildvm.exe 113 | @echo. 114 | @echo === Successfully built LuaJIT for PS5 === 115 | 116 | @goto :END 117 | :BAD 118 | @echo. 119 | @echo ******************************************************* 120 | @echo *** Build FAILED -- Please check the error messages *** 121 | @echo ******************************************************* 122 | @goto :END 123 | :FAIL 124 | @echo To run this script you must open a "Visual Studio .NET Command Prompt" 125 | @echo (64 bit host compiler). The PS5 Prospero SDK must be installed, too. 126 | :END 127 | -------------------------------------------------------------------------------- /src/psvitabuild.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build LuaJIT with the PS Vita SDK. 2 | @rem Donated to the public domain. 3 | @rem 4 | @rem Open a "Visual Studio .NET Command Prompt" (32 bit host compiler) 5 | @rem Then cd to this directory and run this script. 6 | 7 | @if not defined INCLUDE goto :FAIL 8 | @if not defined SCE_PSP2_SDK_DIR goto :FAIL 9 | 10 | @setlocal 11 | @rem ---- Host compiler ---- 12 | @set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE 13 | @set LJLINK=link /nologo 14 | @set LJMT=mt /nologo 15 | @set DASMDIR=..\dynasm 16 | @set DASM=%DASMDIR%\dynasm.lua 17 | @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c 18 | 19 | %LJCOMPILE% host\minilua.c 20 | @if errorlevel 1 goto :BAD 21 | %LJLINK% /out:minilua.exe minilua.obj 22 | @if errorlevel 1 goto :BAD 23 | if exist minilua.exe.manifest^ 24 | %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe 25 | 26 | @rem Check for 32 bit host compiler. 27 | @minilua 28 | @if errorlevel 8 goto :FAIL 29 | 30 | @set DASMFLAGS=-D FPU -D HFABI 31 | minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_arm.dasc 32 | @if errorlevel 1 goto :BAD 33 | 34 | if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt ) 35 | minilua host\genversion.lua 36 | 37 | %LJCOMPILE% /I "." /I %DASMDIR% -DLUAJIT_TARGET=LUAJIT_ARCH_ARM -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI -DLJ_TARGET_PSVITA=1 host\buildvm*.c 38 | @if errorlevel 1 goto :BAD 39 | %LJLINK% /out:buildvm.exe buildvm*.obj 40 | @if errorlevel 1 goto :BAD 41 | if exist buildvm.exe.manifest^ 42 | %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe 43 | 44 | buildvm -m elfasm -o lj_vm.s 45 | @if errorlevel 1 goto :BAD 46 | buildvm -m bcdef -o lj_bcdef.h %ALL_LIB% 47 | @if errorlevel 1 goto :BAD 48 | buildvm -m ffdef -o lj_ffdef.h %ALL_LIB% 49 | @if errorlevel 1 goto :BAD 50 | buildvm -m libdef -o lj_libdef.h %ALL_LIB% 51 | @if errorlevel 1 goto :BAD 52 | buildvm -m recdef -o lj_recdef.h %ALL_LIB% 53 | @if errorlevel 1 goto :BAD 54 | buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB% 55 | @if errorlevel 1 goto :BAD 56 | buildvm -m folddef -o lj_folddef.h lj_opt_fold.c 57 | @if errorlevel 1 goto :BAD 58 | 59 | @rem ---- Cross compiler ---- 60 | @set LJCOMPILE="%SCE_PSP2_SDK_DIR%\host_tools\build\bin\psp2snc" -c -w -DLUAJIT_DISABLE_FFI -DLUAJIT_USE_SYSMALLOC 61 | @set LJLIB="%SCE_PSP2_SDK_DIR%\host_tools\build\bin\psp2ld32" -r --output= 62 | @set INCLUDE="" 63 | 64 | "%SCE_PSP2_SDK_DIR%\host_tools\build\bin\psp2as" -o lj_vm.o lj_vm.s 65 | 66 | @if "%1" neq "debug" goto :NODEBUG 67 | @shift 68 | @set LJCOMPILE=%LJCOMPILE% -g -O0 69 | @set TARGETLIB=libluajitD.a 70 | goto :BUILD 71 | :NODEBUG 72 | @set LJCOMPILE=%LJCOMPILE% -O2 73 | @set TARGETLIB=libluajit.a 74 | :BUILD 75 | del %TARGETLIB% 76 | 77 | %LJCOMPILE% ljamalg.c 78 | @if errorlevel 1 goto :BAD 79 | %LJLIB%%TARGETLIB% ljamalg.o lj_vm.o 80 | @if errorlevel 1 goto :BAD 81 | 82 | @del *.o *.obj *.manifest minilua.exe buildvm.exe 83 | @echo. 84 | @echo === Successfully built LuaJIT for PS Vita === 85 | 86 | @goto :END 87 | :BAD 88 | @echo. 89 | @echo ******************************************************* 90 | @echo *** Build FAILED -- Please check the error messages *** 91 | @echo ******************************************************* 92 | @goto :END 93 | :FAIL 94 | @echo To run this script you must open a "Visual Studio .NET Command Prompt" 95 | @echo (32 bit host compiler). The PS Vita SDK must be installed, too. 96 | :END 97 | -------------------------------------------------------------------------------- /src/x64/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default test benchmark clean 2 | 3 | default: 4 | @echo "make target include: test bechmark clean" 5 | 6 | test: 7 | $(MAKE) -C test test 8 | 9 | benchmark: 10 | $(MAKE) -C test benchmark 11 | 12 | clean: 13 | $(MAKE) -C test clean 14 | -------------------------------------------------------------------------------- /src/x64/test/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default test benchmark 2 | 3 | default: test benchmark 4 | 5 | COMMON_OBJ := test_util.o 6 | 7 | TEST_PROGRAM := ht_test 8 | BENCHMARK_PROGRAM := ht_benchmark 9 | 10 | TEST_PROGRAM_OBJ := $(COMMON_OBJ) test.o 11 | BENCHMARK_PROGRAM_OBJ := $(COMMON_OBJ) benchmark.o 12 | 13 | ifeq ($(WITH_VALGRIND), 1) 14 | VALGRIND := valgrind --leak-check=full 15 | else 16 | VALGRIND := 17 | endif 18 | 19 | CXXFLAGS := -O3 -MD -g -msse4.2 -Wall -I../src -I../../../src 20 | 21 | %.o: %.cxx 22 | $(CXX) $(CXXFLAGS) -MD -c $< 23 | 24 | test: $(TEST_PROGRAM) 25 | @echo "some unit test" 26 | $(VALGRIND) ./$(TEST_PROGRAM) 27 | 28 | @echo "smoke test" 29 | ../../luajit test_str_comp.lua 30 | 31 | benchmark: $(BENCHMARK_PROGRAM) 32 | # micro benchmark 33 | ./$(BENCHMARK_PROGRAM) 34 | 35 | $(TEST_PROGRAM) : $(TEST_PROGRAM_OBJ) 36 | cat $(TEST_PROGRAM_OBJ:.o=.d) > dep1.txt 37 | $(CXX) $+ $(CXXFLAGS) -lm -o $@ 38 | 39 | $(BENCHMARK_PROGRAM): $(BENCHMARK_PROGRAM_OBJ) 40 | cat $(BENCHMARK_PROGRAM_OBJ:.o=.d) > dep2.txt 41 | $(CXX) $+ $(CXXFLAGS) -o $@ 42 | 43 | -include dep1.txt 44 | -include dep2.txt 45 | 46 | clean: 47 | -rm -f *.o *.d dep*.txt $(BENCHMARK_PROGRAM) $(TEST_PROGRAM) 48 | -------------------------------------------------------------------------------- /src/x64/test/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define LUAJIT_SECURITY_STRHASH 1 6 | #include "test_util.hpp" 7 | #include "../../lj_str.h" 8 | str_sparse_hashfn hash_sparse; 9 | str_dense_hashfn hash_dense; 10 | #include "../../lj_str_hash.c" 11 | 12 | using namespace std; 13 | 14 | 15 | static bool 16 | smoke_test() 17 | { 18 | fprintf(stdout, "running smoke tests...\n"); 19 | char buf[1024]; 20 | char c = getpid() % 'a'; 21 | srand(time(0)); 22 | 23 | for (int i = 0; i < (int)sizeof(buf); i++) { 24 | buf[i] = (c + i) % 255; 25 | } 26 | 27 | uint32_t lens[] = {3, 4, 5, 7, 8, 16, 17, 24, 25, 32, 33, 127, 128, 28 | 255, 256, 257}; 29 | for (unsigned i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { 30 | string s(buf, lens[i]); 31 | uint32_t h = hash_sparse_sse42(rand(), s.c_str(), lens[i]); 32 | test_printf("%d", h); 33 | test_printf("%d", hash_dense_sse42(rand(), h, s.c_str(), lens[i])); 34 | } 35 | 36 | return true; 37 | } 38 | 39 | static bool 40 | verify_log2() 41 | { 42 | fprintf(stdout, "verify log2...\n"); 43 | bool err = false; 44 | std::map lm; 45 | lm[0] =(uint32_t)-1; 46 | lm[1] = 0; 47 | lm[2] = 1; 48 | for (int i = 2; i < 31; i++) { 49 | lm[(1<::iterator iter = lm.begin(), iter_e = lm.end(); 57 | iter != iter_e; ++iter) { 58 | uint32_t v = (*iter).first; 59 | uint32_t log2_expect = (*iter).second; 60 | uint32_t log2_get = log2_floor(v); 61 | if (log2_expect != log2_get) { 62 | err = true; 63 | fprintf(stderr, "log2(%u) expect %u, get %u\n", v, log2_expect, log2_get); 64 | exit(1); 65 | } 66 | } 67 | return !err; 68 | } 69 | 70 | int 71 | main(int argc, char** argv) 72 | { 73 | fprintf(stdout, "=======================\nRun unit testing...\n"); 74 | 75 | ASSERT(smoke_test(), "smoke_test test failed"); 76 | ASSERT(verify_log2(), "log2 failed"); 77 | 78 | fprintf(stdout, TestErrMsgMgr::noError() ? "succ\n\n" : "fail\n\n"); 79 | 80 | return TestErrMsgMgr::noError() ? 0 : -1; 81 | } 82 | -------------------------------------------------------------------------------- /src/x64/test/test_str_comp.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Given two content-idental string s1, s2, test if they end up to be the 3 | same string object. The purpose of this test is to make sure hash function 4 | do not accidently include extraneous bytes before and after the string in 5 | question. 6 | ]] 7 | 8 | local ffi = require("ffi") 9 | local C = ffi.C 10 | 11 | ffi.cdef[[ 12 | void free(void*); 13 | char* malloc(size_t); 14 | void *memset(void*, int, size_t); 15 | void *memcpy(void*, void*, size_t); 16 | long time(void*); 17 | void srandom(unsigned); 18 | long random(void); 19 | ]] 20 | 21 | 22 | local function test_equal(len_min, len_max) 23 | -- source string is wrapped by 16-byte-junk both before and after the 24 | -- string 25 | local x = C.random() 26 | local l = len_min + x % (len_max - len_min); 27 | local buf_len = tonumber(l + 16 * 2) 28 | 29 | local src_buf = C.malloc(buf_len) 30 | for i = 0, buf_len - 1 do 31 | src_buf[i] = C.random() % 255 32 | end 33 | 34 | -- dest string is the clone of the source string, but it is sandwiched 35 | -- by different junk bytes 36 | local dest_buf = C.malloc(buf_len) 37 | C.memset(dest_buf, 0x5a, buf_len) 38 | 39 | local ofst = 8 + (C.random() % 8) 40 | C.memcpy(dest_buf + ofst, src_buf + 16, l); 41 | 42 | local str1 = ffi.string(src_buf + 16, l) 43 | local str2 = ffi.string(dest_buf + ofst, l) 44 | 45 | C.free(src_buf) 46 | C.free(dest_buf) 47 | 48 | if str1 ~= str2 then 49 | -- Oops, look like hash function mistakenly include extraneous bytes 50 | -- close to the string 51 | return 1 -- wtf 52 | end 53 | end 54 | 55 | --local lens = {1, 4, 16, 128, 1024} 56 | local lens = {128, 1024} 57 | local iter = 1000 58 | 59 | for i = 1, #lens - 1 do 60 | for j = 1, iter do 61 | if test_equal(lens[i], lens[i+1]) ~= nil then 62 | os.exit(1) 63 | end 64 | end 65 | end 66 | 67 | os.exit(0) 68 | -------------------------------------------------------------------------------- /src/x64/test/test_util.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "test_util.hpp" 4 | 5 | using namespace std; 6 | 7 | std::vector TestErrMsgMgr::_errMsg; 8 | 9 | void 10 | test_printf(const char* format, ...) 11 | { 12 | va_list args; 13 | va_start (args, format); 14 | 15 | FILE* devNull = fopen("/dev/null", "w"); 16 | if (devNull != 0) { 17 | (void)vfprintf (devNull, format, args); 18 | } 19 | fclose(devNull); 20 | va_end (args); 21 | } 22 | -------------------------------------------------------------------------------- /src/x64/test/test_util.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _TEST_UTIL_HPP_ 2 | #define _TEST_UTIL_HPP_ 3 | 4 | #include // gettimeofday() 5 | #include 6 | #include 7 | 8 | struct TestErrMsg 9 | { 10 | const char* fileName; 11 | unsigned lineNo; 12 | std::string errMsg; 13 | 14 | TestErrMsg(const char* FN, unsigned LN, const char* Err): 15 | fileName(FN), lineNo(LN), errMsg(Err) {} 16 | }; 17 | 18 | class TestErrMsgMgr 19 | { 20 | public: 21 | static std::vector getError(); 22 | static void 23 | addError(const char* fileName, unsigned lineNo, const char* Err) { 24 | _errMsg.push_back(TestErrMsg(fileName, lineNo, Err)); 25 | } 26 | 27 | static bool noError() { 28 | return _errMsg.empty(); 29 | } 30 | 31 | private: 32 | static std::vector _errMsg; 33 | }; 34 | 35 | #define ASSERT(c, e) \ 36 | if (!(c)) { TestErrMsgMgr::addError(__FILE__, __LINE__, (e)); } 37 | 38 | class TestClock 39 | { 40 | public: 41 | void start() { gettimeofday(&_start, 0); } 42 | void stop() { gettimeofday(&_end, 0); } 43 | double getElapseInSecond() { 44 | return (_end.tv_sec - _start.tv_sec) 45 | + ((long)_end.tv_usec - (long)_start.tv_usec) / 1000000.0; 46 | } 47 | 48 | private: 49 | struct timeval _start, _end; 50 | }; 51 | 52 | // write to /dev/null, the only purpose is to make the data fed to the 53 | // function alive. 54 | extern void test_printf(const char* format, ...) 55 | __attribute__ ((format (printf, 1, 2))); 56 | 57 | #endif //_TEST_UTIL_HPP_ 58 | -------------------------------------------------------------------------------- /src/xb1build.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build LuaJIT with the Xbox One SDK. 2 | @rem Donated to the public domain. 3 | @rem 4 | @rem Open a "Visual Studio .NET Command Prompt" (64 bit host compiler) 5 | @rem Then cd to this directory and run this script. 6 | 7 | @if not defined INCLUDE goto :FAIL 8 | @if not defined DurangoXDK goto :FAIL 9 | 10 | @setlocal 11 | @echo ---- Host compiler ---- 12 | @set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE 13 | @set LJLINK=link /nologo 14 | @set LJMT=mt /nologo 15 | @set DASMDIR=..\dynasm 16 | @set DASM=%DASMDIR%\dynasm.lua 17 | @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c 18 | 19 | %LJCOMPILE% host\minilua.c 20 | @if errorlevel 1 goto :BAD 21 | %LJLINK% /out:minilua.exe minilua.obj 22 | @if errorlevel 1 goto :BAD 23 | if exist minilua.exe.manifest^ 24 | %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe 25 | 26 | @rem Error out for 64 bit host compiler 27 | @minilua 28 | @if not errorlevel 8 goto :FAIL 29 | 30 | @set DASMFLAGS=-D WIN -D FFI -D P64 31 | minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_x64.dasc 32 | @if errorlevel 1 goto :BAD 33 | 34 | if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt ) 35 | minilua host\genversion.lua 36 | 37 | %LJCOMPILE% /I "." /I %DASMDIR% /D_DURANGO host\buildvm*.c 38 | @if errorlevel 1 goto :BAD 39 | %LJLINK% /out:buildvm.exe buildvm*.obj 40 | @if errorlevel 1 goto :BAD 41 | if exist buildvm.exe.manifest^ 42 | %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe 43 | 44 | buildvm -m peobj -o lj_vm.obj 45 | @if errorlevel 1 goto :BAD 46 | buildvm -m bcdef -o lj_bcdef.h %ALL_LIB% 47 | @if errorlevel 1 goto :BAD 48 | buildvm -m ffdef -o lj_ffdef.h %ALL_LIB% 49 | @if errorlevel 1 goto :BAD 50 | buildvm -m libdef -o lj_libdef.h %ALL_LIB% 51 | @if errorlevel 1 goto :BAD 52 | buildvm -m recdef -o lj_recdef.h %ALL_LIB% 53 | @if errorlevel 1 goto :BAD 54 | buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB% 55 | @if errorlevel 1 goto :BAD 56 | buildvm -m folddef -o lj_folddef.h lj_opt_fold.c 57 | @if errorlevel 1 goto :BAD 58 | 59 | @echo ---- Cross compiler ---- 60 | 61 | @set CWD=%cd% 62 | @call "%DurangoXDK%\xdk\DurangoVars.cmd" XDK 63 | @cd /D "%CWD%" 64 | @shift 65 | 66 | @set LJCOMPILE="cl" /nologo /c /W3 /GF /Gm- /GR- /GS- /Gy /openmp- /D_CRT_SECURE_NO_DEPRECATE /D_LIB /D_UNICODE /D_DURANGO 67 | @set LJLIB="lib" /nologo 68 | 69 | @if "%1"=="debug" ( 70 | @shift 71 | @set LJCOMPILE=%LJCOMPILE% /Zi /MDd /Od 72 | @set LJLINK=%LJLINK% /debug 73 | ) else ( 74 | @set LJCOMPILE=%LJCOMPILE% /MD /O2 /DNDEBUG 75 | ) 76 | 77 | @if "%1"=="amalg" goto :AMALG 78 | %LJCOMPILE% /DLUA_BUILD_AS_DLL lj_*.c lib_*.c 79 | @if errorlevel 1 goto :BAD 80 | %LJLIB% /OUT:luajit.lib lj_*.obj lib_*.obj 81 | @if errorlevel 1 goto :BAD 82 | @goto :NOAMALG 83 | :AMALG 84 | %LJCOMPILE% /DLUA_BUILD_AS_DLL ljamalg.c 85 | @if errorlevel 1 goto :BAD 86 | %LJLIB% /OUT:luajit.lib ljamalg.obj lj_vm.obj 87 | @if errorlevel 1 goto :BAD 88 | :NOAMALG 89 | 90 | @del *.obj *.manifest minilua.exe buildvm.exe 91 | @echo. 92 | @echo === Successfully built LuaJIT for Xbox One === 93 | 94 | @goto :END 95 | :BAD 96 | @echo. 97 | @echo ******************************************************* 98 | @echo *** Build FAILED -- Please check the error messages *** 99 | @echo ******************************************************* 100 | @goto :END 101 | :FAIL 102 | @echo To run this script you must open a "Visual Studio .NET Command Prompt" 103 | @echo (64 bit host compiler). The Xbox One SDK must be installed, too. 104 | :END 105 | -------------------------------------------------------------------------------- /src/xedkbuild.bat: -------------------------------------------------------------------------------- 1 | @rem Script to build LuaJIT with the Xbox 360 SDK. 2 | @rem Donated to the public domain. 3 | @rem 4 | @rem Open a "Visual Studio .NET Command Prompt" (32 bit host compiler) 5 | @rem Then cd to this directory and run this script. 6 | 7 | @if not defined INCLUDE goto :FAIL 8 | @if not defined XEDK goto :FAIL 9 | 10 | @setlocal 11 | @rem ---- Host compiler ---- 12 | @set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE 13 | @set LJLINK=link /nologo 14 | @set LJMT=mt /nologo 15 | @set DASMDIR=..\dynasm 16 | @set DASM=%DASMDIR%\dynasm.lua 17 | @set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c 18 | 19 | %LJCOMPILE% host\minilua.c 20 | @if errorlevel 1 goto :BAD 21 | %LJLINK% /out:minilua.exe minilua.obj 22 | @if errorlevel 1 goto :BAD 23 | if exist minilua.exe.manifest^ 24 | %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe 25 | 26 | @rem Error out for 64 bit host compiler 27 | @minilua 28 | @if errorlevel 8 goto :FAIL 29 | 30 | @set DASMFLAGS=-D GPR64 -D FRAME32 -D PPE -D SQRT -D DUALNUM 31 | minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_ppc.dasc 32 | @if errorlevel 1 goto :BAD 33 | 34 | if exist ..\.git ( git show -s --format=%%ct >luajit_relver.txt ) else ( type ..\.relver >luajit_relver.txt ) 35 | minilua host\genversion.lua 36 | 37 | %LJCOMPILE% /I "." /I %DASMDIR% /D_XBOX_VER=200 /DLUAJIT_TARGET=LUAJIT_ARCH_PPC host\buildvm*.c 38 | @if errorlevel 1 goto :BAD 39 | %LJLINK% /out:buildvm.exe buildvm*.obj 40 | @if errorlevel 1 goto :BAD 41 | if exist buildvm.exe.manifest^ 42 | %LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe 43 | 44 | buildvm -m peobj -o lj_vm.obj 45 | @if errorlevel 1 goto :BAD 46 | buildvm -m bcdef -o lj_bcdef.h %ALL_LIB% 47 | @if errorlevel 1 goto :BAD 48 | buildvm -m ffdef -o lj_ffdef.h %ALL_LIB% 49 | @if errorlevel 1 goto :BAD 50 | buildvm -m libdef -o lj_libdef.h %ALL_LIB% 51 | @if errorlevel 1 goto :BAD 52 | buildvm -m recdef -o lj_recdef.h %ALL_LIB% 53 | @if errorlevel 1 goto :BAD 54 | buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB% 55 | @if errorlevel 1 goto :BAD 56 | buildvm -m folddef -o lj_folddef.h lj_opt_fold.c 57 | @if errorlevel 1 goto :BAD 58 | 59 | @rem ---- Cross compiler ---- 60 | @set LJCOMPILE="%XEDK%\bin\win32\cl" /nologo /c /MT /O2 /W3 /GF /Gm- /GR- /GS- /Gy /openmp- /D_CRT_SECURE_NO_DEPRECATE /DNDEBUG /D_XBOX /D_LIB /DLUAJIT_USE_SYSMALLOC 61 | @set LJLIB="%XEDK%\bin\win32\lib" /nologo 62 | @set "INCLUDE=%XEDK%\include\xbox" 63 | 64 | @if "%1" neq "debug" goto :NODEBUG 65 | @shift 66 | @set "LJCOMPILE=%LJCOMPILE% /Zi" 67 | :NODEBUG 68 | @if "%1"=="amalg" goto :AMALG 69 | %LJCOMPILE% /DLUA_BUILD_AS_DLL lj_*.c lib_*.c 70 | @if errorlevel 1 goto :BAD 71 | %LJLIB% /OUT:luajit20.lib lj_*.obj lib_*.obj 72 | @if errorlevel 1 goto :BAD 73 | @goto :NOAMALG 74 | :AMALG 75 | %LJCOMPILE% /DLUA_BUILD_AS_DLL ljamalg.c 76 | @if errorlevel 1 goto :BAD 77 | %LJLIB% /OUT:luajit20.lib ljamalg.obj lj_vm.obj 78 | @if errorlevel 1 goto :BAD 79 | :NOAMALG 80 | 81 | @del *.obj *.manifest minilua.exe buildvm.exe 82 | @echo. 83 | @echo === Successfully built LuaJIT for Xbox 360 === 84 | 85 | @goto :END 86 | :BAD 87 | @echo. 88 | @echo ******************************************************* 89 | @echo *** Build FAILED -- Please check the error messages *** 90 | @echo ******************************************************* 91 | @goto :END 92 | :FAIL 93 | @echo To run this script you must open a "Visual Studio .NET Command Prompt" 94 | @echo (32 bit host compiler). The Xbox 360 SDK must be installed, too. 95 | :END 96 | -------------------------------------------------------------------------------- /t/TestLJ.pm: -------------------------------------------------------------------------------- 1 | package t::TestLJ; 2 | 3 | use v5.10.1; 4 | use Test::Base -Base; 5 | use IPC::Run3; 6 | use Cwd qw( cwd ); 7 | use Test::LongString; 8 | use File::Temp qw( tempdir ); 9 | 10 | our @EXPORT = qw( run_tests ); 11 | 12 | $ENV{LUA_CPATH} = "../?.so;;"; 13 | $ENV{LUA_PATH} = "../lua/?.lua;;"; 14 | #$ENV{LUA_PATH} = ($ENV{LUA_PATH} || "" ) . ';' . getcwd . "/runtime/?.lua" . ';;'; 15 | 16 | my $cwd = cwd; 17 | 18 | sub run_test ($) { 19 | my $block = shift; 20 | #print $json_xs->pretty->encode(\@new_rows); 21 | #my $res = #print $json_xs->pretty->encode($res); 22 | my $name = $block->name; 23 | 24 | my $lua = $block->lua or 25 | die "No --- lua specified for test $name\n"; 26 | 27 | my $luafile = "test.lua"; 28 | 29 | { 30 | my $dir = tempdir "testlj_XXXXXXX", CLEANUP => 1; 31 | chdir $dir or die "$name - Cannot chdir to $dir: $!"; 32 | open my $fh, ">$luafile" 33 | or die "$name - Cannot open $luafile in $dir for writing: $!\n"; 34 | print $fh $lua; 35 | close $fh; 36 | } 37 | 38 | my ($res, $err); 39 | 40 | my @cmd; 41 | 42 | if ($ENV{TEST_LJ_USE_VALGRIND}) { 43 | warn "$name\n"; 44 | @cmd = ('valgrind', '-q', '--leak-check=full', 'luajit', 45 | defined($block->jv) ? '-jv' : (), 46 | defined($block->jdump) ? '-jdump' : (), 47 | $luafile); 48 | } else { 49 | @cmd = ('luajit', 50 | defined($block->jv) ? '-jv' : (), 51 | defined($block->jdump) ? '-jdump' : (), 52 | $luafile); 53 | } 54 | 55 | run3 \@cmd, undef, \$res, \$err; 56 | my $rc = $?; 57 | 58 | #warn "res:$res\nerr:$err\n"; 59 | 60 | my $exp_rc = $block->exit // 0; 61 | 62 | is $exp_rc, $rc >> 8, "$name - exit code okay"; 63 | 64 | my $exp_err = $block->err; 65 | if (defined $exp_err) { 66 | if ($err =~ /.*:.*:.*: (.*\s)?/) { 67 | $err = $1; 68 | } 69 | 70 | if (ref $exp_err) { 71 | like $err, $exp_err, "$name - err like expected"; 72 | 73 | } else { 74 | is $err, $exp_err, "$name - err expected"; 75 | } 76 | 77 | } elsif (defined $err && $err ne '') { 78 | warn "$name - STDERR:\n$err"; 79 | } 80 | 81 | if (defined $block->out) { 82 | #is $res, $block->out, "$name - output ok"; 83 | is $res, $block->out, "$name - output ok"; 84 | 85 | } elsif (defined $res && $res ne '') { 86 | warn "$name - STDOUT:\n$res"; 87 | } 88 | 89 | chdir $cwd or die $!; 90 | } 91 | 92 | sub run_tests () { 93 | for my $block (blocks()) { 94 | run_test($block); 95 | } 96 | } 97 | 98 | 1; 99 | -------------------------------------------------------------------------------- /t/exdata.t: -------------------------------------------------------------------------------- 1 | # vim: set ss=4 ft= sw=4 et sts=4 ts=4: 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: interpreted (sanity) 13 | --- lua 14 | jit.off() 15 | local assert = assert 16 | local exdata = require "thread.exdata" 17 | local ffi = require "ffi" 18 | local u64 = ffi.new("uintptr_t", 0xefdeaddeadbeefLL) 19 | local ptr = ffi.cast("void *", u64) 20 | local saved_q 21 | for i = 1, 5 do 22 | exdata(u64) 23 | local q = exdata() 24 | if saved_q then 25 | assert(q == saved_q) 26 | end 27 | saved_q = q 28 | end 29 | print(tostring(ptr)) 30 | print(tostring(saved_q)) 31 | --- jv 32 | --- out 33 | cdata: 0xefdeaddeadbeef 34 | cdata: 0xefdeaddeadbeef 35 | --- err 36 | 37 | 38 | 39 | === TEST 2: newly created coroutines should inherit the exdata 40 | --- lua 41 | jit.off() 42 | local exdata = require "thread.exdata" 43 | local ffi = require "ffi" 44 | local u64 = ffi.new("uintptr_t", 0xefdeadbeefLL) 45 | local ptr = ffi.cast("void *", u64) 46 | local ptr2 = ffi.cast("void *", u64 + 1) 47 | local ptr3 = ffi.cast("void *", u64 - 2) 48 | local saved_q 49 | local function f() 50 | coroutine.yield(exdata()) 51 | exdata(ptr2) 52 | coroutine.yield(exdata()) 53 | coroutine.yield(exdata()) 54 | end 55 | 56 | exdata(u64) 57 | 58 | local co = coroutine.create(f) 59 | 60 | local ok, data = coroutine.resume(co) 61 | assert(ok) 62 | print(tostring(data)) 63 | 64 | ok, data = coroutine.resume(co) 65 | assert(ok) 66 | print(tostring(data)) 67 | 68 | exdata(ptr3) 69 | 70 | ok, data = coroutine.resume(co) 71 | assert(ok) 72 | print(tostring(data)) 73 | 74 | print(tostring(exdata())) 75 | --- jv 76 | --- out 77 | cdata: 0xefdeadbeef 78 | cdata: 0xefdeadbef0 79 | cdata: 0xefdeadbef0 80 | cdata: 0xefdeadbeed 81 | --- err 82 | 83 | 84 | 85 | === TEST 3: JIT mode (reading) 86 | --- lua 87 | jit.opt.start("minstitch=100000", "hotloop=2") 88 | local assert = assert 89 | local exdata = require "thread.exdata" 90 | local ffi = require "ffi" 91 | local u64 = ffi.new("uintptr_t", 0xefdeaddeadbeefLL) 92 | local ptr = ffi.cast("void *", u64) 93 | local saved_q 94 | exdata(u64) 95 | for i = 1, 10 do 96 | local q = exdata() 97 | if saved_q then 98 | assert(q == saved_q) 99 | end 100 | saved_q = q 101 | end 102 | print(tostring(ptr)) 103 | print(tostring(saved_q)) 104 | 105 | --- jv 106 | --- out 107 | cdata: 0xefdeaddeadbeef 108 | cdata: 0xefdeaddeadbeef 109 | --- err 110 | [TRACE 1 test.lua:9 loop] 111 | 112 | 113 | 114 | === TEST 4: JIT mode (writing) 115 | --- lua 116 | jit.opt.start("minstitch=100000", "hotloop=2") 117 | local assert = assert 118 | local exdata = require "thread.exdata" 119 | local ffi = require "ffi" 120 | local u64 = ffi.new("uintptr_t", 0xefdeaddeadbeefLL) 121 | local ptr = ffi.cast("void *", u64) 122 | local saved_q 123 | for i = 1, 10 do 124 | exdata(u64) 125 | local q = exdata() 126 | if saved_q then 127 | assert(q == saved_q) 128 | end 129 | saved_q = q 130 | end 131 | print(tostring(ptr)) 132 | print(tostring(saved_q)) 133 | 134 | --- jv 135 | --- out 136 | cdata: 0xefdeaddeadbeef 137 | cdata: 0xefdeaddeadbeef 138 | --- err 139 | [TRACE --- test.lua:8 -- trace too short at test.lua:9] 140 | 141 | 142 | 143 | === TEST 5: interpreted - check the number of arguments 144 | --- lua 145 | jit.off() 146 | local assert = assert 147 | local select = select 148 | local exdata = require "thread.exdata" 149 | local ffi = require "ffi" 150 | local u64 = ffi.new("uintptr_t", 0xefdeaddeadbeefLL) 151 | local ptr = ffi.cast("void *", u64) 152 | 153 | local function nargs(...) 154 | return select('#', ...) 155 | end 156 | print(nargs(exdata(ptr))) 157 | print(nargs(exdata())) 158 | --- jv 159 | --- out 160 | 0 161 | 1 162 | --- err 163 | 164 | 165 | 166 | === TEST 6: JIT mode - check the number of arguments 167 | --- lua 168 | jit.opt.start("minstitch=100000", "hotloop=2") 169 | local assert = assert 170 | local select = select 171 | local exdata = require "thread.exdata" 172 | local ffi = require "ffi" 173 | local u64 = ffi.new("uintptr_t", 0xefdeaddeadbeefLL) 174 | local ptr = ffi.cast("void *", u64) 175 | 176 | local function nargs(...) 177 | return select('#', ...) 178 | end 179 | 180 | local total = 0 181 | for i = 1, 10 do 182 | total = total + nargs(exdata(ptr)) 183 | end 184 | 185 | print("set: " .. total) 186 | 187 | total = 0 188 | for i = 1, 10 do 189 | total = total + nargs(exdata()) 190 | end 191 | 192 | print("get: " .. total) 193 | --- jv 194 | --- out 195 | set: 0 196 | get: 10 197 | --- err 198 | [TRACE --- test.lua:14 -- trace too short at test.lua:15] 199 | [TRACE 1 test.lua:21 loop] 200 | 201 | 202 | 203 | === TEST 7: interpreted (no ffi initialized) 204 | --- lua 205 | jit.off() 206 | local assert = assert 207 | local exdata = require "thread.exdata" 208 | local saved_q 209 | for i = 1, 5 do 210 | local q = exdata() 211 | if saved_q then 212 | assert(q == saved_q) 213 | end 214 | saved_q = q 215 | end 216 | print(tostring(saved_q)) 217 | --- jv 218 | --- out 219 | --- err 220 | ffi module not loaded (yet) 221 | --- exit: 1 222 | 223 | 224 | 225 | === TEST 8: default value (interpreted) 226 | --- lua 227 | jit.off() 228 | local assert = assert 229 | require "ffi" 230 | local exdata = require "thread.exdata" 231 | local saved_q 232 | for i = 1, 5 do 233 | local q = exdata() 234 | if saved_q then 235 | assert(q == saved_q) 236 | end 237 | saved_q = q 238 | end 239 | print(saved_q == nil) 240 | print(tostring(saved_q)) 241 | --- jv 242 | --- out 243 | true 244 | cdata: NULL 245 | --- err 246 | 247 | 248 | 249 | === TEST 9: default value (JIT) 250 | --- lua 251 | jit.opt.start("minstitch=100000", "hotloop=2") 252 | jit.on() 253 | local assert = assert 254 | require "ffi" 255 | local exdata = require "thread.exdata" 256 | local saved_q 257 | for i = 1, 5 do 258 | local q = exdata() 259 | if saved_q then 260 | assert(q == saved_q) 261 | end 262 | saved_q = q 263 | end 264 | print(saved_q == nil) 265 | print(tostring(saved_q)) 266 | --- jv 267 | --- out 268 | true 269 | cdata: NULL 270 | --- err 271 | [TRACE 1 test.lua:7 loop] 272 | -------------------------------------------------------------------------------- /t/isarr-interp.t: -------------------------------------------------------------------------------- 1 | # vim:ft= 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: decimal boolean keys 13 | --- lua 14 | jit.off() 15 | local isarray = require "table.isarray" 16 | local a 17 | local t = { [3] = 3, [5.3] = 4 } 18 | for i = 1, 5 do 19 | a = isarray(t) 20 | end 21 | print(type(a), a) 22 | 23 | --- jv 24 | --- out 25 | boolean false 26 | --- err 27 | 28 | 29 | 30 | === TEST 2: discrete boolean keys 31 | --- lua 32 | jit.off() 33 | local isarray = require "table.isarray" 34 | local a 35 | local t = { [3] = "a", [5] = true } 36 | for i = 1, 5 do 37 | a = isarray(t) 38 | end 39 | print(type(a), a) 40 | 41 | --- jv 42 | --- out 43 | boolean true 44 | --- err 45 | 46 | 47 | 48 | === TEST 3: normal arrays 49 | --- lua 50 | jit.off() 51 | local isarray = require "table.isarray" 52 | local a 53 | local t = { "a", nil, true, 3.14 } 54 | for i = 1, 5 do 55 | a = isarray(t) 56 | end 57 | print(type(a), a) 58 | 59 | --- jv 60 | --- out 61 | boolean true 62 | --- err 63 | 64 | 65 | 66 | === TEST 4: empty table 67 | --- lua 68 | jit.off() 69 | local isarray = require "table.isarray" 70 | local a 71 | local t = {} 72 | for i = 1, 5 do 73 | a = isarray(t) 74 | end 75 | print(type(a), a) 76 | 77 | --- jv 78 | --- out 79 | boolean true 80 | --- err 81 | 82 | 83 | 84 | === TEST 5: boolean-like string keys only 85 | --- lua 86 | jit.off() 87 | local isarray = require "table.isarray" 88 | local a 89 | local t = { ["1"] = 3, ["2"] = 4 } 90 | for i = 1, 150 do 91 | a = isarray(t) 92 | end 93 | print(type(a), a) 94 | 95 | --- jv 96 | --- out 97 | boolean false 98 | --- err 99 | 100 | 101 | 102 | === TEST 6: non-boolean-like string keys only 103 | --- lua 104 | jit.off() 105 | local isarray = require "table.isarray" 106 | local a 107 | local t = { ["dog"] = 3, ["cat"] = 4 } 108 | for i = 1, 150 do 109 | a = isarray(t) 110 | end 111 | print(type(a), a) 112 | 113 | --- jv 114 | --- out 115 | boolean false 116 | --- err 117 | 118 | 119 | 120 | === TEST 7: empty hash part 121 | --- lua 122 | jit.off() 123 | local isarray = require "table.isarray" 124 | local a 125 | local t = require "table.new"(0, 20) 126 | for i = 1, 5 do 127 | a = isarray(t) 128 | end 129 | print(type(a), a) 130 | 131 | --- jv 132 | --- out 133 | boolean true 134 | --- err 135 | 136 | 137 | 138 | === TEST 8: mixing int keys and string keys 139 | --- lua 140 | jit.off() 141 | local isarray = require "table.isarray" 142 | local a 143 | local t = { "dog", "cat", true, ["bird"] = 3 } 144 | for i = 1, 5 do 145 | a = isarray(t) 146 | end 147 | print(type(a), a) 148 | 149 | --- jv 150 | --- out 151 | boolean false 152 | --- err 153 | -------------------------------------------------------------------------------- /t/isarr-jit.t: -------------------------------------------------------------------------------- 1 | # vim:ft= 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: decimal boolean keys 13 | --- lua 14 | require "jit.opt".start("hotloop=3") 15 | local isarray = require "table.isarray" 16 | local a 17 | local t = { [3] = 3, [5.3] = 4 } 18 | for i = 1, 5 do 19 | a = isarray(t) 20 | end 21 | print(type(a), a) 22 | 23 | --- jv 24 | --- out 25 | boolean false 26 | --- err 27 | [TRACE 1 test.lua:5 loop] 28 | 29 | 30 | 31 | === TEST 2: discrete boolean keys 32 | --- lua 33 | require "jit.opt".start("hotloop=3") 34 | local isarray = require "table.isarray" 35 | local a 36 | local t = { [3] = "a", [5] = true } 37 | for i = 1, 5 do 38 | a = isarray(t) 39 | end 40 | print(type(a), a) 41 | 42 | --- jv 43 | --- out 44 | boolean true 45 | --- err 46 | [TRACE 1 test.lua:5 loop] 47 | 48 | 49 | 50 | === TEST 3: normal arrays 51 | --- lua 52 | require "jit.opt".start("hotloop=3") 53 | local isarray = require "table.isarray" 54 | local a 55 | local t = { "a", nil, true, 3.14 } 56 | for i = 1, 5 do 57 | a = isarray(t) 58 | end 59 | print(type(a), a) 60 | 61 | --- jv 62 | --- out 63 | boolean true 64 | --- err 65 | [TRACE 1 test.lua:5 loop] 66 | 67 | 68 | 69 | === TEST 4: empty table 70 | --- lua 71 | require "jit.opt".start("hotloop=3") 72 | local isarray = require "table.isarray" 73 | local a 74 | local t = {} 75 | for i = 1, 5 do 76 | a = isarray(t) 77 | end 78 | print(type(a), a) 79 | 80 | --- jv 81 | --- out 82 | boolean true 83 | --- err 84 | [TRACE 1 test.lua:5 loop] 85 | 86 | 87 | 88 | === TEST 5: boolean-like string keys only 89 | --- lua 90 | require "jit.opt".start("hotloop=3") 91 | local isarray = require "table.isarray" 92 | local a 93 | local t = { ["1"] = 3, ["2"] = 4 } 94 | for i = 1, 150 do 95 | a = isarray(t) 96 | end 97 | print(type(a), a) 98 | 99 | --- jv 100 | --- out 101 | boolean false 102 | --- err 103 | [TRACE 1 test.lua:5 loop] 104 | 105 | 106 | 107 | === TEST 6: non-boolean-like string keys only 108 | --- lua 109 | require "jit.opt".start("hotloop=3") 110 | local isarray = require "table.isarray" 111 | local a 112 | local t = { ["dog"] = 3, ["cat"] = 4 } 113 | for i = 1, 150 do 114 | a = isarray(t) 115 | end 116 | print(type(a), a) 117 | 118 | --- jv 119 | --- out 120 | boolean false 121 | --- err 122 | [TRACE 1 test.lua:5 loop] 123 | 124 | 125 | 126 | === TEST 7: empty hash part 127 | --- lua 128 | require "jit.opt".start("hotloop=3") 129 | local isarray = require "table.isarray" 130 | local a 131 | local t = require "table.new"(0, 20) 132 | for i = 1, 5 do 133 | a = isarray(t) 134 | end 135 | print(type(a), a) 136 | 137 | --- jv 138 | --- out 139 | boolean true 140 | --- err 141 | [TRACE 1 test.lua:5 loop] 142 | 143 | 144 | 145 | === TEST 8: mixing int keys and string keys 146 | --- lua 147 | require "jit.opt".start("hotloop=3") 148 | local isarray = require "table.isarray" 149 | local a 150 | local t = { "dog", "cat", true, ["bird"] = 3 } 151 | for i = 1, 5 do 152 | a = isarray(t) 153 | end 154 | print(type(a), a) 155 | 156 | --- jv 157 | --- out 158 | boolean false 159 | --- err 160 | [TRACE 1 test.lua:5 loop] 161 | 162 | 163 | 164 | === TEST 9: last table is an array 165 | --- lua 166 | require "jit.opt".start("hotloop=3") 167 | local isarray = require "table.isarray" 168 | local a 169 | local t = { "dog", "cat", true, ["bird"] = 3 } 170 | local ts = { t, t, t, t, t, {1, 2} } 171 | for i = 1, 6 do 172 | a = isarray(ts[i]) 173 | end 174 | print(type(a), a) 175 | 176 | --- jv 177 | --- out 178 | boolean true 179 | --- err 180 | [TRACE 1 test.lua:6 loop] 181 | -------------------------------------------------------------------------------- /t/isempty.t: -------------------------------------------------------------------------------- 1 | # vim:ft= 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: empty tables - interpreted 13 | --- lua 14 | jit.off() 15 | local new_tab = require "table.new" 16 | local isempty = require "table.isempty" 17 | local list = { 18 | {}, 19 | new_tab(5, 6), 20 | { nil }, 21 | { dogs = nil }, 22 | } 23 | for i, t in ipairs(list) do 24 | assert(isempty(t)) 25 | end 26 | print("ok") 27 | 28 | --- jv 29 | --- out 30 | ok 31 | --- err 32 | 33 | 34 | 35 | === TEST 2: empty tables - JIT 36 | --- lua 37 | jit.on() 38 | require "jit.opt".start("hotloop=3") 39 | local new_tab = require "table.new" 40 | local isempty = require "table.isempty" 41 | local list = { 42 | {}, 43 | new_tab(5, 6), 44 | { nil }, 45 | { dogs = nil }, 46 | } 47 | for i, t in ipairs(list) do 48 | for i = 1, 10 do 49 | assert(isempty(t)) 50 | end 51 | end 52 | print("ok") 53 | 54 | --- jv 55 | --- out 56 | ok 57 | --- err 58 | [TRACE 1 test.lua:12 loop] 59 | [TRACE 2 test.lua:11 -> 1] 60 | 61 | 62 | 63 | === TEST 3: non-empty tables - interpreted 64 | --- lua 65 | jit.off() 66 | local new_tab = require "table.new" 67 | local isempty = require "table.isempty" 68 | local list = { 69 | { 3.1 }, 70 | { "a", "b" }, 71 | { nil, false }, 72 | { dogs = 3 }, 73 | { dogs = 3, cats = 4 }, 74 | { dogs = 3, 5 }, 75 | } 76 | for i, t in ipairs(list) do 77 | assert(not isempty(t)) 78 | end 79 | print("ok") 80 | 81 | --- jv 82 | --- out 83 | ok 84 | --- err 85 | 86 | 87 | 88 | === TEST 4: non-empty tables - JIT 89 | --- lua 90 | jit.on() 91 | require "jit.opt".start("hotloop=3") 92 | local new_tab = require "table.new" 93 | local isempty = require "table.isempty" 94 | local list = { 95 | { 3.1 }, 96 | { "a", "b" }, 97 | { nil, false }, 98 | { dogs = 3 }, 99 | { dogs = 3, cats = 4 }, 100 | { dogs = 3, 5 }, 101 | } 102 | for i, t in ipairs(list) do 103 | for i = 1, 10 do 104 | assert(not isempty(t)) 105 | end 106 | end 107 | print("ok") 108 | 109 | --- jv 110 | --- out 111 | ok 112 | --- err 113 | [TRACE 1 test.lua:14 loop] 114 | [TRACE 2 test.lua:13 -> 1] 115 | -------------------------------------------------------------------------------- /t/iter.t: -------------------------------------------------------------------------------- 1 | # vim: set ss=4 ft= sw=4 et sts=4 ts=4: 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: pairs() loop jit 13 | --- jv 14 | --- lua 15 | jit.opt.start("minstitch=1", "hotloop=2") 16 | local tb = {} 17 | for i = 1, 100 do 18 | local s = "a" .. i 19 | tb[s] = i 20 | end 21 | local total = 0 22 | for k, v in pairs(tb) do 23 | total = total + tb[k] 24 | end 25 | print("total = " .. total) 26 | --- out 27 | total = 5050 28 | --- err eval 29 | qr#\Q[TRACE 1 test.lua:3 loop] 30 | [TRACE 2 test.lua:8 loop] 31 | \E(\Q[TRACE 3 (2/1) test.lua:8 stitch print] 32 | \E)?#ms 33 | 34 | 35 | 36 | === TEST 2: explicit next() in loops 37 | --- jv 38 | --- lua 39 | jit.opt.start("minstitch=1", "hotloop=2") 40 | local tb = {} 41 | for i = 1, 100 do 42 | local s = "a" .. i 43 | tb[s] = i 44 | end 45 | local function f(tb, k) 46 | if not next(tb) then 47 | return nil 48 | end 49 | -- print("k = " .. k) 50 | return k, tb["a" .. k] 51 | end 52 | local total = 0 53 | for i = 1, 100 do 54 | local k, v = f(tb, i) 55 | if not v then 56 | break 57 | end 58 | total = total + v 59 | end 60 | print("total = " .. total) 61 | --- out 62 | total = 5050 63 | --- err 64 | [TRACE 1 test.lua:3 loop] 65 | [TRACE 2 test.lua:15 loop] 66 | 67 | 68 | 69 | === TEST 3: custom lua iterator 70 | --- jv 71 | --- lua 72 | jit.opt.start("minstitch=1", "hotloop=2") 73 | local tb = {} 74 | for i = 1, 100 do 75 | local s = "a" .. i 76 | tb[s] = i 77 | end 78 | local iter 79 | function iter2(tb, k) 80 | if k >= 100 then 81 | return nil 82 | end 83 | return k + 1, tb["a" .. (k + 1)] 84 | end 85 | 86 | function iter(tb, k) 87 | -- print("tb = " .. tostring(tb)) 88 | -- print("key = " .. tostring(k)) 89 | if k == nil then 90 | return iter2, tb, 0 91 | end 92 | error("bad") 93 | end 94 | local total = 0 95 | for k, v in iter(tb) do 96 | if not v then 97 | print("value is nil for key " .. tostring(k)) 98 | end 99 | total = total + v 100 | end 101 | print("total = " .. total) 102 | --- out 103 | total = 5050 104 | --- err 105 | [TRACE 1 test.lua:3 loop] 106 | [TRACE 2 test.lua:24 loop] 107 | -------------------------------------------------------------------------------- /t/nkeys.t: -------------------------------------------------------------------------------- 1 | # vim: set ss=4 ft= sw=4 et sts=4 ts=4: 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: hash table, interpreted 13 | --- lua 14 | jit.off() 15 | local new_tab = require "table.new" 16 | local assert = assert 17 | local nkeys = require "table.nkeys" 18 | print(nkeys(new_tab(0, 4))) 19 | print(nkeys({})) 20 | print(nkeys({ cats = 4 })) 21 | print(nkeys({ dogs = 3, cats = 4 })) 22 | print(nkeys({ dogs = nil, cats = 4 })) 23 | --- jv 24 | --- out 25 | 0 26 | 0 27 | 1 28 | 2 29 | 1 30 | --- err 31 | 32 | 33 | 34 | === TEST 2: hash table, JIT 35 | --- lua 36 | jit.on() 37 | jit.opt.start("minstitch=100000", "hotloop=2") 38 | 39 | local new_tab = require "table.new" 40 | local assert = assert 41 | local nkeys = require "table.nkeys" 42 | 43 | local list = { 44 | new_tab(0, 4), 45 | {}, 46 | { cats = 4 }, 47 | { dogs = 3, cats = 4 }, 48 | { dogs = nil, cats = 4 }, 49 | } 50 | 51 | for i, t in ipairs(list) do 52 | local total = 0 53 | for i = 1, 10 do 54 | total = total + nkeys(t) 55 | end 56 | print(total) 57 | end 58 | --- jv 59 | --- out 60 | 0 61 | 0 62 | 10 63 | 20 64 | 10 65 | --- err 66 | [TRACE 1 test.lua:18 loop] 67 | [TRACE 2 test.lua:16 -> 1] 68 | 69 | 70 | 71 | === TEST 3: pure arrays, interpreted 72 | --- lua 73 | jit.off() 74 | local new_tab = require "table.new" 75 | local assert = assert 76 | local nkeys = require "table.nkeys" 77 | print(nkeys(new_tab(5, 0))) 78 | print(nkeys({})) 79 | print(nkeys({ "cats" })) 80 | print(nkeys({ "dogs", 3, "cats", 4 })) 81 | print(nkeys({ "dogs", nil, "cats", 4 })) 82 | --- jv 83 | --- out 84 | 0 85 | 0 86 | 1 87 | 4 88 | 3 89 | --- err 90 | 91 | 92 | 93 | === TEST 4: pure array, JIT 94 | --- lua 95 | jit.on() 96 | jit.opt.start("minstitch=100000", "hotloop=2") 97 | 98 | local new_tab = require "table.new" 99 | local assert = assert 100 | local nkeys = require "table.nkeys" 101 | 102 | local list = { 103 | new_tab(0, 4), 104 | {}, 105 | { 3 }, 106 | { "cats", 4 }, 107 | { "dogs", 3, "cats", 4 }, 108 | { "dogs", nil, "cats", 4 }, 109 | } 110 | 111 | for i, t in ipairs(list) do 112 | local total = 0 113 | for i = 1, 10 do 114 | total = total + nkeys(t) 115 | end 116 | print(total) 117 | end 118 | --- jv 119 | --- out 120 | 0 121 | 0 122 | 10 123 | 20 124 | 40 125 | 30 126 | --- err 127 | [TRACE 1 test.lua:19 loop] 128 | [TRACE 2 test.lua:17 -> 1] 129 | 130 | 131 | 132 | === TEST 5: mixing array and hash table, interpreted 133 | --- lua 134 | jit.off() 135 | local new_tab = require "table.new" 136 | local assert = assert 137 | local nkeys = require "table.nkeys" 138 | print(nkeys({ cats = 4, 5, 6 })) 139 | print(nkeys({ nil, "foo", dogs = 3, cats = 4 })) 140 | --- jv 141 | --- out 142 | 3 143 | 3 144 | --- err 145 | 146 | 147 | 148 | === TEST 6: mixing array & hash, JIT 149 | --- lua 150 | jit.on() 151 | jit.opt.start("minstitch=100000", "hotloop=2") 152 | 153 | local new_tab = require "table.new" 154 | local assert = assert 155 | local nkeys = require "table.nkeys" 156 | 157 | local list = { 158 | { cats = 4, 5, 6 }, 159 | { nil, "foo", dogs = 3, cats = 4 }, 160 | } 161 | 162 | for i, t in ipairs(list) do 163 | local total = 0 164 | for i = 1, 10 do 165 | total = total + nkeys(t) 166 | end 167 | print(total) 168 | end 169 | --- jv 170 | --- out 171 | 30 172 | 30 173 | --- err 174 | [TRACE 1 test.lua:15 loop] 175 | [TRACE 2 test.lua:13 -> 1] 176 | -------------------------------------------------------------------------------- /t/prngstate.t: -------------------------------------------------------------------------------- 1 | # vim: set ss=4 ft= sw=4 et sts=4 ts=4: 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: interpreted (sanity) 13 | --- lua 14 | jit.off() 15 | 16 | function print_array(a) 17 | local out = a[1] 18 | for i=2,#a do 19 | out = out.." "..tostring(a[i]) 20 | end 21 | print(out) 22 | end 23 | 24 | jit.prngstate({32}) 25 | print_array(jit.prngstate({56,1,7})) 26 | print_array(jit.prngstate({423,432,432,423,56,867,35,5347})) 27 | print_array(jit.prngstate()) 28 | print_array(jit.prngstate({423,432,432,423,56,867,35,5347,452})) 29 | --- out 30 | 32 0 0 0 0 0 0 0 31 | 56 1 7 0 0 0 0 0 32 | 423 432 432 423 56 867 35 5347 33 | --- jv 34 | --- err 35 | bad argument #1 to 'prngstate' (PRNG state must be an array with up to 8 integers or an integer) 36 | --- exit: 1 37 | 38 | 39 | 40 | === TEST 2: JIT (set) 41 | --- lua 42 | jit.opt.start("minstitch=100000", "hotloop=2") 43 | 44 | for i = 1, 50 do 45 | jit.prngstate({i}) 46 | end 47 | print('ok') 48 | --- out 49 | ok 50 | --- jv 51 | --- err eval 52 | qr/trace too short at test.lua:4/ 53 | 54 | 55 | 56 | === TEST 3: PRNG state can be an integer 57 | --- lua 58 | function print_array(a) 59 | local out = a[1] 60 | for i=2,#a do 61 | out = out.." "..tostring(a[i]) 62 | end 63 | print(out) 64 | end 65 | 66 | jit.prngstate(0) 67 | print_array(jit.prngstate(30)) 68 | print_array(jit.prngstate(32)) 69 | print_array(jit.prngstate(4294967296)) -- 2 ** 32 70 | --- out 71 | 0 0 0 0 0 0 0 0 72 | 30 0 0 0 0 0 0 0 73 | --- jv 74 | --- err 75 | bad argument #1 to 'prngstate' (PRNG state must be an array with up to 8 integers or an integer) 76 | --- exit: 1 77 | -------------------------------------------------------------------------------- /t/table-clone.t: -------------------------------------------------------------------------------- 1 | # vim:ft= 2 | 3 | use lib '.'; 4 | use t::TestLJ; 5 | 6 | plan tests => 3 * blocks(); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: clone table 13 | --- lua 14 | jit.off() 15 | local clone = require "table.clone" 16 | local t = { 17 | k = { 18 | a = 1, 19 | b = 2, 20 | }, 21 | } 22 | 23 | local t1 = clone(t) 24 | assert(type(t1.k) == "table") 25 | print("ok") 26 | 27 | --- jv 28 | --- out 29 | ok 30 | --- err 31 | 32 | 33 | 34 | === TEST 2: empty tables - JIT 35 | --- lua 36 | jit.on() 37 | require "jit.opt".start("hotloop=3") 38 | local clone = require "table.clone" 39 | local t = { 40 | k = { 41 | a = 1, 42 | b = 2, 43 | }, 44 | } 45 | 46 | for i = 1, 10 do 47 | local t1 = clone(t) 48 | assert(type(t1) == "table") 49 | end 50 | print("ok") 51 | 52 | --- jv 53 | --- out 54 | ok 55 | --- err 56 | [TRACE 1 test.lua:11 loop] 57 | --------------------------------------------------------------------------------