Browse Source

RELEASE LuaJIT-2.0.0-beta2

Mike Pall 15 years ago
parent
commit
3e30b4475e
46 changed files with 1238 additions and 390 deletions
  1. 56 0
      COPYRIGHT
  2. 76 20
      Makefile
  3. 2 2
      README
  4. 141 6
      doc/api.html
  5. 31 1
      doc/changes.html
  6. 23 0
      doc/faq.html
  7. 33 26
      doc/install.html
  8. 3 3
      doc/running.html
  9. 18 3
      doc/status.html
  10. 82 0
      etc/luajit.1
  11. 24 0
      etc/luajit.pc
  12. 216 106
      src/Makefile
  13. 2 2
      src/Makefile.dep
  14. 2 5
      src/buildvm_asm.c
  15. 6 1
      src/buildvm_fold.c
  16. 2 1
      src/buildvm_peobj.c
  17. 110 1
      src/buildvm_x86.dasc
  18. 5 91
      src/lib_aux.c
  19. 6 3
      src/lib_io.c
  20. 3 2
      src/lib_jit.c
  21. 4 15
      src/lib_math.c
  22. 1 0
      src/lib_package.c
  23. 5 2
      src/lib_string.c
  24. 12 12
      src/lib_table.c
  25. 134 2
      src/lj_api.c
  26. 7 4
      src/lj_asm.c
  27. 15 2
      src/lj_dispatch.c
  28. 46 0
      src/lj_err.c
  29. 4 0
      src/lj_errmsg.h
  30. 1 1
      src/lj_func.c
  31. 1 2
      src/lj_gc.c
  32. 1 0
      src/lj_ir.c
  33. 9 0
      src/lj_lib.h
  34. 2 1
      src/lj_obj.h
  35. 4 4
      src/lj_opt_fold.c
  36. 1 1
      src/lj_opt_loop.c
  37. 2 2
      src/lj_opt_mem.c
  38. 62 8
      src/lj_record.c
  39. 2 2
      src/lj_tab.c
  40. 48 34
      src/lj_trace.c
  41. 1 1
      src/lj_trace.h
  42. 3 3
      src/lj_vm.h
  43. 4 4
      src/lua.hpp
  44. 12 3
      src/luaconf.h
  45. 10 10
      src/luajit.c
  46. 6 4
      src/luajit.h

+ 56 - 0
COPYRIGHT

@@ -0,0 +1,56 @@
+===============================================================================
+LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
+
+Copyright (C) 2005-2009 Mike Pall. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+
+===============================================================================
+[ LuaJIT includes code from Lua 5.1, which has this license statement: ]
+
+Copyright (C) 1994-2008 Lua.org, PUC-Rio.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+[ LuaJIT includes code from dlmalloc, which has this license statement: ]
+
+This is a version (aka dlmalloc) of malloc/free/realloc written by
+Doug Lea and released to the public domain, as explained at
+http://creativecommons.org/licenses/publicdomain
+
+===============================================================================

+ 76 - 20
Makefile

@@ -12,46 +12,104 @@
 # Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
 # Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
 ##############################################################################
 ##############################################################################
 
 
-BASEVER= 2.0.0
-VERSION= 2.0.0-beta1
+MAJVER=  2
+MINVER=  0
+RELVER=  0
+PREREL=  -beta2
+VERSION= $(MAJVER).$(MINVER).$(RELVER)$(PREREL)
+ABIVER=  5.1
+NODOTABIVER=  51
 
 
 ##############################################################################
 ##############################################################################
 #
 #
 # Change the installation path as needed and modify src/luaconf.h accordingly.
 # Change the installation path as needed and modify src/luaconf.h accordingly.
 # Note: PREFIX must be an absolute path!
 # Note: PREFIX must be an absolute path!
 #
 #
-PREFIX= /usr/local
+export PREFIX= /usr/local
 ##############################################################################
 ##############################################################################
 
 
-INSTALL_BIN= $(PREFIX)/bin
-INSTALL_NAME= luajit-$(VERSION)
-INSTALL_T= $(INSTALL_BIN)/$(INSTALL_NAME)
-INSTALL_TSYM= $(INSTALL_BIN)/luajit
-INSTALL_INC= $(PREFIX)/include/luajit-$(BASEVER)
-INSTALL_JITLIB= $(PREFIX)/share/luajit-$(VERSION)/jit
-
+DPREFIX= $(DESTDIR)$(PREFIX)
+INSTALL_BIN=   $(DPREFIX)/bin
+INSTALL_LIB=   $(DPREFIX)/lib
+INSTALL_SHARE= $(DPREFIX)/share
+INSTALL_INC=   $(DPREFIX)/include/luajit-$(MAJVER).$(MINVER)
+
+INSTALL_JITLIB= $(INSTALL_SHARE)/luajit-$(VERSION)/jit
+INSTALL_LMOD= $(INSTALL_SHARE)/lua/$(ABIVER)
+INSTALL_CMOD= $(INSTALL_LIB)/lua/$(ABIVER)
+INSTALL_MAN= $(INSTALL_SHARE)/man/man1
+INSTALL_PKGCONFIG= $(INSTALL_LIB)/pkgconfig
+
+INSTALL_TNAME= luajit-$(VERSION)
+INSTALL_TSYMNAME= luajit
+INSTALL_ANAME= libluajit-$(ABIVER).a
+INSTALL_SONAME= libluajit-$(ABIVER).so.$(MAJVER).$(MINVER).$(RELVER)
+INSTALL_SOSHORT= libluajit-$(ABIVER).so
+INSTALL_DYLIBNAME= libluajit-$(NODOTABIVER).$(MAJVER).$(MINVER).$(RELVER).dylib
+INSTALL_DYLIBSHORT1= libluajit-$(NODOTABIVER).dylib
+INSTALL_DYLIBSHORT2= libluajit-$(NODOTABIVER).$(MAJVER).dylib
+INSTALL_PCNAME= luajit.pc
+
+INSTALL_STATIC= $(INSTALL_LIB)/$(INSTALL_ANAME)
+INSTALL_DYN= $(INSTALL_LIB)/$(INSTALL_SONAME)
+INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_SOSHORT)
+INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_SOSHORT)
+INSTALL_T= $(INSTALL_BIN)/$(INSTALL_TNAME)
+INSTALL_TSYM= $(INSTALL_BIN)/$(INSTALL_TSYMNAME)
+INSTALL_PC= $(INSTALL_PKGCONFIG)/$(INSTALL_PCNAME)
+
+INSTALL_DIRS= $(INSTALL_BIN) $(INSTALL_LIB) $(INSTALL_INC) $(INSTALL_MAN) \
+  $(INSTALL_PKGCONFIG) $(INSTALL_JITLIB) $(INSTALL_LMOD) $(INSTALL_CMOD)
+
+RM= rm -f
 MKDIR= mkdir -p
 MKDIR= mkdir -p
-SYMLINK= ln -f -s
+SYMLINK= ln -sf
 INSTALL_X= install -m 0755
 INSTALL_X= install -m 0755
 INSTALL_F= install -m 0644
 INSTALL_F= install -m 0644
-
-FILES_T= luajit
+LDCONFIG= ldconfig -n
+SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|"
+
+FILE_T= luajit
+FILE_A= libluajit.a
+FILE_SO= libluajit.so
+FILE_MAN= luajit.1
+FILE_PC= luajit.pc
 FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
 FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
 FILES_JITLIB= bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua vmdef.lua
 FILES_JITLIB= bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua vmdef.lua
 
 
+ifeq (,$(findstring Windows,$(OS)))
+  ifeq (Darwin,$(shell uname -s))
+    INSTALL_SONAME= $(INSTALL_DYLIBNAME)
+    INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_DYLIBSHORT1)
+    INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_DYLIBSHORT2)
+    LDCONFIG= :
+  endif
+endif
+
 ##############################################################################
 ##############################################################################
 
 
 INSTALL_DEP= src/luajit
 INSTALL_DEP= src/luajit
 
 
-all $(INSTALL_DEP):
+default all $(INSTALL_DEP):
 	@echo "==== Building LuaJIT $(VERSION) ===="
 	@echo "==== Building LuaJIT $(VERSION) ===="
 	$(MAKE) -C src
 	$(MAKE) -C src
 	@echo "==== Successfully built LuaJIT $(VERSION) ===="
 	@echo "==== Successfully built LuaJIT $(VERSION) ===="
 
 
 install: $(INSTALL_DEP)
 install: $(INSTALL_DEP)
 	@echo "==== Installing LuaJIT $(VERSION) to $(PREFIX) ===="
 	@echo "==== Installing LuaJIT $(VERSION) to $(PREFIX) ===="
-	$(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_JITLIB)
-	cd src && $(INSTALL_X) $(FILES_T) $(INSTALL_T)
+	$(MKDIR) $(INSTALL_DIRS)
+	cd src && $(INSTALL_X) $(FILE_T) $(INSTALL_T)
+	cd src && test -f $(FILE_A) && $(INSTALL_F) $(FILE_A) $(INSTALL_STATIC) || :
+	$(RM) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2)
+	cd src && test -f $(FILE_SO) && \
+	  $(INSTALL_F) $(FILE_SO) $(INSTALL_DYN) && \
+	  $(LDCONFIG) $(INSTALL_LIB) && \
+	  $(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT1) && \
+	  $(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT2) || :
+	cd etc && $(INSTALL_F) $(FILE_MAN) $(INSTALL_MAN)
+	cd etc && $(SED_PC) $(FILE_PC) > $(FILE_PC).tmp && \
+	  $(INSTALL_F) $(FILE_PC).tmp $(INSTALL_PC) && \
+	  $(RM) $(FILE_PC).tmp
 	cd src && $(INSTALL_F) $(FILES_INC) $(INSTALL_INC)
 	cd src && $(INSTALL_F) $(FILES_INC) $(INSTALL_INC)
 	cd lib && $(INSTALL_F) $(FILES_JITLIB) $(INSTALL_JITLIB)
 	cd lib && $(INSTALL_F) $(FILES_JITLIB) $(INSTALL_JITLIB)
 	@echo "==== Successfully installed LuaJIT $(VERSION) to $(PREFIX) ===="
 	@echo "==== Successfully installed LuaJIT $(VERSION) to $(PREFIX) ===="
@@ -59,7 +117,7 @@ install: $(INSTALL_DEP)
 	@echo "Note: the beta releases deliberately do NOT install a symlink for luajit"
 	@echo "Note: the beta releases deliberately do NOT install a symlink for luajit"
 	@echo "You can do this now by running this command (with sudo):"
 	@echo "You can do this now by running this command (with sudo):"
 	@echo ""
 	@echo ""
-	@echo "  $(SYMLINK) $(INSTALL_NAME) $(INSTALL_TSYM)"
+	@echo "  $(SYMLINK) $(INSTALL_TNAME) $(INSTALL_TSYM)"
 	@echo ""
 	@echo ""
 
 
 ##############################################################################
 ##############################################################################
@@ -77,8 +135,6 @@ cleaner:
 distclean:
 distclean:
 	$(MAKE) -C src distclean
 	$(MAKE) -C src distclean
 
 
-SUB_TARGETS= amalg clean cleaner distclean
-
-.PHONY: all install $(SUB_TARGETS)
+.PHONY: all install amalg clean cleaner distclean
 
 
 ##############################################################################
 ##############################################################################

+ 2 - 2
README

@@ -1,4 +1,4 @@
-README for LuaJIT 2.0.0-beta1
+README for LuaJIT 2.0.0-beta2
 -----------------------------
 -----------------------------
 
 
 LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
 LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
@@ -7,7 +7,7 @@ Project Homepage: http://luajit.org/
 
 
 LuaJIT is Copyright (C) 2005-2009 Mike Pall.
 LuaJIT is Copyright (C) 2005-2009 Mike Pall.
 LuaJIT is free software, released under the MIT/X license.
 LuaJIT is free software, released under the MIT/X license.
-See full Copyright Notice in src/luajit.h
+See full Copyright Notice in the COPYRIGHT file or in luajit.h.
 
 
 Documentation for LuaJIT is available in HTML format.
 Documentation for LuaJIT is available in HTML format.
 Please point your favorite browser to:
 Please point your favorite browser to:

+ 141 - 6
doc/api.html

@@ -100,12 +100,6 @@ These functions are typically used with the command line options
 Flushes the whole cache of compiled code.
 Flushes the whole cache of compiled code.
 </p>
 </p>
 
 
-<h3 id="jit_flush_tr"><tt>jit.flush(tr)</tt></h3>
-<p>
-Flushes the code for the specified root trace and all of its
-side traces from the cache.
-</p>
-
 <h3 id="jit_onoff_func"><tt>jit.on(func|true [,true|false])<br>
 <h3 id="jit_onoff_func"><tt>jit.on(func|true [,true|false])<br>
 jit.off(func|true [,true|false])<br>
 jit.off(func|true [,true|false])<br>
 jit.flush(func|true [,true|false])</tt></h3>
 jit.flush(func|true [,true|false])</tt></h3>
@@ -142,6 +136,13 @@ of a module to turn off JIT compilation for the whole module for
 debugging purposes.
 debugging purposes.
 </p>
 </p>
 
 
+<h3 id="jit_flush_tr"><tt>status = jit.flush(tr)</tt></h3>
+<p>
+Tries to flush the code for the specified trace and all of its
+side traces from the cache. Returns <tt>true</tt> on success.
+Returns <tt>false</tt> if there are still links to this trace.
+</p>
+
 <h3 id="jit_version"><tt>jit.version</tt></h3>
 <h3 id="jit_version"><tt>jit.version</tt></h3>
 <p>
 <p>
 Contains the LuaJIT version string.
 Contains the LuaJIT version string.
@@ -189,6 +190,140 @@ The debug modules <tt>-jbc</tt>, <tt>-jv</tt> and <tt>-jdump</tt> make
 extensive use of these functions. Please check out their source code,
 extensive use of these functions. Please check out their source code,
 if you want to know more.
 if you want to know more.
 </p>
 </p>
+
+<h2 id="c_api">C API extensions</h2>
+<p>
+LuaJIT adds some extensions to the Lua/C API. The LuaJIT include
+directory must be in the compiler search path (<tt>-I<i>path</i></tt>)
+to be able to include the required header for C code:
+</p>
+<pre class="code">
+#include "luajit.h"
+</pre>
+<p>
+Or for C++ code:
+</p>
+<pre class="code">
+#include "lua.hpp"
+</pre>
+
+<h2 id="luaJIT_setmode"><tt>luaJIT_setmode(L, idx, mode)</tt>
+&mdash; Control VM</h2>
+<p>
+This is a C API extension to allow control of the VM from C code. The
+full prototype of <tt>LuaJIT_setmode</tt> is:
+</p>
+<pre class="code">
+LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
+</pre>
+<p>
+The returned status is either success (<tt>1</tt>) or failure (<tt>0</tt>).
+The second argument is either <tt>0</tt> or a stack index (similar to the
+other Lua/C API functions).
+</p>
+<p>
+The third argument specifies the mode, which is 'or'ed with a flag.
+The flag can be <tt>LUAJIT_MODE_OFF</tt> to turn a feature on,
+<tt>LUAJIT_MODE_ON</tt> to turn a feature off, or
+<tt>LUAJIT_MODE_FLUSH</tt> to flush cached code.
+</p>
+<p>
+The following modes are defined:
+</p>
+
+<h3 id="mode_engine"><tt>luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|flag)</tt></h3>
+<p>
+Turn the whole JIT compiler on or off or flush the whole cache of compiled code.
+</p>
+
+<h3 id="mode_func"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_FUNC|flag)</tt><br>
+<tt>luaJIT_setmode(L, idx, LUAJIT_MODE_ALLFUNC|flag)</tt><br>
+<tt>luaJIT_setmode(L, idx, LUAJIT_MODE_ALLSUBFUNC|flag)</tt></h3>
+<p>
+This sets the mode for the function at the stack index <tt>idx</tt> or
+the parent of the calling function (<tt>idx = 0</tt>). It either
+enables JIT compilation for a function, disables it and flushes any
+already compiled code or only flushes already compiled code. This
+applies recursively to all subfunctions of the function with
+<tt>LUAJIT_MODE_ALLFUNC</tt> or only to the subfunctions with
+<tt>LUAJIT_MODE_ALLSUBFUNC</tt>.
+</p>
+
+<h3 id="mode_engine"><tt>luaJIT_setmode(L, trace,<br>
+&nbsp;&nbsp;LUAJIT_MODE_TRACE|LUAJIT_MODE_FLUSH)</tt></h3>
+<p>
+Tries to flush the code for the specified trace and all of its
+side traces from the cache.
+</p>
+
+<h3 id="mode_engine"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC|flag)</tt></h3>
+<p>
+This mode defines a wrapper function for calls to C functions. The
+first time this is called with <tt>LUAJIT_MODE_ON</tt>, the stack
+index at <tt>idx</tt> must be a <tt>lightuserdata</tt> object holding
+a pointer to the wrapper function. All <b>subsequently created C
+functions</b> are called through the wrapper functions. After the initial
+definition <tt>idx</tt> can be left at <tt>0</tt> when turning the mode
+on or off.
+</p>
+<p>
+The wrapper function can be used for debugging purposes or to catch
+and convert foreign exceptions. Recommended usage can be seen in this
+C++ code excerpt:
+</p>
+<pre class="code">
+#include &lt;exception&gt;
+#include "lua.hpp"
+
+// Catch C++ exceptions and convert them to Lua error messages.
+// Customize as needed for your own exception classes.
+static int wrap_exceptions(lua_State *L, lua_CFunction f)
+{
+  try {
+    return f(L);  // Call wrapped function and return result.
+  } catch (const char *s) {  // Catch and convert exceptions.
+    lua_pushstring(L, s);
+  } catch (std::exception& e) {
+    lua_pushstring(L, e.what());
+  } catch (...) {
+    lua_pushliteral(L, "caught (...)");
+  }
+  return lua_error(L);  // Rethrow as a Lua error.
+}
+
+static int myregister(lua_State *L)
+{
+  ...
+  // Define wrapper function and enable it.
+  lua_pushlightuserdata(L, (void *)wrap_exceptions);
+  luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
+  lua_pop(L, 1);
+  luaL_register(L, "mymodule", myfuncs);  // Pass luaL_Reg list.
+  luaJIT_setmode(L, 0, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_OFF);
+  ...
+  // Wrap some more C++ functions which might throw an exception.
+  luaJIT_setmode(L, 0, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
+  lua_pushcfunction(L, mythrowingfunc1);
+  lua_pushcclosure(L, mythrowingfunc2, 1);
+  luaJIT_setmode(L, 0, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_OFF);
+  ...
+}
+</pre>
+<p>
+Note that you can only define <b>a single global wrapper function</b>,
+so be careful when using this mechanism from multiple C++ modules.
+Also note that this mechanism is not without overhead. It should only
+be enabled for definitions of C++ functions that can actually throw
+exceptions. If you're embedding LuaJIT into an application, only
+enable it <b>after</b> running <tt>luaL_openlibs</tt>.
+</p>
+<p>
+LuaJIT already intercepts exception handling for systems using
+ELF/DWARF2 stack unwinding (e.g. Linux). This is a zero-cost mechanism
+and always enabled. You don't need to use any wrapper functions,
+except when you want to get a more specific error message than
+<tt>"C++&nbsp;exception"</tt>.
+</p>
 <br class="flush">
 <br class="flush">
 </div>
 </div>
 <div id="foot">
 <div id="foot">

+ 31 - 1
doc/changes.html

@@ -43,7 +43,7 @@ div.major { max-width: 600px; padding: 1em; margin: 1em 0 1em 0; }
 <div id="main">
 <div id="main">
 <p>
 <p>
 This is a list of changes between the released versions of LuaJIT.<br>
 This is a list of changes between the released versions of LuaJIT.<br>
-The current <span style="color: #c00000;">development version</span> is <strong>LuaJIT&nbsp;2.0.0-beta1</strong>.<br>
+The current <span style="color: #c00000;">development version</span> is <strong>LuaJIT&nbsp;2.0.0-beta2</strong>.<br>
 The current <span style="color: #0000c0;">stable version</span> is <strong>LuaJIT&nbsp;1.1.5</strong>.
 The current <span style="color: #0000c0;">stable version</span> is <strong>LuaJIT&nbsp;1.1.5</strong>.
 </p>
 </p>
 <p>
 <p>
@@ -53,6 +53,36 @@ to see whether newer versions are available.
 </p>
 </p>
 
 
 <div class="major" style="background: #ffd0d0;">
 <div class="major" style="background: #ffd0d0;">
+<h2 id="LuaJIT-2.0.0-beta2">LuaJIT 2.0.0-beta2 &mdash; 2009-11-09</h2>
+<ul>
+<li>Reorganize build system. Build static+shared library on POSIX.</li>
+<li>Allow C++ exception conversion on all platforms
+using a wrapper function.</li>
+<li>Automatically catch C++ exceptions and rethrow Lua error
+(ELF/DWARF2 only).</li>
+<li>Check for the correct x87 FPU precision at strategic points.</li>
+<li>Always use wrappers for libm functions.</li>
+<li>Resurrect metamethod name strings before copying them.</li>
+<li>Mark current trace, even if compiler is idle.</li>
+<li>Ensure FILE metatable is created only once.</li>
+<li>Fix type comparisons when different integer types are involved.</li>
+<li>Fix getmetatable() recording.</li>
+<li>Fix TDUP with dead keys in template table.</li>
+<li><tt>jit.flush(tr)</tt> returns status.
+Prevent manual flush of a trace that's still linked.</li>
+<li>Improve register allocation heuristics for invariant references.</li>
+<li>Compile the push/pop variants of <tt>table.insert()</tt> and
+<tt>table.remove()</tt>.</li>
+<li>Compatibility with MSVC <tt>link&nbsp/debug</tt>.</li>
+<li>Fix <tt>lua_iscfunction()</tt>.</li>
+<li>Fix <tt>math.random()</tt> when compiled with <tt>-fpic</tt> (OSX).</li>
+<li>Fix <tt>table.maxn()</tt>.</li>
+<li>Bump <tt>MACOSX_DEPLOYMENT_TARGET</tt> to <tt>10.4</tt></li>
+<li><tt>luaL_check*()</tt> and <tt>luaL_opt*()</tt> now support
+negative arguments, too.<br>
+This matches the behavior of Lua 5.1, but not the specification.</li>
+</ul>
+
 <h2 id="LuaJIT-2.0.0-beta1">LuaJIT 2.0.0-beta1 &mdash; 2009-10-31</h2>
 <h2 id="LuaJIT-2.0.0-beta1">LuaJIT 2.0.0-beta1 &mdash; 2009-10-31</h2>
 <ul>
 <ul>
 <li>This is the first public release of LuaJIT 2.0.</li>
 <li>This is the first public release of LuaJIT 2.0.</li>

+ 23 - 0
doc/faq.html

@@ -72,6 +72,7 @@ Search for: <a href="http://scholar.google.com/scholar?q=JIT+Compiler"><span cla
 Search for: <a href="http://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">&raquo;</span>&nbsp;Dynamic Language Optimizations</a><br>
 Search for: <a href="http://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">&raquo;</span>&nbsp;Dynamic Language Optimizations</a><br>
 Search for: <a href="http://scholar.google.com/scholar?q=SSA+Form"><span class="ext">&raquo;</span>&nbsp;SSA Form</a><br>
 Search for: <a href="http://scholar.google.com/scholar?q=SSA+Form"><span class="ext">&raquo;</span>&nbsp;SSA Form</a><br>
 Search for: <a href="http://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">&raquo;</span>&nbsp;Linear Scan Register Allocation</a><br>
 Search for: <a href="http://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">&raquo;</span>&nbsp;Linear Scan Register Allocation</a><br>
+Here is a list of the <a href="http://article.gmane.org/gmane.comp.lang.lua.general/58908"><span class="ext">&raquo;</span>&nbsp;innovative features in LuaJIT</a>.<br>
 And, you know, reading the source is of course the only way to enlightenment. :-)
 And, you know, reading the source is of course the only way to enlightenment. :-)
 </dd>
 </dd>
 </dl>
 </dl>
@@ -86,6 +87,28 @@ functions from Lua 5.0.<br>Please convert your code to the
 vararg syntax</a>.</dd>
 vararg syntax</a>.</dd>
 </dl>
 </dl>
 
 
+<dl>
+<dt>Q: Why do I get this error: "bad FPU precision"?<br>
+<dt>Q: I get weird behavior after initializing Direct3D.<br>
+<dt>Q: Some FPU operations crash after I load a Delphi DLL.<br>
+</dt>
+<dd>
+
+DirectX/Direct3D (up to version 9) sets the x87 FPU to single-precision
+mode by default. This violates the Windows ABI and interferes with the
+operation of many programs &mdash; LuaJIT is affected, too. Please make
+sure you always use the <tt>D3DCREATE_FPU_PRESERVE</tt> flag when
+initializing Direct3D.<br>
+
+Direct3D version 10 or higher do not show this behavior anymore.
+Consider testing your application with older versions, too.<br>
+
+Similarly, the Borland/Delphi runtime modifies the FPU control word and
+enables FP exceptions. Of course this violates the Windows ABI, too.
+Please check the Delphi docs for the Set8087CW method.
+
+</dl>
+
 <dl>
 <dl>
 <dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
 <dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
 <dd>The interrupt signal handler sets a Lua debug hook. But this is
 <dd>The interrupt signal handler sets a Lua debug hook. But this is

+ 33 - 26
doc/install.html

@@ -58,17 +58,15 @@ application under x64-based systems, too.
 <h2>Configuring LuaJIT</h2>
 <h2>Configuring LuaJIT</h2>
 <p>
 <p>
 The standard configuration should work fine for most installations.
 The standard configuration should work fine for most installations.
-Usually there is no need to tweak the settings, except when you want to
-install to a non-standard path. The following three files hold all
-user-configurable settings:
+Usually there is no need to tweak the settings. The following files
+hold all user-configurable settings:
 </p>
 </p>
 <ul>
 <ul>
-<li><tt>src/luaconf.h</tt> sets some configuration variables, in
-particular the default paths for loading modules.</li>
-<li><tt>Makefile</tt> has settings for installing LuaJIT (POSIX
+<li><tt>src/luaconf.h</tt> sets some configuration variables.</li>
+<li><tt>Makefile</tt> has settings for <b>installing</b> LuaJIT (POSIX
 only).</li>
 only).</li>
-<li><tt>src/Makefile</tt> has settings for compiling LuaJIT under POSIX,
-MinGW and Cygwin.</li>
+<li><tt>src/Makefile</tt> has settings for <b>compiling</b> LuaJIT
+under POSIX, MinGW and Cygwin.</li>
 <li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with
 <li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with
 MSVC.</li>
 MSVC.</li>
 </ul>
 </ul>
@@ -97,9 +95,8 @@ terminal window and change to this directory. Now unpack the archive
 and change to the newly created directory:
 and change to the newly created directory:
 </p>
 </p>
 <pre class="code">
 <pre class="code">
-tar zxf LuaJIT-2.0.0-beta1.tar.gz
-cd LuaJIT-2.0.0-beta1
-</pre>
+tar zxf LuaJIT-2.0.0-beta2.tar.gz
+cd LuaJIT-2.0.0-beta2</pre>
 <h3>Building LuaJIT</h3>
 <h3>Building LuaJIT</h3>
 <p>
 <p>
 The supplied Makefiles try to auto-detect the settings needed for your
 The supplied Makefiles try to auto-detect the settings needed for your
@@ -109,6 +106,18 @@ which is probably the default on your system, anyway. Simply run:
 <pre class="code">
 <pre class="code">
 make
 make
 </pre>
 </pre>
+<p>
+By default modules are only searched under the prefix <tt>/usr/local</tt>.
+You can add an extra prefix to the search paths by appending the
+<tt>PREFIX</tt> option, e.g.:
+</p>
+<pre class="code">
+make PREFIX=/home/myself/lj2
+</pre>
+<p>
+Note for OSX: <tt>MACOSX_DEPLOYMENT_TARGET</tt> is set to <tt>10.4</tt>
+in <tt>src/Makefile</tt>. Change it, if you want to build on an older version.
+</p>
 <h3>Installing LuaJIT</h3>
 <h3>Installing LuaJIT</h3>
 <p>
 <p>
 The top-level Makefile installs LuaJIT by default under
 The top-level Makefile installs LuaJIT by default under
@@ -124,20 +133,19 @@ sudo make install
 Otherwise specify the directory prefix as an absolute path, e.g.:
 Otherwise specify the directory prefix as an absolute path, e.g.:
 </p>
 </p>
 <pre class="code">
 <pre class="code">
-sudo make install PREFIX=/opt/lj2
+make install PREFIX=/home/myself/lj2
 </pre>
 </pre>
 <p>
 <p>
-But note that the installation prefix and the prefix for the module paths
-(configured in <tt>src/luaconf.h</tt>) must match.
+Obviously the prefixes given during build and installation need to be the same.
 </p>
 </p>
 <p style="color: #c00000;">
 <p style="color: #c00000;">
 Note: to avoid overwriting a previous version, the beta test releases
 Note: to avoid overwriting a previous version, the beta test releases
 only install the LuaJIT executable under the versioned name (i.e.
 only install the LuaJIT executable under the versioned name (i.e.
-<tt>luajit-2.0.0-beta1</tt>). You probably want to create a symlink
+<tt>luajit-2.0.0-beta2</tt>). You probably want to create a symlink
 for convenience, with a command like this:
 for convenience, with a command like this:
 </p>
 </p>
 <pre class="code" style="color: #c00000;">
 <pre class="code" style="color: #c00000;">
-sudo ln -sf luajit-2.0.0-beta1 /usr/local/bin/luajit
+sudo ln -sf luajit-2.0.0-beta2&nbsp;/usr/local/bin/luajit
 </pre>
 </pre>
 
 
 <h2 id="windows">Windows Systems</h2>
 <h2 id="windows">Windows Systems</h2>
@@ -145,8 +153,8 @@ sudo ln -sf luajit-2.0.0-beta1 /usr/local/bin/luajit
 <p>
 <p>
 Either install one of the open source SDKs
 Either install one of the open source SDKs
 (<a href="http://mingw.org/"><span class="ext">&raquo;</span>&nbsp;MinGW</a> or
 (<a href="http://mingw.org/"><span class="ext">&raquo;</span>&nbsp;MinGW</a> or
-<a href="http://www.cygwin.com/"><span class="ext">&raquo;</span>&nbsp;Cygwin</a>) which come with modified
-versions of GCC plus the required development headers.
+<a href="http://www.cygwin.com/"><span class="ext">&raquo;</span>&nbsp;Cygwin</a>), which come with a modified
+GCC plus the required development headers.
 </p>
 </p>
 <p>
 <p>
 Or install Microsoft's Visual C++ (MSVC) &mdash; the freely downloadable
 Or install Microsoft's Visual C++ (MSVC) &mdash; the freely downloadable
@@ -159,8 +167,8 @@ Next, download the source package and unpack it using an archive manager
 </p>
 </p>
 <h3>Building with MSVC</h3>
 <h3>Building with MSVC</h3>
 <p>
 <p>
-Open a "Visual Studio .NET Command Prompt" and <tt>cd</tt> to the
-directory where you've unpacked the sources. Then run this command:
+Open a "Visual Studio .NET Command Prompt", <tt>cd</tt> to the
+directory where you've unpacked the sources and run these commands:
 </p>
 </p>
 <pre class="code">
 <pre class="code">
 cd src
 cd src
@@ -176,14 +184,12 @@ are in your path. Then <tt>cd</tt> to the directory where
 you've unpacked the sources and run this command for MinGW:
 you've unpacked the sources and run this command for MinGW:
 </p>
 </p>
 <pre class="code">
 <pre class="code">
-cd src
 mingw32-make
 mingw32-make
 </pre>
 </pre>
 <p>
 <p>
 Or this command for Cygwin:
 Or this command for Cygwin:
 </p>
 </p>
 <pre class="code">
 <pre class="code">
-cd src
 make
 make
 </pre>
 </pre>
 <p>
 <p>
@@ -191,10 +197,11 @@ Then follow the installation instructions below.
 </p>
 </p>
 <h3>Installing LuaJIT</h3>
 <h3>Installing LuaJIT</h3>
 <p>
 <p>
-Copy <tt>luajit.exe</tt> and <tt>lua51.dll</tt>
-to a newly created directory (any location is ok). Add <tt>lua</tt>
-and <tt>lua\jit</tt> directories below it and copy all Lua files
-from the <tt>lib</tt> directory of the distribution to the latter directory.
+Copy <tt>luajit.exe</tt> and <tt>lua51.dll</tt> (built in the <tt>src</tt>
+directory) to a newly created directory (any location is ok).
+Add <tt>lua</tt> and <tt>lua\jit</tt> directories below it and copy
+all Lua files from the <tt>lib</tt> directory of the distribution
+to the latter directory.
 </p>
 </p>
 <p>
 <p>
 There are no hardcoded
 There are no hardcoded

+ 3 - 3
doc/running.html

@@ -69,11 +69,11 @@ interactive mode, too.
 <p class="indent" style="color: #c00000;">
 <p class="indent" style="color: #c00000;">
 Note: the beta test releases only install under the versioned name on
 Note: the beta test releases only install under the versioned name on
 POSIX systems (to avoid overwriting a previous version). You either need
 POSIX systems (to avoid overwriting a previous version). You either need
-to type <tt>luajit-2.0.0-beta1</tt> to start it or create a symlink
+to type <tt>luajit-2.0.0-beta2</tt> to start it or create a symlink
 with a command like this:
 with a command like this:
 </p>
 </p>
 <pre class="code" style="color: #c00000;">
 <pre class="code" style="color: #c00000;">
-sudo ln -sf luajit-2.0.0-beta1 /usr/local/bin/luajit
+sudo ln -sf luajit-2.0.0-beta2&nbsp;/usr/local/bin/luajit
 </pre>
 </pre>
 <p>
 <p>
 Unlike previous versions <b>optimization is turned on by default</b> in
 Unlike previous versions <b>optimization is turned on by default</b> in
@@ -119,7 +119,7 @@ itself. For a description of their options and output format, please
 read the comment block at the start of their source.
 read the comment block at the start of their source.
 They can be found in the <tt>lib</tt> directory of the source
 They can be found in the <tt>lib</tt> directory of the source
 distribution or installed under the <tt>jit</tt> directory. By default
 distribution or installed under the <tt>jit</tt> directory. By default
-this is <tt>/usr/local/share/luajit-2.0.0-beta1/jit</tt> on POSIX
+this is <tt>/usr/local/share/luajit-2.0.0-beta2/jit</tt> on POSIX
 systems.
 systems.
 </p>
 </p>
 
 

+ 18 - 3
doc/status.html

@@ -90,7 +90,22 @@ known incompatibilities with standard Lua:
 <ul>
 <ul>
 <li>
 <li>
 The Lua <b>debug API</b> is missing a couple of features (call/return
 The Lua <b>debug API</b> is missing a couple of features (call/return
-hooks) and shows slightly different behavior (no per-coroutine hooks).
+hooks) and shows slightly different behavior (no per-coroutine hooks,
+no tail call counting).
+</li>
+<li>
+<b>Bytecode</b> currently cannot be loaded or dumped. Note that
+the bytecode format differs from Lua&nbsp;5.1 &mdash; loading foreign
+bytecode is not supported at all.
+</li>
+<li>
+Some of the <b>configuration options</b> of Lua&nbsp;5.1 are not supported:
+<ul>
+<li>The <b>number type</b> cannot be changed (it's always a <tt>double</tt>).</li>
+<li>The stand-alone executable cannot be linked with <b>readline</b>
+to enable line editing. It's planned to add support for loading it
+on-demand.</li>
+</ul>
 </li>
 </li>
 <li>
 <li>
 Most other issues you're likely to find (e.g. with the existing test
 Most other issues you're likely to find (e.g. with the existing test
@@ -105,7 +120,7 @@ demonstrable need is shown.
 <li>
 <li>
 The <b>JIT compiler</b> is not complete (yet) and falls back to the
 The <b>JIT compiler</b> is not complete (yet) and falls back to the
 interpreter in some cases. All of this works transparently, so unless
 interpreter in some cases. All of this works transparently, so unless
-you use -jv, you'll probably never notice (the interpreter is quite
+you use <tt>-jv</tt>, you'll probably never notice (the interpreter is quite
 fast, too). Here are the known issues:
 fast, too). Here are the known issues:
 <ul>
 <ul>
 <li>
 <li>
@@ -119,7 +134,7 @@ effort.
 </li>
 </li>
 <li>
 <li>
 <b>Recursion</b> is not traced yet. Often no trace will be generated at
 <b>Recursion</b> is not traced yet. Often no trace will be generated at
-all or some unroll limit will catch it and aborts the trace.
+all or some unroll limit will catch it and abort the trace.
 </li>
 </li>
 <li>
 <li>
 The trace compiler currently does not back off specialization for
 The trace compiler currently does not back off specialization for

+ 82 - 0
etc/luajit.1

@@ -0,0 +1,82 @@
+.TH luajit 1 "" "" "LuaJIT documentation"
+.SH NAME
+luajit \- Just-In-Time Compiler for the Lua Language
+\fB
+.SH SYNOPSIS
+.B luajit
+[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
+.SH "WEB SITE"
+.IR http://luajit.org
+.SH DESCRIPTION
+.PP
+This is the command-line program to run Lua programs with \fBLuaJIT\fR.
+.PP
+\fBLuaJIT\fR is a just-in-time (JIT) compiler for the Lua language.
+The virtual machine (VM) is based on a fast interpreter combined with
+a trace compiler. It can significantly improve the performance of Lua programs.
+.PP
+\fBLuaJIT\fR is API\- and ABI-compatible with the VM of the standard
+Lua\ 5.1 interpreter. When embedding the VM into an application,
+the built library can be used as a drop-in replacement.
+.SH OPTIONS
+.TP
+.BI "\-e " chunk
+Run the given chunk of Lua code.
+.TP
+.BI "\-l " library
+Load the named library, just like \fBrequire("\fR\fIlibrary\fR\fB")\fR.
+.TP
+.BI "\-j " command
+Perform LuaJIT control command (optional space after \fB\-j\fR).
+.TP
+.BI "\-O" [opt]
+Control LuaJIT optimizations.
+.TP
+.B "\-i"
+Run in interactive mode.
+.TP
+.B "\-v"
+Show \fBLuaJIT\fR version.
+.TP
+.B "\-\-"
+Stop processing options.
+.TP
+.B "\-"
+Read script from stdin instead.
+.PP
+After all options are processed, the given \fIscript\fR is run.
+The arguments are passed in the global \fIarg\fR table.
+.PP
+Interactive mode is only entered, if no \fIscript\fR and no \fB\-e\fR
+option is given. Interactive mode can be left with EOF (\fICtrl\-Z\fB).
+.SH EXAMPLES
+.TP
+luajit hello.lua world
+
+Prints "Hello world", assuming \fIhello.lua\fR contains:
+.br
+  print("Hello", arg[1])
+.TP
+luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)"
+
+Calculates the sum of the numbers from 1 to 1000000000.
+.br
+And finishes in a reasonable amount of time, too.
+.TP
+luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end"
+
+Runs some nested loops and shows the resulting traces.
+.SH COPYRIGHT
+.PP
+\fBLuaJIT\fR is Copyright \(co 2005-2009 Mike Pall.
+.br
+\fBLuaJIT\fR is open source software, released under the MIT/X license.
+.SH SEE ALSO
+.PP
+More details in the provided HTML docs or at:
+.IR http://luajit.org
+.br
+More about the Lua language can be found at:
+.IR http://lua.org/docs.html
+.PP
+lua(1)

+ 24 - 0
etc/luajit.pc

@@ -0,0 +1,24 @@
+# Package information for LuaJIT to be used by pkg-config.
+majver=2
+minver=0
+relver=0
+version=${majver}.${minver}.${relver}-beta2
+abiver=5.1
+
+prefix=/usr/local
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+libname=luajit-${abiver}
+includedir=${prefix}/include/luajit-${majver}.${minver}
+
+INSTALL_LMOD=${prefix}/share/lua/${abiver}
+INSTALL_CMOD=${prefix}/lib/lua/${abiver}
+
+Name: LuaJIT
+Description: Just-in-time compiler for Lua
+URL: http://luajit.org
+Version: ${version}
+Requires:
+Libs: -L${libdir} -l${libname}
+Libs.private: -Wl,-E -lm -ldl
+Cflags: -I${includedir}

+ 216 - 106
src/Makefile

@@ -8,10 +8,17 @@
 # Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
 # Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
 ##############################################################################
 ##############################################################################
 
 
+MAJVER=  2
+MINVER=  0
+RELVER=  0
+ABIVER=  5.1
+NODOTABIVER= 51
+
 ##############################################################################
 ##############################################################################
 # Compiler options: change them as needed. This mainly affects the speed of
 # Compiler options: change them as needed. This mainly affects the speed of
 # the JIT compiler itself, not the speed of the JIT compiled code.
 # the JIT compiler itself, not the speed of the JIT compiled code.
 # Turn any of the optional settings on by removing the '#' in front of them.
 # Turn any of the optional settings on by removing the '#' in front of them.
+# You need to 'make clean' and 'make' again, if you change any options.
 #
 #
 # Note: LuaJIT can only be compiled for x86, and not for x64 (yet)!
 # Note: LuaJIT can only be compiled for x86, and not for x64 (yet)!
 #       In the meantime, the x86 binary runs fine under a x64 OS.
 #       In the meantime, the x86 binary runs fine under a x64 OS.
@@ -81,89 +88,142 @@ XCFLAGS=
 #XCFLAGS+= -DLUA_USE_ASSERT
 #XCFLAGS+= -DLUA_USE_ASSERT
 #
 #
 ##############################################################################
 ##############################################################################
+
+##############################################################################
+# Build mode: override the mode as needed. Default is mixed mode on POSIX.
+# On Windows this is the same as dynamic mode.
+#
+# Mixed mode creates a static + dynamic library and a statically linked luajit.
+BUILDMODE= mixed
+#
+# Static mode creates a static library and a statically linked luajit.
+#BUILDMODE= static
+#
+# Dynamic mode creates a dynamic library and a dynamically linked luajit.
+# Note: this executable will only run when the library is installed!
+#BUILDMODE= dynamic
+##############################################################################
 # You probably don't need to change anything below this line.
 # You probably don't need to change anything below this line.
 ##############################################################################
 ##############################################################################
 
 
+##############################################################################
+# Flags and options for host and target.
+##############################################################################
+
 CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(CFLAGS) $(XCFLAGS)
 CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(CFLAGS) $(XCFLAGS)
 LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
 LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
 
 
 HOST_CC= $(CC)
 HOST_CC= $(CC)
 HOST_RM= rm -f
 HOST_RM= rm -f
+# NOTE: The LuaJIT distribution comes with a pre-generated buildvm_*.h.
+# You DO NOT NEED an installed copy of (plain) Lua 5.1 to run DynASM unless
+# you want to MODIFY the corresponding *.dasc file. You can also use LuaJIT
+# itself (bootstrapped from the pre-generated file) to run DynASM of course.
+HOST_LUA= lua
+
 HOST_XCFLAGS=
 HOST_XCFLAGS=
 HOST_XLDFLAGS=
 HOST_XLDFLAGS=
 HOST_XLIBS=
 HOST_XLIBS=
+HOST_CFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH)
+HOST_LDFLAGS= $(LDOPTIONS) $(HOST_XLDFLAGS)
+HOST_LIBS= $(HOST_XLIBS)
+
+# Cross-compilation example: make CROSS=i586-mingw32msvc- TARGET_SYS=Windows
+CROSS=
+STATIC_CC = $(CROSS)$(CC)
+DYNAMIC_CC = $(CROSS)$(CC) -fPIC
+TARGET_CC= $(STATIC_CC)
+TARGET_STCC= $(STATIC_CC)
+TARGET_DYNCC= $(DYNAMIC_CC)
+TARGET_LD= $(CROSS)$(CC)
+TARGET_AR= $(CROSS)ar rcus
+TARGET_STRIP= $(CROSS)strip
+
+TARGET_SONAME= libluajit-$(ABIVER).so.$(MAJVER)
+TARGET_DYLIBNAME= libluajit-$(NODOTABIVER).$(MAJVER).$(MINVER).$(RELVER).dylib
+TARGET_DLLNAME= lua$(NODOTABIVER).dll
+TARGET_XSHLDFLAGS= -shared -fPIC -Wl,-soname,$(TARGET_SONAME)
+TARGET_DYNXLDOPTS=
 
 
-TARGET_CC= $(CC)
-TARGET_STRIP= strip
-TARGET_XCFLAGS= -D_FILE_OFFSET_BITS=64
-TARGET_XLDFLAGS=
-TARGET_XSHLDFLAGS= -shared
-TARGET_XLIBS=
 TARGET_ARCH= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET))
 TARGET_ARCH= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET))
 TARGET_DISABLE= -U_FORTIFY_SOURCE
 TARGET_DISABLE= -U_FORTIFY_SOURCE
-ifneq (,$(findstring stack-protector,$(shell $(CC) -dumpspecs)))
+ifneq (,$(findstring stack-protector,$(shell $(TARGET_CC) -dumpspecs)))
   TARGET_DISABLE+= -fno-stack-protector
   TARGET_DISABLE+= -fno-stack-protector
 endif
 endif
 
 
+TARGET_XCFLAGS= -D_FILE_OFFSET_BITS=64
+TARGET_XLDFLAGS=
+TARGET_XLDOPTS=
+TARGET_XLIBS=
+TARGET_CFLAGS= $(CCOPTIONS) $(TARGET_DISABLE) $(TARGET_XCFLAGS)
+TARGET_LDFLAGS= $(LDOPTIONS) $(TARGET_XLDFLAGS) $(TARGET_XLDOPTS)
+TARGET_SHLDFLAGS= $(LDOPTIONS) $(TARGET_XSHLDFLAGS)
+TARGET_LIBS= -lm $(TARGET_XLIBS)
+
+ifneq (,$(PREFIX))
+ifneq (/usr/local,$(PREFIX))
+  TARGET_XCFLAGS+= -DLUA_XROOT=\"$(PREFIX)/\"
+  ifneq (/usr,$(PREFIX))
+    TARGET_DYNXLDOPTS= -Wl,-rpath,$(PREFIX)/lib
+  endif
+endif
+endif
+
+##############################################################################
+# System detection.
+##############################################################################
+
 ifneq (,$(findstring Windows,$(OS)))
 ifneq (,$(findstring Windows,$(OS)))
-  TARGET_SYS= Windows
+  HOST_SYS= Windows
 else
 else
-  TARGET_SYS:= $(shell uname -s)
+  HOST_SYS:= $(shell uname -s)
   ifneq (,$(findstring CYGWIN,$(TARGET_SYS)))
   ifneq (,$(findstring CYGWIN,$(TARGET_SYS)))
-    TARGET_SYS= Windows
+    HOST_SYS= Windows
   endif
   endif
 endif
 endif
+ifeq (Windows,$(HOST_SYS))
+  HOST_RM= del
+endif
 
 
-ifeq (Linux,$(TARGET_SYS))
-  TARGET_XLIBS= -ldl
-  TARGET_XLDFLAGS= -Wl,-E
-else
+TARGET_SYS= $(HOST_SYS)
 ifeq (Windows,$(TARGET_SYS))
 ifeq (Windows,$(TARGET_SYS))
-  HOST_RM= del
-  TARGET_STRIP= strip --strip-unneeded
+  TARGET_STRIP+= --strip-unneeded
+  TARGET_XSHLDFLAGS= -shared
+  TARGET_DYNXLDOPTS=
 else
 else
 ifeq (Darwin,$(TARGET_SYS))
 ifeq (Darwin,$(TARGET_SYS))
-  TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup
-  TARGET_STRIP= strip -x
-  export MACOSX_DEPLOYMENT_TARGET=10.3
+  export MACOSX_DEPLOYMENT_TARGET=10.4
+  TARGET_STRIP+= -x
+  TARGET_AR+= 2>/dev/null
+  TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
+  ifneq (,$(TARGET_DYNXLDOPTS))
+    TARGET_DYNXLDOPTS=
+    TARGET_XSHLDFLAGS+= -install_name $(PREFIX)/lib/$(TARGET_DYLIBNAME)
+  endif
 else
 else
   TARGET_XLDFLAGS= -Wl,-E
   TARGET_XLDFLAGS= -Wl,-E
+  ifeq (Linux,$(TARGET_SYS))
+    TARGET_XLIBS= -ldl
+  endif
 endif
 endif
 endif
 endif
-endif
-
-# NOTE: The LuaJIT distribution comes with a pre-generated buildvm_*.h.
-# You DO NOT NEED an installed copy of (plain) Lua 5.1 to run DynASM unless
-# you want to MODIFY the corresponding *.dasc file. You can also use LuaJIT
-# itself (bootstrapped from the pre-generated file) to run DynASM of course.
-DASM_LUA= lua
-
-Q= @
-E= @echo
-#Q=
-#E= @:
-
-##############################################################################
 
 
-TARGET_CFLAGS= $(CCOPTIONS) $(TARGET_DISABLE) $(TARGET_XCFLAGS)
-TARGET_LDFLAGS= $(LDOPTIONS) $(TARGET_XLDFLAGS)
-TARGET_SHLDFLAGS= $(LDOPTIONS) $(TARGET_XSHLDFLAGS)
-TARGET_LIBS= -lm $(TARGET_XLIBS)
 ifneq (,$(CCDEBUG))
 ifneq (,$(CCDEBUG))
   TARGET_STRIP= @:
   TARGET_STRIP= @:
 endif
 endif
 
 
-HOST_CFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH)
-HOST_LDFLAGS= $(LDOPTIONS) $(HOST_XLDFLAGS)
-HOST_LIBS= $(HOST_XLIBS)
+##############################################################################
+# Files and pathnames.
+##############################################################################
 
 
 DASM_DIR= ../dynasm
 DASM_DIR= ../dynasm
-DASM= $(DASM_LUA) $(DASM_DIR)/dynasm.lua
+DASM= $(HOST_LUA) $(DASM_DIR)/dynasm.lua
 DASM_FLAGS=
 DASM_FLAGS=
 DASM_DISTFLAGS= -LN
 DASM_DISTFLAGS= -LN
 
 
 BUILDVM_O= buildvm.o buildvm_asm.o buildvm_peobj.o buildvm_lib.o buildvm_fold.o
 BUILDVM_O= buildvm.o buildvm_asm.o buildvm_peobj.o buildvm_lib.o buildvm_fold.o
 BUILDVM_T= buildvm
 BUILDVM_T= buildvm
+BUILDVM_X= ./$(BUILDVM_T)
 
 
 HOST_O= $(BUILDVM_O)
 HOST_O= $(BUILDVM_O)
 HOST_T= $(BUILDVM_T)
 HOST_T= $(BUILDVM_T)
@@ -188,53 +248,113 @@ LJCORE_O= lj_gc.o lj_err.o lj_ctype.o lj_bc.o lj_obj.o \
 	  $(LJLIB_O) lib_init.o
 	  $(LJLIB_O) lib_init.o
 
 
 LJVMCORE_O= $(LJVM_O) $(LJCORE_O)
 LJVMCORE_O= $(LJVM_O) $(LJCORE_O)
+LJVMCORE_DYNO= $(LJVMCORE_O:.o=_dyn.o)
+
+LIB_VMDEF= ../lib/vmdef.lua
+LIB_VMDEFP= $(LIB_VMDEF)
 
 
-# NYI: Need complete support for building as a shared library on POSIX.
-#      This is currently *only* suitable for MinGW and Cygwin, see below.
 LUAJIT_O= luajit.o
 LUAJIT_O= luajit.o
-LUAJIT_SO= luajit.so
+LUAJIT_A= libluajit.a
+LUAJIT_SO= libluajit.so
 LUAJIT_T= luajit
 LUAJIT_T= luajit
 
 
-LIB_VMDEF= ../lib/vmdef.lua
+ALL_T= $(LUAJIT_T) $(LUAJIT_A) $(LUAJIT_SO) $(BUILDVM_T)
+ALL_GEN= $(LJVM_S) lj_ffdef.h lj_libdef.h lj_recdef.h $(LIB_VMDEFP) lj_folddef.h
+ALL_DYNGEN= buildvm_x86.h
+WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk
+ALL_RM= $(ALL_T) $(ALL_GEN) *.o $(WIN_RM)
 
 
-TARGET_DEP= $(LIB_VMDEF)
-TARGET_O= $(LJVMCORE_O) $(LUAJIT_O)
-TARGET_T= $(LUAJIT_T)
+##############################################################################
+# Build mode handling.
+##############################################################################
 
 
-ALL_GEN= $(LJVM_S) lj_ffdef.h lj_libdef.h lj_recdef.h $(LIB_VMDEF) lj_folddef.h
-ALL_DYNGEN= buildvm_x86.h
-WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest
-ALL_RM= $(LUAJIT_T) $(LUAJIT_SO) $(HOST_T) $(ALL_GEN) *.o $(WIN_RM)
+# Mixed mode defaults.
+TARGET_O= $(LUAJIT_A)
+TARGET_T= $(LUAJIT_T) $(LUAJIT_SO)
+TARGET_DEP= $(LIB_VMDEF) $(LUAJIT_SO)
 
 
+ifeq (Windows,$(HOST_SYS))
+  BUILDVM_T= buildvm.exe
+  LIB_VMDEFP= $(subst /,\\,$(LIB_VMDEF))
+endif
 ifeq (Windows,$(TARGET_SYS))
 ifeq (Windows,$(TARGET_SYS))
+  DYNAMIC_CC= $(STATIC_CC)
   LJVM_BOUT= $(LJVM_O)
   LJVM_BOUT= $(LJVM_O)
   LJVM_MODE= peobj
   LJVM_MODE= peobj
-  LIB_VMDEF= ..\lib\vmdef.lua
-  # Imported symbols are bound to a specific DLL name under Windows.
-  LUAJIT_SO= lua51.dll
+  LUAJIT_SO= $(TARGET_DLLNAME)
   LUAJIT_T= luajit.exe
   LUAJIT_T= luajit.exe
-  BUILDVM_T= buildvm.exe
-  #
-  # You can comment out the following two lines to build a static executable.
-  # But then you won't be able to dynamically load any C modules, because
-  # they bind to lua51.dll.
-  #
-  TARGET_XCFLAGS+= -DLUA_BUILD_AS_DLL
-  TARGET_O= $(LUAJIT_SO) $(LUAJIT_O)
+  ifneq ($(HOST_SYS),$(TARGET_SYS))
+    HOST_XCFLAGS+= -malign-double
+  endif
+  # Mixed mode is not supported on Windows. And static mode doesn't work well.
+  # C modules cannot be loaded, because they bind to lua51.dll.
+  ifneq (static,$(BUILDMODE))
+    BUILDMODE= dynamic
+    TARGET_XCFLAGS+= -DLUA_BUILD_AS_DLL
+  endif
 endif
 endif
 
 
-##############################################################################
+ifeq (static,$(BUILDMODE))
+  TARGET_DYNCC= @:
+  TARGET_T= $(LUAJIT_T)
+  TARGET_DEP= $(LIB_VMDEF)
+else
+ifeq (dynamic,$(BUILDMODE))
+  TARGET_CC= $(DYNAMIC_CC)
+  TARGET_DYNCC= @:
+  LJVMCORE_DYNO= $(LJVMCORE_O)
+  TARGET_O= $(LUAJIT_SO)
+  TARGET_XLDOPTS= $(TARGET_DYNXLDOPTS)
+else
+ifeq (Darwin,$(TARGET_SYS))
+  TARGET_DYNCC= @:
+  LJVMCORE_DYNO= $(LJVMCORE_O)
+endif
+endif
+endif
 
 
-default: $(TARGET_T)
+Q= @
+E= @echo
+#Q=
+#E= @:
 
 
-all:	$(TARGET_T)
+##############################################################################
+# Make targets.
+##############################################################################
+
+default all:	$(TARGET_T)
 
 
 amalg:
 amalg:
 	@grep "^[+|]" ljamalg.c
 	@grep "^[+|]" ljamalg.c
 	$(MAKE) all "LJCORE_O=ljamalg.o"
 	$(MAKE) all "LJCORE_O=ljamalg.o"
 
 
-MAKE_TARGETS= amalg
+clean:
+	$(HOST_RM) $(ALL_RM)
+
+cleaner:
+	$(HOST_RM) $(ALL_RM) $(ALL_DYNGEN)
+
+distclean:	clean
+	$(E) "DYNASM    $@"
+	$(Q)$(DASM) $(DASM_DISTFLAGS) -o buildvm_x86.h buildvm_x86.dasc
+
+depend:
+	@test -f lj_ffdef.h || touch lj_ffdef.h
+	@test -f lj_libdef.h || touch lj_libdef.h
+	@test -f lj_recdef.h || touch lj_recdef.h
+	@test -f lj_folddef.h || touch lj_folddef.h
+	@test -f buildvm_x86.h || touch buildvm_x86.h
+	@$(HOST_CC) $(HOST_CFLAGS) -MM *.c | sed "s|$(DASM_DIR)|\$$(DASM_DIR)|g" >Makefile.dep
+	@test -s lj_ffdef.h || $(HOST_RM) lj_ffdef.h
+	@test -s lj_libdef.h || $(HOST_RM) lj_libdef.h
+	@test -s lj_recdef.h || $(HOST_RM) lj_recdef.h
+	@test -s lj_folddef.h || $(HOST_RM) lj_folddef.h
+	@test -s buildvm_x86.h || $(HOST_RM) buildvm_x86.h
+
+.PHONY: default all amalg clean cleaner distclean depend
 
 
+##############################################################################
+# Rules for generated files.
 ##############################################################################
 ##############################################################################
 
 
 buildvm_x86.h: buildvm_x86.dasc
 buildvm_x86.h: buildvm_x86.dasc
@@ -247,80 +367,70 @@ $(BUILDVM_T): $(BUILDVM_O)
 
 
 $(LJVM_BOUT): $(BUILDVM_T)
 $(LJVM_BOUT): $(BUILDVM_T)
 	$(E) "BUILDVM   $@"
 	$(E) "BUILDVM   $@"
-	$(Q)./$(BUILDVM_T) -m $(LJVM_MODE) -o $@
+	$(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@
 
 
 lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
 lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
 	$(E) "BUILDVM   $@"
 	$(E) "BUILDVM   $@"
-	$(Q)./$(BUILDVM_T) -m ffdef -o $@ $(LJLIB_C)
+	$(Q)$(BUILDVM_X) -m ffdef -o $@ $(LJLIB_C)
 
 
 lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
 lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
 	$(E) "BUILDVM   $@"
 	$(E) "BUILDVM   $@"
-	$(Q)./$(BUILDVM_T) -m libdef -o $@ $(LJLIB_C)
+	$(Q)$(BUILDVM_X) -m libdef -o $@ $(LJLIB_C)
 
 
 lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
 lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
 	$(E) "BUILDVM   $@"
 	$(E) "BUILDVM   $@"
-	$(Q)./$(BUILDVM_T) -m recdef -o $@ $(LJLIB_C)
+	$(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C)
 
 
 $(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
 $(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
 	$(E) "BUILDVM   $@"
 	$(E) "BUILDVM   $@"
-	$(Q)./$(BUILDVM_T) -m vmdef -o $@ $(LJLIB_C)
+	$(Q)$(BUILDVM_X) -m vmdef -o $(LIB_VMDEFP) $(LJLIB_C)
 
 
 lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
 lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
 	$(E) "BUILDVM   $@"
 	$(E) "BUILDVM   $@"
-	$(Q)./$(BUILDVM_T) -m folddef -o $@ lj_opt_fold.c
-
-$(LUAJIT_SO): $(LJVMCORE_O)
-	$(E) "LINK      $@"
-	$(Q)$(TARGET_CC) $(TARGET_SHLDFLAGS) -o $@ $(LJVMCORE_O) $(TARGET_LIBS)
-	$(Q)$(TARGET_STRIP) $@
-
-$(LUAJIT_T): $(TARGET_O) $(TARGET_DEP)
-	$(E) "LINK      $@"
-	$(Q)$(TARGET_CC) $(TARGET_LDFLAGS) -o $@ $(TARGET_O) $(TARGET_LIBS)
-	$(Q)$(TARGET_STRIP) $@
-	$(E) "OK        Successfully built LuaJIT"
+	$(Q)$(BUILDVM_X) -m folddef -o $@ lj_opt_fold.c
 
 
 ##############################################################################
 ##############################################################################
+# Object file rules.
+##############################################################################
 
 
 %.o: %.c
 %.o: %.c
 	$(E) "CC        $@"
 	$(E) "CC        $@"
+	$(Q)$(TARGET_DYNCC) $(TARGET_CFLAGS) -c -o $(@:.o=_dyn.o) $<
 	$(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
 	$(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
 
 
 %.o: %.s
 %.o: %.s
 	$(E) "ASM       $@"
 	$(E) "ASM       $@"
+	$(Q)$(TARGET_DYNCC) $(TARGET_CFLAGS) -c -o $(@:.o=_dyn.o) $<
 	$(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
 	$(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
 
 
+$(LUAJIT_O):
+	$(E) "CC        $@"
+	$(Q)$(TARGET_STCC) $(TARGET_CFLAGS) -c -o $@ $<
+
 $(HOST_O): %.o: %.c
 $(HOST_O): %.o: %.c
 	$(E) "HOSTCC    $@"
 	$(E) "HOSTCC    $@"
 	$(Q)$(HOST_CC) $(HOST_CFLAGS) -c -o $@ $<
 	$(Q)$(HOST_CC) $(HOST_CFLAGS) -c -o $@ $<
 
 
 include Makefile.dep
 include Makefile.dep
 
 
+##############################################################################
+# Target file rules.
 ##############################################################################
 ##############################################################################
 
 
-clean:
-	$(HOST_RM) $(ALL_RM)
-
-cleaner:	clean
-	$(HOST_RM) $(ALL_DYNGEN)
+$(LUAJIT_A): $(LJVMCORE_O)
+	$(E) "AR        $@"
+	$(Q)$(TARGET_AR) $@ $(LJVMCORE_O)
 
 
-distclean:	clean
-	$(E) "DYNASM    $@"
-	$(Q)$(DASM) $(DASM_DISTFLAGS) -o buildvm_x86.h buildvm_x86.dasc
-
-depend:
-	@test -f lj_ffdef.h || touch lj_ffdef.h
-	@test -f lj_libdef.h || touch lj_libdef.h
-	@test -f lj_recdef.h || touch lj_recdef.h
-	@test -f lj_folddef.h || touch lj_folddef.h
-	@test -f buildvm_x86.h || touch buildvm_x86.h
-	@$(HOST_CC) $(HOST_CFLAGS) -MM *.c | sed "s|$(DASM_DIR)|\$$(DASM_DIR)|g" >Makefile.dep
-	@test -s lj_ffdef.h || $(HOST_RM) lj_ffdef.h
-	@test -s lj_libdef.h || $(HOST_RM) lj_libdef.h
-	@test -s lj_recdef.h || $(HOST_RM) lj_recdef.h
-	@test -s lj_folddef.h || $(HOST_RM) lj_folddef.h
-	@test -s buildvm_x86.h || $(HOST_RM) buildvm_x86.h
+# The dependency on _O, but linking with _DYNO is intentional.
+$(LUAJIT_SO): $(LJVMCORE_O)
+	$(E) "DYNLINK   $@"
+	$(Q)$(TARGET_LD) $(TARGET_SHLDFLAGS) -o $@ $(LJVMCORE_DYNO) $(TARGET_LIBS)
+	$(Q)$(TARGET_STRIP) $@
 
 
-.PHONY: default all $(MAKE_TARGETS) clean cleaner distclean depend
+$(LUAJIT_T): $(TARGET_O) $(LUAJIT_O) $(TARGET_DEP)
+	$(E) "LINK      $@"
+	$(Q)$(TARGET_LD) $(TARGET_LDFLAGS) -o $@ $(LUAJIT_O) $(TARGET_O) $(TARGET_LIBS)
+	$(Q)$(TARGET_STRIP) $@
+	$(E) "OK        Successfully built LuaJIT"
 
 
 ##############################################################################
 ##############################################################################

+ 2 - 2
src/Makefile.dep

@@ -34,8 +34,8 @@ lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
 lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
 lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
   lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h
   lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h
 lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
 lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
-  lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_state.h \
-  lj_ff.h lj_ffdef.h lj_ctype.h lj_lib.h lj_libdef.h
+  lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h \
+  lj_state.h lj_ff.h lj_ffdef.h lj_ctype.h lj_lib.h lj_libdef.h
 lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
 lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
   lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \
   lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \
   lj_libdef.h
   lj_libdef.h

+ 2 - 5
src/buildvm_asm.c

@@ -71,10 +71,7 @@ err:
     exit(1);
     exit(1);
   }
   }
   emit_asm_bytes(ctx, cp, n);
   emit_asm_bytes(ctx, cp, n);
-  if (!strncmp(sym, LABEL_PREFIX, sizeof(LABEL_PREFIX)-1))
-    fprintf(ctx->fp, "\t%s _%s\n", opname, sym);
-  else
-    fprintf(ctx->fp, "\t%s _" LABEL_PREFIX "wrapper_%s\n", opname, sym);
+  fprintf(ctx->fp, "\t%s _%s\n", opname, sym);
 }
 }
 
 
 /* Emit an assembler label. */
 /* Emit an assembler label. */
@@ -135,7 +132,7 @@ void emit_asm(BuildCtx *ctx)
   fprintf(ctx->fp, "\t.text\n");
   fprintf(ctx->fp, "\t.text\n");
   emit_asm_align(ctx, 4);
   emit_asm_align(ctx, 4);
 
 
-  emit_asm_label(ctx, LABEL_ASM_BEGIN, 0, 1);
+  emit_asm_label(ctx, LABEL_ASM_BEGIN, 0, 0);
   if (ctx->mode == BUILD_elfasm)
   if (ctx->mode == BUILD_elfasm)
     fprintf(ctx->fp, ".Lbegin:\n");
     fprintf(ctx->fp, ".Lbegin:\n");
 
 

+ 6 - 1
src/buildvm_fold.c

@@ -188,7 +188,12 @@ void emit_fold(BuildCtx *ctx)
       } else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) {
       } else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) {
 	p += 2;
 	p += 2;
 	*q = '\0';
 	*q = '\0';
-	fprintf(ctx->fp, funcidx ? ",\n  %s" : "  %s", p);
+	if (funcidx)
+	  fprintf(ctx->fp, ",\n");
+	if (p[-2] == 'X')
+	  fprintf(ctx->fp, "  %s", p);
+	else
+	  fprintf(ctx->fp, "  fold_%s", p);
 	funcidx++;
 	funcidx++;
       } else {
       } else {
 	buf[strlen(buf)-1] = '\0';
 	buf[strlen(buf)-1] = '\0';

+ 2 - 1
src/buildvm_peobj.c

@@ -264,7 +264,8 @@ void emit_peobj(BuildCtx *ctx)
       emit_peobj_sym(ctx, name, 0,
       emit_peobj_sym(ctx, name, 0,
 		     PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
 		     PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
     }
     }
-    emit_peobj_sym_func(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0);
+    emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0,
+		   PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
     for (i = nzsym; i < ctx->nsym; i++) {
     for (i = nzsym; i < ctx->nsym; i++) {
       int pi = ctx->perm[i];
       int pi = ctx->perm[i];
       if (pi >= ctx->npc) {
       if (pi >= ctx->npc) {

+ 110 - 1
src/buildvm_x86.dasc

@@ -287,6 +287,35 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
   |  lea RA, [BASE+RA*8]
   |  lea RA, [BASE+RA*8]
   |  jmp <9
   |  jmp <9
   |
   |
+  |->gate_cwrap:			// Call gate for wrapped C functions.
+  |  // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return
+  |  mov [RA-4], PC
+  |  mov KBASE, CFUNC:RB->f
+  |  mov L:RB, SAVE_L
+  |  lea RC, [RA+NARGS:RC*8-8]
+  |  mov L:RB->base, RA
+  |  lea RA, [RC+8*LUA_MINSTACK]
+  |  mov ARG2, KBASE
+  |  mov ARG1, L:RB
+  |  mov L:RB->top, RC
+  |  cmp RA, L:RB->maxstack
+  |  ja ->gate_c_growstack		// Need to grow stack.
+  |  set_vmstate C
+  |  // (lua_State *L, lua_CFunction f)
+  |  call aword [DISPATCH+DISPATCH_GL(wrapf)]
+  |  set_vmstate INTERP
+  |  // nresults returned in eax (RD).
+  |  mov BASE, L:RB->base
+  |  lea RA, [BASE+RD*8]
+  |  neg RA
+  |  add RA, L:RB->top			// RA = (L->top-(L->base+nresults))*8
+  |->vm_returnc:
+  |  add RD, 1				// RD = nresults+1
+  |  mov NRESULTS, RD
+  |  test PC, FRAME_TYPE
+  |  jz ->BC_RET_Z			// Handle regular return to Lua.
+  |  jmp ->vm_return
+  |
   |->gate_c:				// Call gate for C functions.
   |->gate_c:				// Call gate for C functions.
   |  // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return
   |  // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return
   |  mov [RA-4], PC
   |  mov [RA-4], PC
@@ -312,6 +341,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
   |  mov NRESULTS, RD
   |  mov NRESULTS, RD
   |  test PC, FRAME_TYPE
   |  test PC, FRAME_TYPE
   |  jz ->BC_RET_Z			// Handle regular return to Lua.
   |  jz ->BC_RET_Z			// Handle regular return to Lua.
+  |  // Fallthrough.
   |
   |
   |//-- Return handling (non-inline) ---------------------------------------
   |//-- Return handling (non-inline) ---------------------------------------
   |
   |
@@ -1455,7 +1485,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
   |  mov ARG5, RA
   |  mov ARG5, RA
   |  fstp FPARG1
   |  fstp FPARG1
   |  mov RB, BASE
   |  mov RB, BASE
-  |  call extern func
+  |  call extern lj_wrapper_ .. func
   |  mov RA, ARG5
   |  mov RA, ARG5
   |  mov BASE, RB
   |  mov BASE, RB
   |  jmp ->fff_resn
   |  jmp ->fff_resn
@@ -3584,6 +3614,85 @@ static void emit_asm_debug(BuildCtx *ctx)
 	"\t.byte 0x83\n\t.uleb128 0x5\n"	/* offset ebx */
 	"\t.byte 0x83\n\t.uleb128 0x5\n"	/* offset ebx */
 	"\t.align 4\n"
 	"\t.align 4\n"
 	".LEFDE0:\n\n", (int)ctx->codesz);
 	".LEFDE0:\n\n", (int)ctx->codesz);
+    fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
+    fprintf(ctx->fp,
+	".Lframe1:\n"
+	"\t.long .LECIE1-.LSCIE1\n"
+	".LSCIE1:\n"
+	"\t.long 0\n"
+	"\t.byte 0x1\n"
+	"\t.string \"zPR\"\n"
+	"\t.uleb128 0x1\n"
+	"\t.sleb128 -4\n"
+	"\t.byte 0x8\n"
+	"\t.uleb128 6\n"			/* augmentation length */
+	"\t.byte 0x1b\n"			/* pcrel|sdata4 */
+	"\t.long lj_err_unwind_dwarf-.\n"
+	"\t.byte 0x1b\n"			/* pcrel|sdata4 */
+	"\t.byte 0xc\n\t.uleb128 0x4\n\t.uleb128 0x4\n"
+	"\t.byte 0x88\n\t.uleb128 0x1\n"
+	"\t.align 4\n"
+	".LECIE1:\n\n");
+    fprintf(ctx->fp,
+	".LSFDE1:\n"
+	"\t.long .LEFDE1-.LASFDE1\n"
+	".LASFDE1:\n"
+	"\t.long .LASFDE1-.Lframe1\n"
+	"\t.long .Lbegin-.\n"
+	"\t.long %d\n"
+	"\t.uleb128 0\n"			/* augmentation length */
+	"\t.byte 0xe\n\t.uleb128 0x30\n"	/* def_cfa_offset */
+	"\t.byte 0x85\n\t.uleb128 0x2\n"	/* offset ebp */
+	"\t.byte 0x87\n\t.uleb128 0x3\n"	/* offset edi */
+	"\t.byte 0x86\n\t.uleb128 0x4\n"	/* offset esi */
+	"\t.byte 0x83\n\t.uleb128 0x5\n"	/* offset ebx */
+	"\t.align 4\n"
+	".LEFDE1:\n\n", (int)ctx->codesz);
+    break;
+  case BUILD_machasm:
+    /* NYI: OSX ignores it. Something must be missing. */
+    fprintf(ctx->fp, "\t.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support\n");
+    fprintf(ctx->fp,
+	"EH_frame1:\n"
+	"\t.set L$set$0,LECIE1-LSCIE1\n"
+	"\t.long L$set$0\n"
+	"LSCIE1:\n"
+	"\t.long 0\n"
+	"\t.byte 0x1\n"
+	"\t.ascii \"zPR\"\n"
+	"\t.byte 0x1\n"
+	"\t.byte 128-4\n"
+	"\t.byte 0x8\n"
+	"\t.byte 6\n"				/* augmentation length */
+	"\t.byte 0x9b\n"			/* indirect|pcrel|sdata4 */
+	"\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n"
+	"\t.byte 0x1b\n"			/* pcrel|sdata4 */
+	"\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n"  /* esp=5 on 32 bit MACH-O. */
+	"\t.byte 0x88\n\t.byte 0x1\n"
+	"\t.align 2\n"
+	"LECIE1:\n\n");
+    fprintf(ctx->fp,
+	"_lj_vm_asm_begin.eh:\n"
+	"LSFDE1:\n"
+	"\t.set L$set$1,LEFDE1-LASFDE1\n"
+	"\t.long L$set$1\n"
+	"LASFDE1:\n"
+	"\t.long LASFDE1-EH_frame1\n"
+	"\t.long _lj_vm_asm_begin-.\n"
+	"\t.long %d\n"
+	"\t.byte 0\n"				/* augmentation length */
+	"\t.byte 0xe\n\t.byte 0x30\n"		/* def_cfa_offset */
+	"\t.byte 0x84\n\t.byte 0x2\n"		/* offset ebp (4 for MACH-O)*/
+	"\t.byte 0x87\n\t.byte 0x3\n"		/* offset edi */
+	"\t.byte 0x86\n\t.byte 0x4\n"		/* offset esi */
+	"\t.byte 0x83\n\t.byte 0x5\n"		/* offset ebx */
+	"\t.align 2\n"
+	"LEFDE1:\n\n", (int)ctx->codesz);
+      fprintf(ctx->fp,
+	"\t.non_lazy_symbol_pointer\n"
+	"L_lj_err_unwind_dwarf$non_lazy_ptr:\n"
+	".indirect_symbol _lj_err_unwind_dwarf\n"
+	".long 0\n");
     break;
     break;
   default:  /* Difficult for other modes. */
   default:  /* Difficult for other modes. */
     break;
     break;

+ 5 - 91
src/lib_aux.c

@@ -20,97 +20,6 @@
 #include "lj_err.h"
 #include "lj_err.h"
 #include "lj_lib.h"
 #include "lj_lib.h"
 
 
-/* convert a stack index to positive */
-#define abs_index(L, i) \
-  ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
-
-/* -- Type checks --------------------------------------------------------- */
-
-LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
-{
-  if (!lua_checkstack(L, size))
-    lj_err_callerv(L, LJ_ERR_STKOVM, msg);
-}
-
-LUALIB_API void luaL_checktype(lua_State *L, int narg, int tt)
-{
-  if (lua_type(L, narg) != tt)
-    lj_err_argt(L, narg, tt);
-}
-
-LUALIB_API void luaL_checkany(lua_State *L, int narg)
-{
-  lj_lib_checkany(L, narg);
-}
-
-LUALIB_API const char *luaL_checklstring(lua_State *L, int narg, size_t *len)
-{
-  GCstr *s = lj_lib_checkstr(L, narg);
-  if (len != NULL) *len = s->len;
-  return strdata(s);
-}
-
-LUALIB_API const char *luaL_optlstring(lua_State *L, int narg,
-				       const char *def, size_t *len)
-{
-  GCstr *s = lj_lib_optstr(L, narg);
-  if (s) {
-    if (len != NULL) *len = s->len;
-    return strdata(s);
-  }
-  if (len != NULL) *len = def ? strlen(def) : 0;
-  return def;
-}
-
-LUALIB_API lua_Number luaL_checknumber(lua_State *L, int narg)
-{
-  return lj_lib_checknum(L, narg);
-}
-
-LUALIB_API lua_Number luaL_optnumber(lua_State *L, int narg, lua_Number def)
-{
-  lj_lib_opt(L, narg,
-    return lj_lib_checknum(L, narg);
-  ,
-    return def;
-  )
-}
-
-LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int narg)
-{
-#if LJ_64
-  return (lua_Integer)lj_lib_checknum(L, narg);
-#else
-  return lj_lib_checkint(L, narg);
-#endif
-}
-
-LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int narg, lua_Integer def)
-{
-#if LJ_64
-  lj_lib_opt(L, narg,
-    return (lua_Integer)lj_lib_checknum(L, narg);
-  ,
-    return def;
-  )
-#else
-  return lj_lib_optint(L, narg, def);
-#endif
-}
-
-LUALIB_API int luaL_checkoption(lua_State *L, int narg, const char *def,
-				const char *const lst[])
-{
-  GCstr *s = lj_lib_optstr(L, narg);
-  const char *opt = s ? strdata(s) : def;
-  uint32_t i;
-  if (!opt) lj_err_argt(L, narg, LUA_TSTRING);
-  for (i = 0; lst[i]; i++)
-    if (strcmp(lst[i], opt) == 0)
-      return (int)i;
-  lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
-}
-
 /* -- Module registration ------------------------------------------------- */
 /* -- Module registration ------------------------------------------------- */
 
 
 LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
 LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
@@ -149,6 +58,7 @@ static int libsize(const luaL_Reg *l)
 LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
 LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
 			     const luaL_Reg *l, int nup)
 			     const luaL_Reg *l, int nup)
 {
 {
+  lj_lib_checkfpu(L);
   if (libname) {
   if (libname) {
     int size = libsize(l);
     int size = libsize(l);
     /* check whether lib already exists */
     /* check whether lib already exists */
@@ -285,6 +195,10 @@ LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
 
 
 #define FREELIST_REF	0
 #define FREELIST_REF	0
 
 
+/* Convert a stack index to an absolute index. */
+#define abs_index(L, i) \
+  ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
+
 LUALIB_API int luaL_ref(lua_State *L, int t)
 LUALIB_API int luaL_ref(lua_State *L, int t)
 {
 {
   int ref;
   int ref;

+ 6 - 3
src/lib_io.c

@@ -523,8 +523,11 @@ static void io_fenv_new(lua_State *L, int narr, lua_CFunction cls)
 
 
 LUALIB_API int luaopen_io(lua_State *L)
 LUALIB_API int luaopen_io(lua_State *L)
 {
 {
-  LJ_LIB_REG_(L, NULL, io_method);
-  lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+  if (tvisnil(L->top-1)) {
+    LJ_LIB_REG_(L, NULL, io_method);
+    lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+  }
   io_fenv_new(L, 0, lj_cf_io_pipe_close);  /* top-3 */
   io_fenv_new(L, 0, lj_cf_io_pipe_close);  /* top-3 */
   io_fenv_new(L, 2, lj_cf_io_file_close);  /* top-2 */
   io_fenv_new(L, 2, lj_cf_io_file_close);  /* top-2 */
   LJ_LIB_REG(L, io);
   LJ_LIB_REG(L, io);
@@ -532,7 +535,7 @@ LUALIB_API int luaopen_io(lua_State *L)
   io_std_new(L, stdin, IO_INPUT, "stdin");
   io_std_new(L, stdin, IO_INPUT, "stdin");
   io_std_new(L, stdout, IO_OUTPUT, "stdout");
   io_std_new(L, stdout, IO_OUTPUT, "stdout");
   io_std_new(L, stderr, 0, "stderr");
   io_std_new(L, stderr, 0, "stderr");
-  lua_pop(L, 1);
+  L->top--;
   return 1;
   return 1;
 }
 }
 
 

+ 3 - 2
src/lib_jit.c

@@ -73,8 +73,9 @@ LJLIB_CF(jit_flush)
 #if LJ_HASJIT
 #if LJ_HASJIT
   if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) {
   if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) {
     int traceno = lj_lib_checkint(L, 1);
     int traceno = lj_lib_checkint(L, 1);
-    luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
-    return 0;
+    setboolV(L->top-1,
+	     luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE));
+    return 1;
   }
   }
 #endif
 #endif
   return setjitmode(L, LUAJIT_MODE_FLUSH);
   return setjitmode(L, LUAJIT_MODE_FLUSH);

+ 4 - 15
src/lib_math.c

@@ -69,11 +69,9 @@ LJLIB_ASM_(math_max)		LJLIB_REC(math_minmax IR_MAX)
 LJLIB_PUSH(3.14159265358979323846) LJLIB_SET(pi)
 LJLIB_PUSH(3.14159265358979323846) LJLIB_SET(pi)
 LJLIB_PUSH(1e310) LJLIB_SET(huge)
 LJLIB_PUSH(1e310) LJLIB_SET(huge)
 
 
-#ifdef __MACH__
 LJ_FUNCA double lj_wrapper_sinh(double x) { return sinh(x); }
 LJ_FUNCA double lj_wrapper_sinh(double x) { return sinh(x); }
 LJ_FUNCA double lj_wrapper_cosh(double x) { return cosh(x); }
 LJ_FUNCA double lj_wrapper_cosh(double x) { return cosh(x); }
 LJ_FUNCA double lj_wrapper_tanh(double x) { return tanh(x); }
 LJ_FUNCA double lj_wrapper_tanh(double x) { return tanh(x); }
-#endif
 
 
 /* ------------------------------------------------------------------------ */
 /* ------------------------------------------------------------------------ */
 
 
@@ -98,8 +96,8 @@ typedef union { uint64_t u64; double d; } U64double;
   z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
   z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
   r ^= z; tw->gen[i] = z;
   r ^= z; tw->gen[i] = z;
 
 
-/* PRNG step function. Returns a double in the range 0.0 <= d < 1.0. */
-static double tw223_step(TW223State *tw)
+/* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */
+static LJ_NOINLINE double tw223_step(TW223State *tw)
 {
 {
   uint64_t z, r = 0;
   uint64_t z, r = 0;
   U64double u;
   U64double u;
@@ -108,16 +106,7 @@ static double tw223_step(TW223State *tw)
   TW223_GEN(2, 55, 24,  7)
   TW223_GEN(2, 55, 24,  7)
   TW223_GEN(3, 47, 21,  8)
   TW223_GEN(3, 47, 21,  8)
   u.u64 = (r & (((uint64_t)1 << 52)-1)) | ((uint64_t)0x3ff << 52);
   u.u64 = (r & (((uint64_t)1 << 52)-1)) | ((uint64_t)0x3ff << 52);
-#if defined(__GNUC__) && LJ_TARGET_X86 && __pic__
-  /* Compensate for unbelievable GCC pessimization. */
-  {
-    volatile U64double u1;
-    u1.u64 = (uint64_t)0x3f8 << 52;
-    return u.d - u1.d;
-  }
-#else
-  return u.d - 1.0;
-#endif
+  return u.d;
 }
 }
 
 
 /* PRNG initialization function. */
 /* PRNG initialization function. */
@@ -146,7 +135,7 @@ LJLIB_CF(math_random)
   TW223State *tw = (TW223State *)(uddata(udataV(lj_lib_upvalue(L, 1))));
   TW223State *tw = (TW223State *)(uddata(udataV(lj_lib_upvalue(L, 1))));
   double d;
   double d;
   if (LJ_UNLIKELY(!tw->valid)) tw223_init(tw, 0.0);
   if (LJ_UNLIKELY(!tw->valid)) tw223_init(tw, 0.0);
-  d = tw223_step(tw);
+  d = tw223_step(tw) - 1.0;
   if (n > 0) {
   if (n > 0) {
     double r1 = lj_lib_checknum(L, 1);
     double r1 = lj_lib_checknum(L, 1);
     if (n == 1) {
     if (n == 1) {

+ 1 - 0
src/lib_package.c

@@ -354,6 +354,7 @@ static int lj_cf_package_require(lua_State *L)
     lua_pushvalue(L, -1);  /* extra copy to be returned */
     lua_pushvalue(L, -1);  /* extra copy to be returned */
     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
   }
   }
+  lj_lib_checkfpu(L);
   return 1;
   return 1;
 }
 }
 
 

+ 5 - 2
src/lib_string.c

@@ -16,6 +16,7 @@
 #include "lualib.h"
 #include "lualib.h"
 
 
 #include "lj_obj.h"
 #include "lj_obj.h"
+#include "lj_gc.h"
 #include "lj_err.h"
 #include "lj_err.h"
 #include "lj_str.h"
 #include "lj_str.h"
 #include "lj_tab.h"
 #include "lj_tab.h"
@@ -774,6 +775,7 @@ LJLIB_CF(string_format)
 LUALIB_API int luaopen_string(lua_State *L)
 LUALIB_API int luaopen_string(lua_State *L)
 {
 {
   GCtab *mt;
   GCtab *mt;
+  GCstr *mmstr;
   LJ_LIB_REG(L, string);
   LJ_LIB_REG(L, string);
 #if defined(LUA_COMPAT_GFIND)
 #if defined(LUA_COMPAT_GFIND)
   lua_getfield(L, -1, "gmatch");
   lua_getfield(L, -1, "gmatch");
@@ -782,8 +784,9 @@ LUALIB_API int luaopen_string(lua_State *L)
   mt = lj_tab_new(L, 0, 1);
   mt = lj_tab_new(L, 0, 1);
   /* NOBARRIER: G(L)->mmname[] is a GC root. */
   /* NOBARRIER: G(L)->mmname[] is a GC root. */
   setgcref(G(L)->basemt[~LJ_TSTR], obj2gco(mt));
   setgcref(G(L)->basemt[~LJ_TSTR], obj2gco(mt));
-  settabV(L, lj_tab_setstr(L, mt, strref(G(L)->mmname[MM_index])),
-	      tabV(L->top-1));
+  mmstr = strref(G(L)->mmname[MM_index]);
+  if (isdead(G(L), obj2gco(mmstr))) flipwhite(obj2gco(mmstr));
+  settabV(L, lj_tab_setstr(L, mt, mmstr), tabV(L->top-1));
   mt->nomm = cast_byte(~(1u<<MM_index));
   mt->nomm = cast_byte(~(1u<<MM_index));
   return 1;
   return 1;
 }
 }

+ 12 - 12
src/lib_table.c

@@ -74,21 +74,21 @@ LJLIB_CF(table_maxn)
   TValue *array = tvref(t->array);
   TValue *array = tvref(t->array);
   Node *node;
   Node *node;
   lua_Number m = 0;
   lua_Number m = 0;
-  uint32_t i;
-  for (i = 0; i < t->asize; i++)
+  ptrdiff_t i;
+  for (i = (ptrdiff_t)t->asize - 1; i >= 0; i--)
     if (!tvisnil(&array[i])) {
     if (!tvisnil(&array[i])) {
-      m = (lua_Number)i;
+      m = (lua_Number)(int32_t)i;
       break;
       break;
     }
     }
   node = noderef(t->node);
   node = noderef(t->node);
-  for (i = 0; i <= t->hmask; i++)
+  for (i = (ptrdiff_t)t->hmask; i >= 0; i--)
     if (tvisnum(&node[i].key) && numV(&node[i].key) > m)
     if (tvisnum(&node[i].key) && numV(&node[i].key) > m)
       m = numV(&node[i].key);
       m = numV(&node[i].key);
   setnumV(L->top-1, m);
   setnumV(L->top-1, m);
   return 1;
   return 1;
 }
 }
 
 
-LJLIB_CF(table_insert)
+LJLIB_CF(table_insert)		LJLIB_REC(.)
 {
 {
   GCtab *t = lj_lib_checktab(L, 1);
   GCtab *t = lj_lib_checktab(L, 1);
   int32_t n, i = (int32_t)lj_tab_len(t) + 1;
   int32_t n, i = (int32_t)lj_tab_len(t) + 1;
@@ -111,20 +111,20 @@ LJLIB_CF(table_insert)
   }
   }
   {
   {
     TValue *dst = lj_tab_setint(L, t, i);
     TValue *dst = lj_tab_setint(L, t, i);
-    copyTV(L, dst, L->top-1);
+    copyTV(L, dst, L->top-1);  /* Set new value. */
     lj_gc_barriert(L, t, dst);
     lj_gc_barriert(L, t, dst);
   }
   }
   return 0;
   return 0;
 }
 }
 
 
-LJLIB_CF(table_remove)
+LJLIB_CF(table_remove)		LJLIB_REC(.)
 {
 {
   GCtab *t = lj_lib_checktab(L, 1);
   GCtab *t = lj_lib_checktab(L, 1);
   int32_t e = (int32_t)lj_tab_len(t);
   int32_t e = (int32_t)lj_tab_len(t);
   int32_t pos = lj_lib_optint(L, 2, e);
   int32_t pos = lj_lib_optint(L, 2, e);
-  if (!(1 <= pos && pos <= e))  /* position is outside bounds? */
-    return 0;  /* nothing to remove */
-  lua_rawgeti(L, 1, pos);
+  if (!(1 <= pos && pos <= e))  /* Nothing to remove? */
+    return 0;
+  lua_rawgeti(L, 1, pos);  /* Get previous value. */
   /* NOBARRIER: This just moves existing elements around. */
   /* NOBARRIER: This just moves existing elements around. */
   for (; pos < e; pos++) {
   for (; pos < e; pos++) {
     cTValue *src = lj_tab_getint(t, pos+1);
     cTValue *src = lj_tab_getint(t, pos+1);
@@ -135,8 +135,8 @@ LJLIB_CF(table_remove)
       setnilV(dst);
       setnilV(dst);
     }
     }
   }
   }
-  setnilV(lj_tab_setint(L, t, e));
-  return 1;
+  setnilV(lj_tab_setint(L, t, e));  /* Remove (last) value. */
+  return 1;  /* Return previous value. */
 }
 }
 
 
 LJLIB_CF(table_concat)
 LJLIB_CF(table_concat)

+ 134 - 2
src/lj_api.c

@@ -91,6 +91,12 @@ LUA_API int lua_checkstack(lua_State *L, int size)
   return 1;
   return 1;
 }
 }
 
 
+LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
+{
+  if (!lua_checkstack(L, size))
+    lj_err_callerv(L, LJ_ERR_STKOVM, msg);
+}
+
 LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
 LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
 {
 {
   TValue *f, *t;
   TValue *f, *t;
@@ -193,6 +199,18 @@ LUA_API int lua_type(lua_State *L, int idx)
   }
   }
 }
 }
 
 
+LUALIB_API void luaL_checktype(lua_State *L, int idx, int tt)
+{
+  if (lua_type(L, idx) != tt)
+    lj_err_argt(L, idx, tt);
+}
+
+LUALIB_API void luaL_checkany(lua_State *L, int idx)
+{
+  if (index2adr(L, idx) == niltv(L))
+    lj_err_arg(L, idx, LJ_ERR_NOVAL);
+}
+
 LUA_API const char *lua_typename(lua_State *L, int t)
 LUA_API const char *lua_typename(lua_State *L, int t)
 {
 {
   UNUSED(L);
   UNUSED(L);
@@ -202,7 +220,7 @@ LUA_API const char *lua_typename(lua_State *L, int t)
 LUA_API int lua_iscfunction(lua_State *L, int idx)
 LUA_API int lua_iscfunction(lua_State *L, int idx)
 {
 {
   cTValue *o = index2adr(L, idx);
   cTValue *o = index2adr(L, idx);
-  return !isluafunc(funcV(o));
+  return tvisfunc(o) && !isluafunc(funcV(o));
 }
 }
 
 
 LUA_API int lua_isnumber(lua_State *L, int idx)
 LUA_API int lua_isnumber(lua_State *L, int idx)
@@ -295,6 +313,30 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
     return 0;
     return 0;
 }
 }
 
 
+LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
+{
+  cTValue *o = index2adr(L, idx);
+  TValue tmp;
+  if (tvisnum(o))
+    return numV(o);
+  else if (!(tvisstr(o) && lj_str_numconv(strVdata(o), &tmp)))
+    lj_err_argt(L, idx, LUA_TNUMBER);
+  return numV(&tmp);
+}
+
+LUALIB_API lua_Number luaL_optnumber(lua_State *L, int idx, lua_Number def)
+{
+  cTValue *o = index2adr(L, idx);
+  TValue tmp;
+  if (tvisnum(o))
+    return numV(o);
+  else if (tvisnil(o))
+    return def;
+  else if (!(tvisstr(o) && lj_str_numconv(strVdata(o), &tmp)))
+    lj_err_argt(L, idx, LUA_TNUMBER);
+  return numV(&tmp);
+}
+
 LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
 LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
 {
 {
   cTValue *o = index2adr(L, idx);
   cTValue *o = index2adr(L, idx);
@@ -313,6 +355,44 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
 #endif
 #endif
 }
 }
 
 
+LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
+{
+  cTValue *o = index2adr(L, idx);
+  TValue tmp;
+  lua_Number n;
+  if (LJ_LIKELY(tvisnum(o)))
+    n = numV(o);
+  else if (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp))
+    n = numV(&tmp);
+  else
+    lj_err_argt(L, idx, LUA_TNUMBER);
+#if LJ_64
+  return (lua_Integer)n;
+#else
+  return lj_num2int(n);
+#endif
+}
+
+LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def)
+{
+  cTValue *o = index2adr(L, idx);
+  TValue tmp;
+  lua_Number n;
+  if (LJ_LIKELY(tvisnum(o)))
+    n = numV(o);
+  else if (tvisnil(o))
+    return def;
+  else if (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp))
+    n = numV(&tmp);
+  else
+    lj_err_argt(L, idx, LUA_TNUMBER);
+#if LJ_64
+  return (lua_Integer)n;
+#else
+  return lj_num2int(n);
+#endif
+}
+
 LUA_API int lua_toboolean(lua_State *L, int idx)
 LUA_API int lua_toboolean(lua_State *L, int idx)
 {
 {
   cTValue *o = index2adr(L, idx);
   cTValue *o = index2adr(L, idx);
@@ -337,6 +417,57 @@ LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
   return strdata(s);
   return strdata(s);
 }
 }
 
 
+LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len)
+{
+  TValue *o = index2adr(L, idx);
+  GCstr *s;
+  if (LJ_LIKELY(tvisstr(o))) {
+    s = strV(o);
+  } else if (tvisnum(o)) {
+    lj_gc_check(L);
+    o = index2adr(L, idx);  /* GC may move the stack. */
+    s = lj_str_fromnum(L, &o->n);
+  } else {
+    lj_err_argt(L, idx, LUA_TSTRING);
+  }
+  if (len != NULL) *len = s->len;
+  return strdata(s);
+}
+
+LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
+				       const char *def, size_t *len)
+{
+  TValue *o = index2adr(L, idx);
+  GCstr *s;
+  if (LJ_LIKELY(tvisstr(o))) {
+    s = strV(o);
+  } else if (tvisnil(o)) {
+    if (len != NULL) *len = def ? strlen(def) : 0;
+    return def;
+  } else if (tvisnum(o)) {
+    lj_gc_check(L);
+    o = index2adr(L, idx);  /* GC may move the stack. */
+    s = lj_str_fromnum(L, &o->n);
+  } else {
+    lj_err_argt(L, idx, LUA_TSTRING);
+  }
+  if (len != NULL) *len = s->len;
+  return strdata(s);
+}
+
+LUALIB_API int luaL_checkoption(lua_State *L, int idx, const char *def,
+				const char *const lst[])
+{
+  ptrdiff_t i;
+  const char *s = lua_tolstring(L, idx, NULL);
+  if (s == NULL && (s = def) == NULL)
+    lj_err_argt(L, idx, LUA_TSTRING);
+  for (i = 0; lst[i]; i++)
+    if (strcmp(lst[i], s) == 0)
+      return (int)i;
+  lj_err_argv(L, idx, LJ_ERR_INVOPTM, s);
+}
+
 LUA_API size_t lua_objlen(lua_State *L, int idx)
 LUA_API size_t lua_objlen(lua_State *L, int idx)
 {
 {
   TValue *o = index2adr(L, idx);
   TValue *o = index2adr(L, idx);
@@ -355,7 +486,8 @@ LUA_API size_t lua_objlen(lua_State *L, int idx)
 LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx)
 LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx)
 {
 {
   cTValue *o = index2adr(L, idx);
   cTValue *o = index2adr(L, idx);
-  return funcV(o)->c.gate == lj_gate_c ? funcV(o)->c.f : NULL;
+  ASMFunction gate = funcV(o)->c.gate;
+  return (gate == lj_gate_c || gate == lj_gate_cwrap) ? funcV(o)->c.f : NULL;
 }
 }
 
 
 LUA_API void *lua_touserdata(lua_State *L, int idx)
 LUA_API void *lua_touserdata(lua_State *L, int idx)

+ 7 - 4
src/lj_asm.c

@@ -738,11 +738,14 @@ static Reg ra_allocref(ASMState *as, IRRef ref, RegSet allow)
       }
       }
       RA_DBGX((as, "hintmiss  $f $r", ref, r));
       RA_DBGX((as, "hintmiss  $f $r", ref, r));
     }
     }
-    /* Invariants should preferably get unused registers. */
-    if (ref < as->loopref && !irt_isphi(ir->t))
-      r = rset_pickbot(pick);
-    else
+    /* Invariants should preferably get unmodified registers. */
+    if (ref < as->loopref && !irt_isphi(ir->t)) {
+      if ((pick & ~as->modset))
+	pick &= ~as->modset;
+      r = rset_pickbot(pick);  /* Reduce conflicts with inverse allocation. */
+    } else {
       r = rset_picktop(pick);
       r = rset_picktop(pick);
+    }
   } else {
   } else {
     r = ra_evict(as, allow);
     r = ra_evict(as, allow);
   }
   }

+ 15 - 2
src/lj_dispatch.c

@@ -153,8 +153,7 @@ int luaJIT_setmode(lua_State *L, int idx, int mode)
   case LUAJIT_MODE_TRACE:
   case LUAJIT_MODE_TRACE:
     if (!(mode & LUAJIT_MODE_FLUSH))
     if (!(mode & LUAJIT_MODE_FLUSH))
       return 0;  /* Failed. */
       return 0;  /* Failed. */
-    lj_trace_flush(G2J(g), idx);
-    break;
+    return lj_trace_flush(G2J(g), idx);
 #else
 #else
   case LUAJIT_MODE_ENGINE:
   case LUAJIT_MODE_ENGINE:
   case LUAJIT_MODE_FUNC:
   case LUAJIT_MODE_FUNC:
@@ -165,6 +164,20 @@ int luaJIT_setmode(lua_State *L, int idx, int mode)
       return 0;  /* Failed. */
       return 0;  /* Failed. */
     break;
     break;
 #endif
 #endif
+  case LUAJIT_MODE_WRAPCFUNC:
+    if ((mode & LUAJIT_MODE_ON)) {
+      if (idx != 0) {
+	cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx;
+	if (tvislightud(tv) && lightudV(tv) != NULL)
+	  g->wrapf = (lua_CFunction)lightudV(tv);
+	else
+	  return 0;  /* Failed. */
+      }
+      g->wrapmode = 1;
+    } else {
+      g->wrapmode = 0;
+    }
+    break;
   default:
   default:
     return 0;  /* Failed. */
     return 0;  /* Failed. */
   }
   }

+ 46 - 0
src/lj_err.c

@@ -676,6 +676,8 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg,
 {
 {
   const char *fname = "?";
   const char *fname = "?";
   const char *ftype = getfuncname(L, L->base - 1, &fname);
   const char *ftype = getfuncname(L, L->base - 1, &fname);
+  if (narg < 0 && narg > LUA_REGISTRYINDEX)
+    narg = (L->top - L->base) + narg + 1;
   if (ftype && ftype[3] == 'h' && --narg == 0)  /* Check for "method". */
   if (ftype && ftype[3] == 'h' && --narg == 0)  /* Check for "method". */
     msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg);
     msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg);
   else
   else
@@ -761,3 +763,47 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)
   return 0;  /* unreachable */
   return 0;  /* unreachable */
 }
 }
 
 
+/* -- C++ exception support ----------------------------------------------- */
+
+#if defined(__ELF__) || defined(__MACH__)
+typedef enum
+{
+  _URC_NO_REASON,
+  _URC_FOREIGN_EXCEPTION_CAUGHT,
+  _URC_FATAL_PHASE2_ERROR,
+  _URC_FATAL_PHASE1_ERROR,
+  _URC_NORMAL_STOP,
+  _URC_END_OF_STACK,
+  _URC_HANDLER_FOUND,
+  _URC_INSTALL_CONTEXT,
+  _URC_CONTINUE_UNWIND
+} _Unwind_Reason_Code;
+
+#define _UA_SEARCH_PHASE	1
+#define _UA_CLEANUP_PHASE	2
+#define _UA_HANDLER_FRAME	4
+#define _UA_FORCE_UNWIND	8
+#define _UA_END_OF_STACK	16
+
+extern void *_Unwind_GetCFA(void *ctx);
+extern void _Unwind_DeleteException(void *uex);
+
+/* DWARF2 personality handler referenced from .eh_frame. */
+LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, uint64_t uexclass,
+				 void *uex, void *ctx)
+{
+  if (version != 1)
+    return _URC_FATAL_PHASE1_ERROR;
+  UNUSED(uexclass);
+  if ((actions & _UA_SEARCH_PHASE))
+    return _URC_HANDLER_FOUND;
+  if ((actions & _UA_HANDLER_FRAME)) {
+    void *cf = _Unwind_GetCFA(ctx);
+    lua_State *L = cframe_L(cf);
+    _Unwind_DeleteException(uex);
+    lj_err_msg(L, LJ_ERR_ERRCPP);
+  }
+  return _URC_CONTINUE_UNWIND;
+}
+#endif
+

+ 4 - 0
src/lj_errmsg.h

@@ -8,6 +8,7 @@
 /* Basic error handling. */
 /* Basic error handling. */
 ERRDEF(ERRMEM,	"not enough memory")
 ERRDEF(ERRMEM,	"not enough memory")
 ERRDEF(ERRERR,	"error in error handling")
 ERRDEF(ERRERR,	"error in error handling")
+ERRDEF(ERRCPP,	"C++ exception")
 
 
 /* Allocations. */
 /* Allocations. */
 ERRDEF(STROV,	"string length overflow")
 ERRDEF(STROV,	"string length overflow")
@@ -56,6 +57,9 @@ ERRDEF(NOENV,	"no calling environment")
 ERRDEF(CYIELD,	"attempt to yield across C-call boundary")
 ERRDEF(CYIELD,	"attempt to yield across C-call boundary")
 ERRDEF(BADLU,	"bad light userdata pointer")
 ERRDEF(BADLU,	"bad light userdata pointer")
 ERRDEF(NOGCMM,	"bad action while in __gc metamethod")
 ERRDEF(NOGCMM,	"bad action while in __gc metamethod")
+#ifdef LUA_USE_WIN
+ERRDEF(BADFPU,	"bad FPU precision (use D3DCREATE_FPU_PRESERVE with DirectX)")
+#endif
 
 
 /* Standard library function errors. */
 /* Standard library function errors. */
 ERRDEF(ASSERT,	"assertion failed!")
 ERRDEF(ASSERT,	"assertion failed!")

+ 1 - 1
src/lj_func.c

@@ -138,7 +138,7 @@ GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env)
   fn->c.nupvalues = cast_byte(nelems);
   fn->c.nupvalues = cast_byte(nelems);
   /* NOBARRIER: The GCfunc is new (marked white). */
   /* NOBARRIER: The GCfunc is new (marked white). */
   setgcref(fn->c.env, obj2gco(env));
   setgcref(fn->c.env, obj2gco(env));
-  fn->c.gate = lj_gate_c;
+  fn->c.gate = G(L)->wrapmode ? lj_gate_cwrap : lj_gate_c;
   return fn;
   return fn;
 }
 }
 
 

+ 1 - 2
src/lj_gc.c

@@ -230,8 +230,7 @@ static void gc_traverse_trace(global_State *g, Trace *T)
 
 
 /* The current trace is a GC root while not anchored in the prototype (yet). */
 /* The current trace is a GC root while not anchored in the prototype (yet). */
 #define gc_mark_curtrace(g) \
 #define gc_mark_curtrace(g) \
-  { if (G2J(g)->state != LJ_TRACE_IDLE && G2J(g)->curtrace != 0) \
-    gc_traverse_trace(g, &G2J(g)->cur); }
+  { if (G2J(g)->curtrace != 0) gc_traverse_trace(g, &G2J(g)->cur); }
 #else
 #else
 #define gc_mark_curtrace(g)	UNUSED(g)
 #define gc_mark_curtrace(g)	UNUSED(g)
 #endif
 #endif

+ 1 - 0
src/lj_ir.c

@@ -252,6 +252,7 @@ TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t)
 {
 {
   IRIns *ir, *cir = J->cur.ir;
   IRIns *ir, *cir = J->cur.ir;
   IRRef ref;
   IRRef ref;
+  lua_assert(!isdead(J2G(J), o));
   for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev)
   for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev)
     if (ir_kgc(&cir[ref]) == o)
     if (ir_kgc(&cir[ref]) == o)
       goto found;
       goto found;

+ 9 - 0
src/lj_lib.h

@@ -48,6 +48,15 @@ LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst);
 #define lj_lib_upvalue(L, n) \
 #define lj_lib_upvalue(L, n) \
   (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1])
   (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1])
 
 
+#ifdef LUA_USE_WIN
+#define lj_lib_checkfpu(L) \
+  do { setnumV(L->top++, (lua_Number)1437217655); \
+    if (lua_tointeger(L, -1) != 1437217655) lj_err_caller(L, LJ_ERR_BADFPU); \
+    L->top--; } while (0)
+#else
+#define lj_lib_checkfpu(L)	UNUSED(L)
+#endif
+
 /* Library function declarations. Scanned by buildvm. */
 /* Library function declarations. Scanned by buildvm. */
 #define LJLIB_CF(name)		static int lj_cf_##name(lua_State *L)
 #define LJLIB_CF(name)		static int lj_cf_##name(lua_State *L)
 #define LJLIB_ASM(name)		static int lj_ffh_##name(lua_State *L)
 #define LJLIB_ASM(name)		static int lj_ffh_##name(lua_State *L)

+ 2 - 1
src/lj_obj.h

@@ -531,7 +531,7 @@ typedef struct global_State {
   uint8_t hookmask;	/* Hook mask. */
   uint8_t hookmask;	/* Hook mask. */
   uint8_t dispatchmode;	/* Dispatch mode. */
   uint8_t dispatchmode;	/* Dispatch mode. */
   uint8_t vmevmask;	/* VM event mask. */
   uint8_t vmevmask;	/* VM event mask. */
-  uint8_t unused1;
+  uint8_t wrapmode;	/* Wrap mode. */
   GCRef mainthref;	/* Link to main thread. */
   GCRef mainthref;	/* Link to main thread. */
   TValue registrytv;	/* Anchor for registry. */
   TValue registrytv;	/* Anchor for registry. */
   TValue tmptv;		/* Temporary TValue. */
   TValue tmptv;		/* Temporary TValue. */
@@ -539,6 +539,7 @@ typedef struct global_State {
   int32_t hookcount;	/* Instruction hook countdown. */
   int32_t hookcount;	/* Instruction hook countdown. */
   int32_t hookcstart;	/* Start count for instruction hook counter. */
   int32_t hookcstart;	/* Start count for instruction hook counter. */
   lua_Hook hookf;	/* Hook function. */
   lua_Hook hookf;	/* Hook function. */
+  lua_CFunction wrapf;	/* Wrapper for C function calls. */
   lua_CFunction panic;	/* Called as a last resort for errors. */
   lua_CFunction panic;	/* Called as a last resort for errors. */
   volatile int32_t vmstate;  /* VM state or current JIT code trace number. */
   volatile int32_t vmstate;  /* VM state or current JIT code trace number. */
   GCRef jit_L;		/* Current JIT code lua_State or NULL. */
   GCRef jit_L;		/* Current JIT code lua_State or NULL. */

+ 4 - 4
src/lj_opt_fold.c

@@ -138,7 +138,7 @@ typedef IRRef (LJ_FASTCALL *FoldFunc)(jit_State *J);
 /* Macros for the fold specs, so buildvm can recognize them. */
 /* Macros for the fold specs, so buildvm can recognize them. */
 #define LJFOLD(x)
 #define LJFOLD(x)
 #define LJFOLDX(x)
 #define LJFOLDX(x)
-#define LJFOLDF(name)	static TRef LJ_FASTCALL name(jit_State *J)
+#define LJFOLDF(name)	static TRef LJ_FASTCALL fold_##name(jit_State *J)
 /* Note: They must be at the start of a line or buildvm ignores them! */
 /* Note: They must be at the start of a line or buildvm ignores them! */
 
 
 /* Barrier to prevent using operands across PHIs. */
 /* Barrier to prevent using operands across PHIs. */
@@ -979,7 +979,7 @@ LJFOLDF(comm_equal)
   /* For non-numbers only: x == x ==> drop; x ~= x ==> fail */
   /* For non-numbers only: x == x ==> drop; x ~= x ==> fail */
   if (fins->op1 == fins->op2 && !irt_isnum(fins->t))
   if (fins->op1 == fins->op2 && !irt_isnum(fins->t))
     return CONDFOLD(fins->o == IR_EQ);
     return CONDFOLD(fins->o == IR_EQ);
-  return comm_swap(J);
+  return fold_comm_swap(J);
 }
 }
 
 
 LJFOLD(LT any any)
 LJFOLD(LT any any)
@@ -1013,7 +1013,7 @@ LJFOLDF(comm_dup)
 {
 {
   if (fins->op1 == fins->op2)  /* x o x ==> x */
   if (fins->op1 == fins->op2)  /* x o x ==> x */
     return LEFTFOLD;
     return LEFTFOLD;
-  return comm_swap(J);
+  return fold_comm_swap(J);
 }
 }
 
 
 LJFOLD(BXOR any any)
 LJFOLD(BXOR any any)
@@ -1021,7 +1021,7 @@ LJFOLDF(comm_bxor)
 {
 {
   if (fins->op1 == fins->op2)  /* i xor i ==> 0 */
   if (fins->op1 == fins->op2)  /* i xor i ==> 0 */
     return INTFOLD(0);
     return INTFOLD(0);
-  return comm_swap(J);
+  return fold_comm_swap(J);
 }
 }
 
 
 /* -- Simplification of compound expressions ------------------------------ */
 /* -- Simplification of compound expressions ------------------------------ */

+ 1 - 1
src/lj_opt_loop.c

@@ -286,7 +286,7 @@ static void loop_unroll(jit_State *J)
 	if (!irt_sametype(t, irr->t)) {
 	if (!irt_sametype(t, irr->t)) {
 	  if (irt_isnum(t) && irt_isinteger(irr->t))  /* Fix int->num case. */
 	  if (irt_isnum(t) && irt_isinteger(irr->t))  /* Fix int->num case. */
 	    subst[ins] = tref_ref(emitir(IRTN(IR_TONUM), ref, 0));
 	    subst[ins] = tref_ref(emitir(IRTN(IR_TONUM), ref, 0));
-	  else
+	  else if (!(irt_isinteger(t) && irt_isinteger(irr->t)))
 	    lj_trace_err(J, LJ_TRERR_TYPEINS);
 	    lj_trace_err(J, LJ_TRERR_TYPEINS);
 	}
 	}
       }
       }

+ 2 - 2
src/lj_opt_mem.c

@@ -519,8 +519,8 @@ int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref)
     } else if (irt_isnil(store->t)) {  /* Must check any nil store. */
     } else if (irt_isnil(store->t)) {  /* Must check any nil store. */
       IRRef skref = IR(store->op1)->op2;
       IRRef skref = IR(store->op1)->op2;
       IRRef xkref = IR(xref)->op2;
       IRRef xkref = IR(xref)->op2;
-      /* Same key type MAY alias. */
-      if (irt_sametype(IR(skref)->t, IR(xkref)->t)) {
+      /* Same key type MAY alias. Need ALOAD check due to multiple int types. */
+      if (loadop == IR_ALOAD || irt_sametype(IR(skref)->t, IR(xkref)->t)) {
 	if (skref == xkref || !irref_isk(skref) || !irref_isk(xkref))
 	if (skref == xkref || !irref_isk(skref) || !irref_isk(xkref))
 	  return 0;  /* A nil store with same const key or var key MAY alias. */
 	  return 0;  /* A nil store with same const key or var key MAY alias. */
 	/* Different const keys CANNOT alias. */
 	/* Different const keys CANNOT alias. */

+ 62 - 8
src/lj_record.c

@@ -168,8 +168,8 @@ static int rec_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv)
 {
 {
   int diff = !lj_obj_equal(av, bv);
   int diff = !lj_obj_equal(av, bv);
   if (!tref_isk2(a, b)) {  /* Shortcut, also handles primitives. */
   if (!tref_isk2(a, b)) {  /* Shortcut, also handles primitives. */
-    IRType ta = tref_type(a);
-    IRType tb = tref_type(b);
+    IRType ta = tref_isinteger(a) ? IRT_INT : tref_type(a);
+    IRType tb = tref_isinteger(b) ? IRT_INT : tref_type(b);
     if (ta != tb) {
     if (ta != tb) {
       /* Widen mixed number/int comparisons to number/number comparison. */
       /* Widen mixed number/int comparisons to number/number comparison. */
       if (ta == IRT_INT && tb == IRT_NUM) {
       if (ta == IRT_INT && tb == IRT_NUM) {
@@ -447,7 +447,7 @@ static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
     mix.tab = lj_ir_ktab(J, mt);
     mix.tab = lj_ir_ktab(J, mt);
     goto nocheck;
     goto nocheck;
   }
   }
-  ix->mt = mix.tab;
+  ix->mt = mt ? mix.tab : TREF_NIL;
   emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB));
   emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB));
 nocheck:
 nocheck:
   if (mt) {
   if (mt) {
@@ -457,6 +457,8 @@ nocheck:
       copyTV(J->L, &ix->mobjv, mo);
       copyTV(J->L, &ix->mobjv, mo);
     ix->mtv = mt;
     ix->mtv = mt;
     settabV(J->L, &mix.tabv, mt);
     settabV(J->L, &mix.tabv, mt);
+    if (isdead(J2G(J), obj2gco(mmstr)))
+      flipwhite(obj2gco(mmstr));  /* Need same logic as lj_str_new(). */
     setstrV(J->L, &mix.keyv, mmstr);
     setstrV(J->L, &mix.keyv, mmstr);
     mix.key = lj_ir_kstr(J, mmstr);
     mix.key = lj_ir_kstr(J, mmstr);
     mix.val = 0;
     mix.val = 0;
@@ -880,7 +882,7 @@ static void recff_nyi(jit_State *J, TRef *res, RecordFFData *rd)
   lj_trace_err_info(J, LJ_TRERR_NYIFF);
   lj_trace_err_info(J, LJ_TRERR_NYIFF);
 }
 }
 
 
-LJ_NORET static void recff_err_ffu(jit_State *J, RecordFFData *rd)
+LJ_NORET static void recff_err_nyi(jit_State *J, RecordFFData *rd)
 {
 {
   setfuncV(J->L, &J->errinfo, rd->fn);
   setfuncV(J->L, &J->errinfo, rd->fn);
   lj_trace_err_info(J, LJ_TRERR_NYIFFU);
   lj_trace_err_info(J, LJ_TRERR_NYIFFU);
@@ -986,7 +988,7 @@ static void recff_tonumber(jit_State *J, TRef *res, RecordFFData *rd)
     if (arg[1]) {
     if (arg[1]) {
       TRef base = lj_ir_toint(J, arg[1]);
       TRef base = lj_ir_toint(J, arg[1]);
       if (!tref_isk(base) || IR(tref_ref(base))->i != 10)
       if (!tref_isk(base) || IR(tref_ref(base))->i != 10)
-	recff_err_ffu(J, rd);
+	recff_err_nyi(J, rd);
     }
     }
     if (tref_isstr(tr))
     if (tref_isstr(tr))
       tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
       tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
@@ -1016,7 +1018,7 @@ static void recff_tostring(jit_State *J, TRef *res, RecordFFData *rd)
     } else if (tref_isnumber(tr)) {
     } else if (tref_isnumber(tr)) {
       res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
       res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
     } else {
     } else {
-      recff_err_ffu(J, rd);
+      recff_err_nyi(J, rd);
     }
     }
   }
   }
 }
 }
@@ -1338,6 +1340,58 @@ static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd)
   UNUSED(rd);
   UNUSED(rd);
 }
 }
 
 
+static void recff_table_remove(jit_State *J, TRef *res, RecordFFData *rd)
+{
+  if (tref_istab(arg[0])) {
+    if (!arg[1] || tref_isnil(arg[1])) {  /* Simple pop: t[#t] = nil */
+      TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0);
+      GCtab *t = tabV(&rd->argv[0]);
+      MSize len = lj_tab_len(t);
+      emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0));
+      if (len) {
+	RecordIndex ix;
+	ix.tab = arg[0];
+	ix.key = trlen;
+	settabV(J->L, &ix.tabv, t);
+	setintV(&ix.keyv, len);
+	ix.idxchain = 0;
+	if (rd->cres != 0) {  /* Specialize load only if result needed. */
+	  ix.val = 0;
+	  res[0] = rec_idx(J, &ix);  /* Load previous value. */
+	  /* Assumes ix.key/ix.tab is not modified for raw rec_idx(). */
+	}
+	ix.val = TREF_NIL;
+	rec_idx(J, &ix);  /* Remove value. */
+      } else {
+	rd->nres = 0;
+      }
+    } else {  /* Complex case: remove in the middle. */
+      recff_err_nyi(J, rd);
+    }
+  }  /* else: Interpreter will throw. */
+}
+
+static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd)
+{
+  rd->nres = 0;
+  if (tref_istab(arg[0]) && arg[1]) {
+    if (!arg[2]) {  /* Simple push: t[#t+1] = v */
+      TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0);
+      GCtab *t = tabV(&rd->argv[0]);
+      RecordIndex ix;
+      ix.tab = arg[0];
+      ix.val = arg[1];
+      ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
+      settabV(J->L, &ix.tabv, t);
+      setintV(&ix.keyv, lj_tab_len(t) + 1);
+      ix.idxchain = 0;
+      rec_idx(J, &ix);  /* Set new value. */
+    } else {  /* Complex case: insert in the middle. */
+      recff_err_nyi(J, rd);
+    }
+  }  /* else: Interpreter will throw. */
+}
+
 /* -- Record calls and returns -------------------------------------------- */
 /* -- Record calls and returns -------------------------------------------- */
 
 
 #undef arg
 #undef arg
@@ -1618,8 +1672,8 @@ void lj_record_ins(jit_State *J)
   case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
   case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
     /* Emit nothing for two numeric or string consts. */
     /* Emit nothing for two numeric or string consts. */
     if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
     if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
-      IRType ta = tref_type(ra);
-      IRType tc = tref_type(rc);
+      IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
+      IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc);
       int irop;
       int irop;
       if (ta != tc) {
       if (ta != tc) {
 	/* Widen mixed number/int comparisons to number/number comparison. */
 	/* Widen mixed number/int comparisons to number/number comparison. */

+ 2 - 2
src/lj_tab.c

@@ -191,8 +191,8 @@ GCtab *lj_tab_dup(lua_State *L, const GCtab *kt)
       Node *kn = &knode[i];
       Node *kn = &knode[i];
       Node *n = &node[i];
       Node *n = &node[i];
       Node *next = nextnode(kn);
       Node *next = nextnode(kn);
-      copyTV(L, &n->val, &kn->val);
-      copyTV(L, &n->key, &kn->key);
+      /* Don't use copyTV here, since it asserts on a copy of a DEADKEY. */
+      n->val = kn->val; n->key = kn->key;
       setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
       setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
     }
     }
   }
   }

+ 48 - 34
src/lj_trace.c

@@ -191,47 +191,58 @@ static void trace_unpatch(jit_State *J, Trace *T)
   }
   }
 }
 }
 
 
-/* Flush a root trace and any attached side traces. */
-void lj_trace_flush(jit_State *J, TraceNo traceno)
+/* Free a root trace and any attached side traces. */
+static void trace_freeroot(jit_State *J, Trace *T, TraceNo traceno)
 {
 {
-  Trace *T = NULL;
-  GCproto *pt;
-  if (traceno > 0 && traceno <= J->sizetrace)
-    T = J->trace[traceno];
-  if (T == NULL)
-    return;
-  pt = &gcref(T->startpt)->pt;
-  if (T->root == 0 && pt != NULL) {
-    TraceNo side;
-    /* First unpatch any modified bytecode. */
-    trace_unpatch(J, T);
-    /* Unlink root trace from chain anchored in prototype. */
-    if (pt->trace == traceno) {  /* Trace is first in chain. Easy. */
-      pt->trace = T->nextroot;
-    } else {  /* Otherwise search in chain of root traces. */
-      Trace *T2 = J->trace[pt->trace];
-      while (T2->nextroot != traceno) {
-	lua_assert(T2->nextroot != 0);
-	T2 = J->trace[T2->nextroot];
-      }
-      T2->nextroot = T->nextroot;  /* Unlink from chain. */
+  GCproto *pt = &gcref(T->startpt)->pt;
+  TraceNo side;
+  lua_assert(T->root == 0 && pt != NULL);
+  /* First unpatch any modified bytecode. */
+  trace_unpatch(J, T);
+  /* Unlink root trace from chain anchored in prototype. */
+  if (pt->trace == traceno) {  /* Trace is first in chain. Easy. */
+    pt->trace = T->nextroot;
+  } else {  /* Otherwise search in chain of root traces. */
+    Trace *T2 = J->trace[pt->trace];
+    while (T2->nextroot != traceno) {
+      lua_assert(T2->nextroot != 0);
+      T2 = J->trace[T2->nextroot];
     }
     }
-    /* Free all side traces. */
-    for (side = T->nextside; side != 0; ) {
-      TraceNo next = J->trace[side]->nextside;
-      trace_free(J, side);
-      side = next;
+    T2->nextroot = T->nextroot;  /* Unlink from chain. */
+  }
+  /* Free all side traces. */
+  for (side = T->nextside; side != 0; ) {
+    TraceNo next = J->trace[side]->nextside;
+    trace_free(J, side);
+    side = next;
+  }
+  /* Now free the trace itself. */
+  trace_free(J, traceno);
+}
+
+/* Flush a root trace + side traces, if there are no links to it. */
+int lj_trace_flush(jit_State *J, TraceNo traceno)
+{
+  if (traceno > 0 && traceno < J->sizetrace) {
+    Trace *T = J->trace[traceno];
+    if (T && T->root == 0) {
+      ptrdiff_t i;
+      for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--)
+	if (i != (ptrdiff_t)traceno && J->trace[i] &&
+	    J->trace[i]->root != traceno && J->trace[i]->link == traceno)
+	  return 0;  /* Failed: existing link to trace. */
+      trace_freeroot(J, T, traceno);
+      return 1;  /* Ok. */
     }
     }
-    /* Now free the trace itself. */
-    trace_free(J, traceno);
-  }  /* Flush for non-root traces is currently ignored. */
+  }
+  return 0;  /* Failed. */
 }
 }
 
 
 /* Flush all traces associated with a prototype. */
 /* Flush all traces associated with a prototype. */
 void lj_trace_flushproto(global_State *g, GCproto *pt)
 void lj_trace_flushproto(global_State *g, GCproto *pt)
 {
 {
   while (pt->trace != 0)
   while (pt->trace != 0)
-    lj_trace_flush(G2J(g), pt->trace);
+    trace_freeroot(G2J(g), G2J(g)->trace[pt->trace], pt->trace);
 }
 }
 
 
 /* Flush all traces. */
 /* Flush all traces. */
@@ -241,8 +252,11 @@ int lj_trace_flushall(lua_State *L)
   ptrdiff_t i;
   ptrdiff_t i;
   if ((J2G(J)->hookmask & HOOK_GC))
   if ((J2G(J)->hookmask & HOOK_GC))
     return 1;
     return 1;
-  for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--)
-    lj_trace_flush(J, (TraceNo)i);
+  for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) {
+    Trace *T = J->trace[i];
+    if (T && T->root == 0)
+      trace_freeroot(J, T, (TraceNo)i);
+  }
 #ifdef LUA_USE_ASSERT
 #ifdef LUA_USE_ASSERT
   for (i = 0; i < (ptrdiff_t)J->sizetrace; i++)
   for (i = 0; i < (ptrdiff_t)J->sizetrace; i++)
     lua_assert(J->trace[i] == NULL);
     lua_assert(J->trace[i] == NULL);

+ 1 - 1
src/lj_trace.h

@@ -26,7 +26,7 @@ LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e);
 LJ_FUNC void lj_trace_freeproto(global_State *g, GCproto *pt);
 LJ_FUNC void lj_trace_freeproto(global_State *g, GCproto *pt);
 LJ_FUNC void lj_trace_reenableproto(GCproto *pt);
 LJ_FUNC void lj_trace_reenableproto(GCproto *pt);
 LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt);
 LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt);
-LJ_FUNC void lj_trace_flush(jit_State *J, TraceNo traceno);
+LJ_FUNC int lj_trace_flush(jit_State *J, TraceNo traceno);
 LJ_FUNC int lj_trace_flushall(lua_State *L);
 LJ_FUNC int lj_trace_flushall(lua_State *L);
 LJ_FUNC void lj_trace_freestate(global_State *g);
 LJ_FUNC void lj_trace_freestate(global_State *g);
 
 

+ 3 - 3
src/lj_vm.h

@@ -46,6 +46,7 @@ LJ_ASMF void lj_vm_powi(void);
 LJ_ASMF void lj_gate_lf(void);
 LJ_ASMF void lj_gate_lf(void);
 LJ_ASMF void lj_gate_lv(void);
 LJ_ASMF void lj_gate_lv(void);
 LJ_ASMF void lj_gate_c(void);
 LJ_ASMF void lj_gate_c(void);
+LJ_ASMF void lj_gate_cwrap(void);
 
 
 /* Continuations for metamethods. */
 /* Continuations for metamethods. */
 LJ_ASMF void lj_cont_cat(void);  /* Continue with concatenation. */
 LJ_ASMF void lj_cont_cat(void);  /* Continue with concatenation. */
@@ -55,12 +56,11 @@ LJ_ASMF void lj_cont_condt(void);  /* Branch if result is true. */
 LJ_ASMF void lj_cont_condf(void);  /* Branch if result is false. */
 LJ_ASMF void lj_cont_condf(void);  /* Branch if result is false. */
 
 
 /* Start of the ASM code. */
 /* Start of the ASM code. */
-LJ_ASMF void lj_vm_asm_begin(void);
+LJ_ASMF char lj_vm_asm_begin[];
 
 
 /* Opcode handler offsets, relative to lj_vm_asm_begin. */
 /* Opcode handler offsets, relative to lj_vm_asm_begin. */
 LJ_ASMF const uint16_t lj_vm_op_ofs[];
 LJ_ASMF const uint16_t lj_vm_op_ofs[];
 
 
-#define makeasmfunc(ofs) \
-  ((ASMFunction)((char *)lj_vm_asm_begin + (ofs)))
+#define makeasmfunc(ofs)	((ASMFunction)(lj_vm_asm_begin + (ofs)))
 
 
 #endif
 #endif

+ 4 - 4
src/lua.hpp

@@ -1,9 +1,9 @@
-// lua.hpp
-// Lua header files for C++
-// <<extern "C">> not supplied automatically because Lua also compiles as C++
+// C++ wrapper for LuaJIT header files.
 
 
 extern "C" {
 extern "C" {
 #include "lua.h"
 #include "lua.h"
-#include "lualib.h"
 #include "lauxlib.h"
 #include "lauxlib.h"
+#include "lualib.h"
+#include "luajit.h"
 }
 }
+

+ 12 - 3
src/luaconf.h

@@ -34,13 +34,22 @@
   ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
   ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
 #else
 #else
 #define LUA_ROOT	"/usr/local/"
 #define LUA_ROOT	"/usr/local/"
-#define LUA_JDIR	LUA_ROOT "share/luajit-2.0.0-beta1/"
 #define LUA_LDIR	LUA_ROOT "share/lua/5.1/"
 #define LUA_LDIR	LUA_ROOT "share/lua/5.1/"
 #define LUA_CDIR	LUA_ROOT "lib/lua/5.1/"
 #define LUA_CDIR	LUA_ROOT "lib/lua/5.1/"
+#ifdef LUA_XROOT
+#define LUA_JDIR	LUA_XROOT "share/luajit-2.0.0-beta2/"
+#define LUA_XPATH \
+  ";" LUA_XROOT "share/lua/5.1/?.lua;" LUA_XROOT "share/lua/5.1/?/init.lua"
+#define LUA_XCPATH	LUA_XROOT "lib/lua/5.1/?.lua;"
+#else
+#define LUA_JDIR	LUA_ROOT "share/luajit-2.0.0-beta2/"
+#define LUA_XPATH
+#define LUA_XCPATH
+#endif
 #define LUA_PATH_DEFAULT \
 #define LUA_PATH_DEFAULT \
-  "./?.lua;" LUA_JDIR"?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;"
+  "./?.lua;" LUA_JDIR"?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua" LUA_XPATH
 #define LUA_CPATH_DEFAULT \
 #define LUA_CPATH_DEFAULT \
-  "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
+  "./?.so;" LUA_CDIR"?.so;" LUA_XCPATH LUA_CDIR"loadall.so"
 #endif
 #endif
 
 
 /* Environment variable names for path overrides and initialization code. */
 /* Environment variable names for path overrides and initialization code. */

+ 10 - 10
src/luajit.c

@@ -55,16 +55,16 @@ static void laction(int i)
 static void print_usage(void)
 static void print_usage(void)
 {
 {
   fprintf(stderr,
   fprintf(stderr,
-  "usage: %s [options] [script [args]].\n"
+  "usage: %s [options]... [script [args]...].\n"
   "Available options are:\n"
   "Available options are:\n"
-  "  -e stat  execute string " LUA_QL("stat") "\n"
-  "  -l name  require library " LUA_QL("name") "\n"
-  "  -j cmd   perform LuaJIT control command\n"
-  "  -O[lvl]  set LuaJIT optimization level\n"
-  "  -i       enter interactive mode after executing " LUA_QL("script") "\n"
-  "  -v       show version information\n"
-  "  --       stop handling options\n"
-  "  -        execute stdin and stop handling options\n"
+  "  -e chunk  Execute string " LUA_QL("chunk") ".\n"
+  "  -l name   Require library " LUA_QL("name") ".\n"
+  "  -j cmd    Perform LuaJIT control command.\n"
+  "  -O[opt]   Control LuaJIT optimizations.\n"
+  "  -i        Enter interactive mode after executing " LUA_QL("script") ".\n"
+  "  -v        Show version information.\n"
+  "  --        Stop handling options.\n"
+  "  -         Execute stdin and stop handling options.\n"
   ,
   ,
   progname);
   progname);
   fflush(stderr);
   fflush(stderr);
@@ -143,7 +143,7 @@ static void print_jit_status(lua_State *L)
   fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stderr);
   fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stderr);
   for (n++; (s = lua_tostring(L, n)); n++)
   for (n++; (s = lua_tostring(L, n)); n++)
     fprintf(stderr, " %s", s);
     fprintf(stderr, " %s", s);
-  fputs("\n", stdout);
+  fputs("\n", stderr);
 }
 }
 
 
 static int getargs(lua_State *L, char **argv, int n)
 static int getargs(lua_State *L, char **argv, int n)

+ 6 - 4
src/luajit.h

@@ -30,9 +30,9 @@
 
 
 #include "lua.h"
 #include "lua.h"
 
 
-#define LUAJIT_VERSION		"LuaJIT 2.0.0-beta1"
+#define LUAJIT_VERSION		"LuaJIT 2.0.0-beta2"
 #define LUAJIT_VERSION_NUM	20000  /* Version 2.0.0 = 02.00.00. */
 #define LUAJIT_VERSION_NUM	20000  /* Version 2.0.0 = 02.00.00. */
-#define LUAJIT_VERSION_SYM	luaJIT_version_2_0_0_beta1
+#define LUAJIT_VERSION_SYM	luaJIT_version_2_0_0_beta2
 #define LUAJIT_COPYRIGHT	"Copyright (C) 2005-2009 Mike Pall"
 #define LUAJIT_COPYRIGHT	"Copyright (C) 2005-2009 Mike Pall"
 #define LUAJIT_URL		"http://luajit.org/"
 #define LUAJIT_URL		"http://luajit.org/"
 
 
@@ -49,12 +49,14 @@ enum {
 
 
   LUAJIT_MODE_TRACE,		/* Flush a compiled trace. */
   LUAJIT_MODE_TRACE,		/* Flush a compiled trace. */
 
 
+  LUAJIT_MODE_WRAPCFUNC = 0x10,	/* Set wrapper mode for C function calls. */
+
   LUAJIT_MODE_MAX
   LUAJIT_MODE_MAX
 };
 };
 
 
 /* Flags or'ed in to the mode. */
 /* Flags or'ed in to the mode. */
-#define LUAJIT_MODE_OFF		0x0000	/* Disable JIT compilation. */
-#define LUAJIT_MODE_ON		0x0100	/* (Re-)enable JIT compilation. */
+#define LUAJIT_MODE_OFF		0x0000	/* Turn feature off. */
+#define LUAJIT_MODE_ON		0x0100	/* Turn feature on. */
 #define LUAJIT_MODE_FLUSH	0x0200	/* Flush JIT-compiled code. */
 #define LUAJIT_MODE_FLUSH	0x0200	/* Flush JIT-compiled code. */
 
 
 /* LuaJIT public C API. */
 /* LuaJIT public C API. */