This is a list of changes between the released versions of LuaJIT.
-The current development version is LuaJIT 2.0.0-beta1.
+The current development version is LuaJIT 2.0.0-beta2.
The current stable version is LuaJIT 1.1.5.
@@ -53,6 +53,36 @@ to see whether newer versions are available.
LuaJIT 2.0.0-beta2 — 2009-11-09
+-
+
- Reorganize build system. Build static+shared library on POSIX. +
- Allow C++ exception conversion on all platforms +using a wrapper function. +
- Automatically catch C++ exceptions and rethrow Lua error +(ELF/DWARF2 only). +
- Check for the correct x87 FPU precision at strategic points. +
- Always use wrappers for libm functions. +
- Resurrect metamethod name strings before copying them. +
- Mark current trace, even if compiler is idle. +
- Ensure FILE metatable is created only once. +
- Fix type comparisons when different integer types are involved. +
- Fix getmetatable() recording. +
- Fix TDUP with dead keys in template table. +
- jit.flush(tr) returns status. +Prevent manual flush of a trace that's still linked. +
- Improve register allocation heuristics for invariant references. +
- Compile the push/pop variants of table.insert() and +table.remove(). +
- Compatibility with MSVC link /debug. +
- Fix lua_iscfunction(). +
- Fix math.random() when compiled with -fpic (OSX). +
- Fix table.maxn(). +
- Bump MACOSX_DEPLOYMENT_TARGET to 10.4 +
- luaL_check*() and luaL_opt*() now support
+negative arguments, too.
+This matches the behavior of Lua 5.1, but not the specification.
+
LuaJIT 2.0.0-beta1 — 2009-10-31
- This is the first public release of LuaJIT 2.0. diff --git a/doc/faq.html b/doc/faq.html index 6f62e1eb..f76308a1 100644 --- a/doc/faq.html +++ b/doc/faq.html @@ -72,6 +72,7 @@ Search for: » Dynamic Language Optimizations
- Q: Why do I get this error: "bad FPU precision"?
+- Q: I get weird behavior after initializing Direct3D.
+- Q: Some FPU operations crash after I load a Delphi DLL.
+
+ - Q: I get weird behavior after initializing Direct3D.
-
+
+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 — LuaJIT is affected, too. Please make
+sure you always use the D3DCREATE_FPU_PRESERVE flag when
+initializing Direct3D.
+ +Direct3D version 10 or higher do not show this behavior anymore. +Consider testing your application with older versions, too.
+ +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. + + - Q: Sometimes Ctrl-C fails to stop my Lua program. Why?
- The interrupt signal handler sets a Lua debug hook. But this is
diff --git a/doc/install.html b/doc/install.html
index b7211d21..3aa60f1c 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -58,17 +58,15 @@ application under x64-based systems, too.
Configuring LuaJIT
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:
-
-
- src/luaconf.h sets some configuration variables, in -particular the default paths for loading modules. -
- Makefile has settings for installing LuaJIT (POSIX +
- src/luaconf.h sets some configuration variables. +
- Makefile has settings for installing LuaJIT (POSIX only). -
- src/Makefile has settings for compiling LuaJIT under POSIX, -MinGW and Cygwin. +
- src/Makefile has settings for compiling LuaJIT +under POSIX, MinGW and Cygwin.
- src/msvcbuild.bat has settings for compiling LuaJIT with MSVC.
-tar zxf LuaJIT-2.0.0-beta1.tar.gz -cd LuaJIT-2.0.0-beta1 -
+tar zxf LuaJIT-2.0.0-beta2.tar.gz +cd LuaJIT-2.0.0-beta2Building LuaJIT
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:
make
++By default modules are only searched under the prefix /usr/local. +You can add an extra prefix to the search paths by appending the +PREFIX option, e.g.: +
++make PREFIX=/home/myself/lj2 +
++Note for OSX: MACOSX_DEPLOYMENT_TARGET is set to 10.4 +in src/Makefile. Change it, if you want to build on an older version. +
Installing LuaJIT
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.:
-sudo make install PREFIX=/opt/lj2 +make install PREFIX=/home/myself/lj2
-But note that the installation prefix and the prefix for the module paths -(configured in src/luaconf.h) must match. +Obviously the prefixes given during build and installation need to be the same.
Note: to avoid overwriting a previous version, the beta test releases only install the LuaJIT executable under the versioned name (i.e. -luajit-2.0.0-beta1). You probably want to create a symlink +luajit-2.0.0-beta2). You probably want to create a symlink for convenience, with a command like this:
-sudo ln -sf luajit-2.0.0-beta1 /usr/local/bin/luajit +sudo ln -sf luajit-2.0.0-beta2 /usr/local/bin/luajit
Windows Systems
@@ -145,8 +153,8 @@ sudo ln -sf luajit-2.0.0-beta1 /usr/local/bin/luajitEither install one of the open source SDKs (» MinGW or -» Cygwin) which come with modified -versions of GCC plus the required development headers. +» Cygwin), which come with a modified +GCC plus the required development headers.
Or install Microsoft's Visual C++ (MSVC) — the freely downloadable @@ -159,8 +167,8 @@ Next, download the source package and unpack it using an archive manager
Building with MSVC
-Open a "Visual Studio .NET Command Prompt" and cd to the -directory where you've unpacked the sources. Then run this command: +Open a "Visual Studio .NET Command Prompt", cd to the +directory where you've unpacked the sources and run these commands:
cd src @@ -176,14 +184,12 @@ are in your path. Then cd to the directory where you've unpacked the sources and run this command for MinGW:
-cd src mingw32-make
Or this command for Cygwin:
-cd src make
@@ -191,10 +197,11 @@ Then follow the installation instructions below.
Installing LuaJIT
-Copy luajit.exe and lua51.dll -to a newly created directory (any location is ok). Add lua -and lua\jit directories below it and copy all Lua files -from the lib directory of the distribution to the latter directory. +Copy luajit.exe and lua51.dll (built in the src +directory) to a newly created directory (any location is ok). +Add lua and lua\jit directories below it and copy +all Lua files from the lib directory of the distribution +to the latter directory.
There are no hardcoded diff --git a/doc/running.html b/doc/running.html index db69578c..fcb28e85 100644 --- a/doc/running.html +++ b/doc/running.html @@ -69,11 +69,11 @@ interactive mode, too.
Note: the beta test releases only install under the versioned name on POSIX systems (to avoid overwriting a previous version). You either need -to type luajit-2.0.0-beta1 to start it or create a symlink +to type luajit-2.0.0-beta2 to start it or create a symlink with a command like this:
-sudo ln -sf luajit-2.0.0-beta1 /usr/local/bin/luajit +sudo ln -sf luajit-2.0.0-beta2 /usr/local/bin/luajit
Unlike previous versions optimization is turned on by default 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. They can be found in the lib directory of the source distribution or installed under the jit directory. By default -this is /usr/local/share/luajit-2.0.0-beta1/jit on POSIX +this is /usr/local/share/luajit-2.0.0-beta2/jit on POSIX systems.
diff --git a/doc/status.html b/doc/status.html index 23c14c76..aa4a1e26 100644 --- a/doc/status.html +++ b/doc/status.html @@ -90,7 +90,22 @@ known incompatibilities with standard Lua:- The Lua debug API 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). + +
- +Bytecode currently cannot be loaded or dumped. Note that +the bytecode format differs from Lua 5.1 — loading foreign +bytecode is not supported at all. + +
-
+Some of the configuration options of Lua 5.1 are not supported:
+
-
+
- The number type cannot be changed (it's always a double). +
- The stand-alone executable cannot be linked with readline +to enable line editing. It's planned to add support for loading it +on-demand. +
- Most other issues you're likely to find (e.g. with the existing test @@ -105,7 +120,7 @@ demonstrable need is shown.
-
The JIT compiler is not complete (yet) and falls back to the
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 -jv, you'll probably never notice (the interpreter is quite
fast, too). Here are the known issues:
- @@ -119,7 +134,7 @@ effort.
- Recursion 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.
-
The trace compiler currently does not back off specialization for
diff --git a/etc/luajit.1 b/etc/luajit.1
new file mode 100644
index 00000000..fab65803
--- /dev/null
+++ b/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)
diff --git a/etc/luajit.pc b/etc/luajit.pc
new file mode 100644
index 00000000..f0490097
--- /dev/null
+++ b/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}
diff --git a/src/Makefile b/src/Makefile
index bb1839d1..c0deb774 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -8,10 +8,17 @@
# 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
# 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.
+# 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)!
# In the meantime, the x86 binary runs fine under a x64 OS.
@@ -81,89 +88,142 @@ XCFLAGS=
#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.
##############################################################################
+##############################################################################
+# Flags and options for host and target.
+##############################################################################
+
CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(CFLAGS) $(XCFLAGS)
LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
HOST_CC= $(CC)
HOST_RM= rm -f
-HOST_XCFLAGS=
-HOST_XLDFLAGS=
-HOST_XLIBS=
-
-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_DISABLE= -U_FORTIFY_SOURCE
-ifneq (,$(findstring stack-protector,$(shell $(CC) -dumpspecs)))
- TARGET_DISABLE+= -fno-stack-protector
-endif
-
-ifneq (,$(findstring Windows,$(OS)))
- TARGET_SYS= Windows
-else
- TARGET_SYS:= $(shell uname -s)
- ifneq (,$(findstring CYGWIN,$(TARGET_SYS)))
- TARGET_SYS= Windows
- endif
-endif
-
-ifeq (Linux,$(TARGET_SYS))
- TARGET_XLIBS= -ldl
- TARGET_XLDFLAGS= -Wl,-E
-else
-ifeq (Windows,$(TARGET_SYS))
- HOST_RM= del
- TARGET_STRIP= strip --strip-unneeded
-else
-ifeq (Darwin,$(TARGET_SYS))
- TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup
- TARGET_STRIP= strip -x
- export MACOSX_DEPLOYMENT_TARGET=10.3
-else
- TARGET_XLDFLAGS= -Wl,-E
-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))
- TARGET_STRIP= @:
-endif
+HOST_LUA= lua
+HOST_XCFLAGS=
+HOST_XLDFLAGS=
+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_ARCH= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET))
+TARGET_DISABLE= -U_FORTIFY_SOURCE
+ifneq (,$(findstring stack-protector,$(shell $(TARGET_CC) -dumpspecs)))
+ TARGET_DISABLE+= -fno-stack-protector
+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)))
+ HOST_SYS= Windows
+else
+ HOST_SYS:= $(shell uname -s)
+ ifneq (,$(findstring CYGWIN,$(TARGET_SYS)))
+ HOST_SYS= Windows
+ endif
+endif
+ifeq (Windows,$(HOST_SYS))
+ HOST_RM= del
+endif
+
+TARGET_SYS= $(HOST_SYS)
+ifeq (Windows,$(TARGET_SYS))
+ TARGET_STRIP+= --strip-unneeded
+ TARGET_XSHLDFLAGS= -shared
+ TARGET_DYNXLDOPTS=
+else
+ifeq (Darwin,$(TARGET_SYS))
+ 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
+ TARGET_XLDFLAGS= -Wl,-E
+ ifeq (Linux,$(TARGET_SYS))
+ TARGET_XLIBS= -ldl
+ endif
+endif
+endif
+
+ifneq (,$(CCDEBUG))
+ TARGET_STRIP= @:
+endif
+
+##############################################################################
+# Files and pathnames.
+##############################################################################
+
DASM_DIR= ../dynasm
-DASM= $(DASM_LUA) $(DASM_DIR)/dynasm.lua
+DASM= $(HOST_LUA) $(DASM_DIR)/dynasm.lua
DASM_FLAGS=
DASM_DISTFLAGS= -LN
BUILDVM_O= buildvm.o buildvm_asm.o buildvm_peobj.o buildvm_lib.o buildvm_fold.o
BUILDVM_T= buildvm
+BUILDVM_X= ./$(BUILDVM_T)
HOST_O= $(BUILDVM_O)
HOST_T= $(BUILDVM_T)
@@ -188,121 +248,91 @@ LJCORE_O= lj_gc.o lj_err.o lj_ctype.o lj_bc.o lj_obj.o \
$(LJLIB_O) lib_init.o
LJVMCORE_O= $(LJVM_O) $(LJCORE_O)
-
-# 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_SO= luajit.so
-LUAJIT_T= luajit
+LJVMCORE_DYNO= $(LJVMCORE_O:.o=_dyn.o)
LIB_VMDEF= ../lib/vmdef.lua
+LIB_VMDEFP= $(LIB_VMDEF)
-TARGET_DEP= $(LIB_VMDEF)
-TARGET_O= $(LJVMCORE_O) $(LUAJIT_O)
-TARGET_T= $(LUAJIT_T)
+LUAJIT_O= luajit.o
+LUAJIT_A= libluajit.a
+LUAJIT_SO= libluajit.so
+LUAJIT_T= luajit
-ALL_GEN= $(LJVM_S) lj_ffdef.h lj_libdef.h lj_recdef.h $(LIB_VMDEF) lj_folddef.h
+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
-ALL_RM= $(LUAJIT_T) $(LUAJIT_SO) $(HOST_T) $(ALL_GEN) *.o $(WIN_RM)
-
-ifeq (Windows,$(TARGET_SYS))
- LJVM_BOUT= $(LJVM_O)
- LJVM_MODE= peobj
- LIB_VMDEF= ..\lib\vmdef.lua
- # Imported symbols are bound to a specific DLL name under Windows.
- LUAJIT_SO= lua51.dll
- 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)
-endif
+WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk
+ALL_RM= $(ALL_T) $(ALL_GEN) *.o $(WIN_RM)
+##############################################################################
+# Build mode handling.
##############################################################################
-default: $(TARGET_T)
+# Mixed mode defaults.
+TARGET_O= $(LUAJIT_A)
+TARGET_T= $(LUAJIT_T) $(LUAJIT_SO)
+TARGET_DEP= $(LIB_VMDEF) $(LUAJIT_SO)
-all: $(TARGET_T)
+ifeq (Windows,$(HOST_SYS))
+ BUILDVM_T= buildvm.exe
+ LIB_VMDEFP= $(subst /,\\,$(LIB_VMDEF))
+endif
+ifeq (Windows,$(TARGET_SYS))
+ DYNAMIC_CC= $(STATIC_CC)
+ LJVM_BOUT= $(LJVM_O)
+ LJVM_MODE= peobj
+ LUAJIT_SO= $(TARGET_DLLNAME)
+ LUAJIT_T= luajit.exe
+ 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
+
+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
+
+Q= @
+E= @echo
+#Q=
+#E= @:
+
+##############################################################################
+# Make targets.
+##############################################################################
+
+default all: $(TARGET_T)
amalg:
@grep "^[+|]" ljamalg.c
$(MAKE) all "LJCORE_O=ljamalg.o"
-MAKE_TARGETS= amalg
-
-##############################################################################
-
-buildvm_x86.h: buildvm_x86.dasc
- $(E) "DYNASM $@"
- $(Q)$(DASM) $(DASM_FLAGS) -o $@ buildvm_x86.dasc
-
-$(BUILDVM_T): $(BUILDVM_O)
- $(E) "HOSTLINK $@"
- $(Q)$(HOST_CC) $(HOST_LDFLAGS) -o $@ $(BUILDVM_O) $(HOST_LIBS)
-
-$(LJVM_BOUT): $(BUILDVM_T)
- $(E) "BUILDVM $@"
- $(Q)./$(BUILDVM_T) -m $(LJVM_MODE) -o $@
-
-lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
- $(E) "BUILDVM $@"
- $(Q)./$(BUILDVM_T) -m ffdef -o $@ $(LJLIB_C)
-
-lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
- $(E) "BUILDVM $@"
- $(Q)./$(BUILDVM_T) -m libdef -o $@ $(LJLIB_C)
-
-lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
- $(E) "BUILDVM $@"
- $(Q)./$(BUILDVM_T) -m recdef -o $@ $(LJLIB_C)
-
-$(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
- $(E) "BUILDVM $@"
- $(Q)./$(BUILDVM_T) -m vmdef -o $@ $(LJLIB_C)
-
-lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
- $(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"
-
-##############################################################################
-
-%.o: %.c
- $(E) "CC $@"
- $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
-
-%.o: %.s
- $(E) "ASM $@"
- $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
-
-$(HOST_O): %.o: %.c
- $(E) "HOSTCC $@"
- $(Q)$(HOST_CC) $(HOST_CFLAGS) -c -o $@ $<
-
-include Makefile.dep
-
-##############################################################################
-
clean:
$(HOST_RM) $(ALL_RM)
-cleaner: clean
- $(HOST_RM) $(ALL_DYNGEN)
+cleaner:
+ $(HOST_RM) $(ALL_RM) $(ALL_DYNGEN)
distclean: clean
$(E) "DYNASM $@"
@@ -321,6 +351,86 @@ depend:
@test -s lj_folddef.h || $(HOST_RM) lj_folddef.h
@test -s buildvm_x86.h || $(HOST_RM) buildvm_x86.h
-.PHONY: default all $(MAKE_TARGETS) clean cleaner distclean depend
+.PHONY: default all amalg clean cleaner distclean depend
+
+##############################################################################
+# Rules for generated files.
+##############################################################################
+
+buildvm_x86.h: buildvm_x86.dasc
+ $(E) "DYNASM $@"
+ $(Q)$(DASM) $(DASM_FLAGS) -o $@ buildvm_x86.dasc
+
+$(BUILDVM_T): $(BUILDVM_O)
+ $(E) "HOSTLINK $@"
+ $(Q)$(HOST_CC) $(HOST_LDFLAGS) -o $@ $(BUILDVM_O) $(HOST_LIBS)
+
+$(LJVM_BOUT): $(BUILDVM_T)
+ $(E) "BUILDVM $@"
+ $(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@
+
+lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
+ $(E) "BUILDVM $@"
+ $(Q)$(BUILDVM_X) -m ffdef -o $@ $(LJLIB_C)
+
+lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
+ $(E) "BUILDVM $@"
+ $(Q)$(BUILDVM_X) -m libdef -o $@ $(LJLIB_C)
+
+lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
+ $(E) "BUILDVM $@"
+ $(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C)
+
+$(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
+ $(E) "BUILDVM $@"
+ $(Q)$(BUILDVM_X) -m vmdef -o $(LIB_VMDEFP) $(LJLIB_C)
+
+lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
+ $(E) "BUILDVM $@"
+ $(Q)$(BUILDVM_X) -m folddef -o $@ lj_opt_fold.c
+
+##############################################################################
+# Object file rules.
+##############################################################################
+
+%.o: %.c
+ $(E) "CC $@"
+ $(Q)$(TARGET_DYNCC) $(TARGET_CFLAGS) -c -o $(@:.o=_dyn.o) $<
+ $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
+
+%.o: %.s
+ $(E) "ASM $@"
+ $(Q)$(TARGET_DYNCC) $(TARGET_CFLAGS) -c -o $(@:.o=_dyn.o) $<
+ $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
+
+$(LUAJIT_O):
+ $(E) "CC $@"
+ $(Q)$(TARGET_STCC) $(TARGET_CFLAGS) -c -o $@ $<
+
+$(HOST_O): %.o: %.c
+ $(E) "HOSTCC $@"
+ $(Q)$(HOST_CC) $(HOST_CFLAGS) -c -o $@ $<
+
+include Makefile.dep
+
+##############################################################################
+# Target file rules.
+##############################################################################
+
+$(LUAJIT_A): $(LJVMCORE_O)
+ $(E) "AR $@"
+ $(Q)$(TARGET_AR) $@ $(LJVMCORE_O)
+
+# 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) $@
+
+$(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"
##############################################################################
diff --git a/src/Makefile.dep b/src/Makefile.dep
index b1cdd93b..1fb81e27 100644
--- a/src/Makefile.dep
+++ b/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 \
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 \
- 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 \
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \
lj_libdef.h
diff --git a/src/buildvm_asm.c b/src/buildvm_asm.c
index e6972bd5..5daab13b 100644
--- a/src/buildvm_asm.c
+++ b/src/buildvm_asm.c
@@ -71,10 +71,7 @@ err:
exit(1);
}
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. */
@@ -135,7 +132,7 @@ void emit_asm(BuildCtx *ctx)
fprintf(ctx->fp, "\t.text\n");
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)
fprintf(ctx->fp, ".Lbegin:\n");
diff --git a/src/buildvm_fold.c b/src/buildvm_fold.c
index 5f065643..271118e0 100644
--- a/src/buildvm_fold.c
+++ b/src/buildvm_fold.c
@@ -188,7 +188,12 @@ void emit_fold(BuildCtx *ctx)
} else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) {
p += 2;
*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++;
} else {
buf[strlen(buf)-1] = '\0';
diff --git a/src/buildvm_peobj.c b/src/buildvm_peobj.c
index 9acf6b76..1a8661bf 100644
--- a/src/buildvm_peobj.c
+++ b/src/buildvm_peobj.c
@@ -264,7 +264,8 @@ void emit_peobj(BuildCtx *ctx)
emit_peobj_sym(ctx, name, 0,
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++) {
int pi = ctx->perm[i];
if (pi >= ctx->npc) {
diff --git a/src/buildvm_x86.dasc b/src/buildvm_x86.dasc
index add00c9d..f6add4d0 100644
--- a/src/buildvm_x86.dasc
+++ b/src/buildvm_x86.dasc
@@ -287,6 +287,35 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
| lea RA, [BASE+RA*8]
| 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.
| // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return
| mov [RA-4], PC
@@ -312,6 +341,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
| mov NRESULTS, RD
| test PC, FRAME_TYPE
| jz ->BC_RET_Z // Handle regular return to Lua.
+ | // Fallthrough.
|
|//-- Return handling (non-inline) ---------------------------------------
|
@@ -1455,7 +1485,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
| mov ARG5, RA
| fstp FPARG1
| mov RB, BASE
- | call extern func
+ | call extern lj_wrapper_ .. func
| mov RA, ARG5
| mov BASE, RB
| 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.align 4\n"
".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;
default: /* Difficult for other modes. */
break;
diff --git a/src/lib_aux.c b/src/lib_aux.c
index 1ae32dbc..2bd06fbb 100644
--- a/src/lib_aux.c
+++ b/src/lib_aux.c
@@ -20,97 +20,6 @@
#include "lj_err.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 ------------------------------------------------- */
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,
const luaL_Reg *l, int nup)
{
+ lj_lib_checkfpu(L);
if (libname) {
int size = libsize(l);
/* check whether lib already exists */
@@ -285,6 +195,10 @@ LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
#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)
{
int ref;
diff --git a/src/lib_io.c b/src/lib_io.c
index 01623258..aefe4213 100644
--- a/src/lib_io.c
+++ b/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)
{
- 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, 2, lj_cf_io_file_close); /* top-2 */
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, stdout, IO_OUTPUT, "stdout");
io_std_new(L, stderr, 0, "stderr");
- lua_pop(L, 1);
+ L->top--;
return 1;
}
diff --git a/src/lib_jit.c b/src/lib_jit.c
index 4a57f3b4..6cd0d0b6 100644
--- a/src/lib_jit.c
+++ b/src/lib_jit.c
@@ -73,8 +73,9 @@ LJLIB_CF(jit_flush)
#if LJ_HASJIT
if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) {
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
return setjitmode(L, LUAJIT_MODE_FLUSH);
diff --git a/src/lib_math.c b/src/lib_math.c
index ec8b0c2b..adc77c9d 100644
--- a/src/lib_math.c
+++ b/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(1e310) LJLIB_SET(huge)
-#ifdef __MACH__
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_tanh(double x) { return tanh(x); }
-#endif
/* ------------------------------------------------------------------------ */
@@ -98,8 +96,8 @@ typedef union { uint64_t u64; double d; } U64double;
z = (((z<
> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<
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; U64double u; @@ -108,16 +106,7 @@ static double tw223_step(TW223State *tw) TW223_GEN(2, 55, 24, 7) TW223_GEN(3, 47, 21, 8) 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. */ @@ -146,7 +135,7 @@ LJLIB_CF(math_random) TW223State *tw = (TW223State *)(uddata(udataV(lj_lib_upvalue(L, 1)))); double d; if (LJ_UNLIKELY(!tw->valid)) tw223_init(tw, 0.0); - d = tw223_step(tw); + d = tw223_step(tw) - 1.0; if (n > 0) { double r1 = lj_lib_checknum(L, 1); if (n == 1) { diff --git a/src/lib_package.c b/src/lib_package.c index 69fa1db9..4ede0659 100644 --- a/src/lib_package.c +++ b/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_setfield(L, 2, name); /* _LOADED[name] = true */ } + lj_lib_checkfpu(L); return 1; } diff --git a/src/lib_string.c b/src/lib_string.c index fdd7fbcb..6c857328 100644 --- a/src/lib_string.c +++ b/src/lib_string.c @@ -16,6 +16,7 @@ #include "lualib.h" #include "lj_obj.h" +#include "lj_gc.h" #include "lj_err.h" #include "lj_str.h" #include "lj_tab.h" @@ -774,6 +775,7 @@ LJLIB_CF(string_format) LUALIB_API int luaopen_string(lua_State *L) { GCtab *mt; + GCstr *mmstr; LJ_LIB_REG(L, string); #if defined(LUA_COMPAT_GFIND) lua_getfield(L, -1, "gmatch"); @@ -782,8 +784,9 @@ LUALIB_API int luaopen_string(lua_State *L) mt = lj_tab_new(L, 0, 1); /* NOBARRIER: G(L)->mmname[] is a GC root. */ 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<array); Node *node; 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])) { - m = (lua_Number)i; + m = (lua_Number)(int32_t)i; break; } 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) m = numV(&node[i].key); setnumV(L->top-1, m); return 1; } -LJLIB_CF(table_insert) +LJLIB_CF(table_insert) LJLIB_REC(.) { GCtab *t = lj_lib_checktab(L, 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); - copyTV(L, dst, L->top-1); + copyTV(L, dst, L->top-1); /* Set new value. */ lj_gc_barriert(L, t, dst); } return 0; } -LJLIB_CF(table_remove) +LJLIB_CF(table_remove) LJLIB_REC(.) { GCtab *t = lj_lib_checktab(L, 1); int32_t e = (int32_t)lj_tab_len(t); 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. */ for (; pos < e; pos++) { cTValue *src = lj_tab_getint(t, pos+1); @@ -135,8 +135,8 @@ LJLIB_CF(table_remove) 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) diff --git a/src/lj_api.c b/src/lj_api.c index ea4eaf66..db48e3a6 100644 --- a/src/lj_api.c +++ b/src/lj_api.c @@ -91,6 +91,12 @@ LUA_API int lua_checkstack(lua_State *L, int size) 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) { 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) { 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) { 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) @@ -295,6 +313,30 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx) 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) { cTValue *o = index2adr(L, idx); @@ -313,6 +355,44 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx) #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) { 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); } +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) { 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) { 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) diff --git a/src/lj_asm.c b/src/lj_asm.c index b89b8543..a4d0c606 100644 --- a/src/lj_asm.c +++ b/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)); } - /* 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); + } } else { r = ra_evict(as, allow); } diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index d2fce2e0..b427a06e 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c @@ -153,8 +153,7 @@ int luaJIT_setmode(lua_State *L, int idx, int mode) case LUAJIT_MODE_TRACE: if (!(mode & LUAJIT_MODE_FLUSH)) return 0; /* Failed. */ - lj_trace_flush(G2J(g), idx); - break; + return lj_trace_flush(G2J(g), idx); #else case LUAJIT_MODE_ENGINE: case LUAJIT_MODE_FUNC: @@ -165,6 +164,20 @@ int luaJIT_setmode(lua_State *L, int idx, int mode) return 0; /* Failed. */ break; #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: return 0; /* Failed. */ } diff --git a/src/lj_err.c b/src/lj_err.c index a723af48..71c561b1 100644 --- a/src/lj_err.c +++ b/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 *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". */ msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); else @@ -761,3 +763,47 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) 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 + diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h index 03abd59b..3c79eaa4 100644 --- a/src/lj_errmsg.h +++ b/src/lj_errmsg.h @@ -8,6 +8,7 @@ /* Basic error handling. */ ERRDEF(ERRMEM, "not enough memory") ERRDEF(ERRERR, "error in error handling") +ERRDEF(ERRCPP, "C++ exception") /* Allocations. */ ERRDEF(STROV, "string length overflow") @@ -56,6 +57,9 @@ ERRDEF(NOENV, "no calling environment") ERRDEF(CYIELD, "attempt to yield across C-call boundary") ERRDEF(BADLU, "bad light userdata pointer") 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. */ ERRDEF(ASSERT, "assertion failed!") diff --git a/src/lj_func.c b/src/lj_func.c index 92cdeda2..6616eff6 100644 --- a/src/lj_func.c +++ b/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); /* NOBARRIER: The GCfunc is new (marked white). */ 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; } diff --git a/src/lj_gc.c b/src/lj_gc.c index e479b567..0d8a03ec 100644 --- a/src/lj_gc.c +++ b/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). */ #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 #define gc_mark_curtrace(g) UNUSED(g) #endif diff --git a/src/lj_ir.c b/src/lj_ir.c index 2ff54821..1efb12f0 100644 --- a/src/lj_ir.c +++ b/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; IRRef ref; + lua_assert(!isdead(J2G(J), o)); for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) if (ir_kgc(&cir[ref]) == o) goto found; diff --git a/src/lj_lib.h b/src/lj_lib.h index 1cba3778..59a0f2be 100644 --- a/src/lj_lib.h +++ b/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) \ (&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. */ #define LJLIB_CF(name) static int lj_cf_##name(lua_State *L) #define LJLIB_ASM(name) static int lj_ffh_##name(lua_State *L) diff --git a/src/lj_obj.h b/src/lj_obj.h index e5ea713d..9101f053 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -531,7 +531,7 @@ typedef struct global_State { uint8_t hookmask; /* Hook mask. */ uint8_t dispatchmode; /* Dispatch mode. */ uint8_t vmevmask; /* VM event mask. */ - uint8_t unused1; + uint8_t wrapmode; /* Wrap mode. */ GCRef mainthref; /* Link to main thread. */ TValue registrytv; /* Anchor for registry. */ TValue tmptv; /* Temporary TValue. */ @@ -539,6 +539,7 @@ typedef struct global_State { int32_t hookcount; /* Instruction hook countdown. */ int32_t hookcstart; /* Start count for instruction hook counter. */ lua_Hook hookf; /* Hook function. */ + lua_CFunction wrapf; /* Wrapper for C function calls. */ lua_CFunction panic; /* Called as a last resort for errors. */ volatile int32_t vmstate; /* VM state or current JIT code trace number. */ GCRef jit_L; /* Current JIT code lua_State or NULL. */ diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index e5d98162..2102561d 100644 --- a/src/lj_opt_fold.c +++ b/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. */ #define LJFOLD(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! */ /* Barrier to prevent using operands across PHIs. */ @@ -979,7 +979,7 @@ LJFOLDF(comm_equal) /* For non-numbers only: x == x ==> drop; x ~= x ==> fail */ if (fins->op1 == fins->op2 && !irt_isnum(fins->t)) return CONDFOLD(fins->o == IR_EQ); - return comm_swap(J); + return fold_comm_swap(J); } LJFOLD(LT any any) @@ -1013,7 +1013,7 @@ LJFOLDF(comm_dup) { if (fins->op1 == fins->op2) /* x o x ==> x */ return LEFTFOLD; - return comm_swap(J); + return fold_comm_swap(J); } LJFOLD(BXOR any any) @@ -1021,7 +1021,7 @@ LJFOLDF(comm_bxor) { if (fins->op1 == fins->op2) /* i xor i ==> 0 */ return INTFOLD(0); - return comm_swap(J); + return fold_comm_swap(J); } /* -- Simplification of compound expressions ------------------------------ */ diff --git a/src/lj_opt_loop.c b/src/lj_opt_loop.c index adc0c476..05e9409e 100644 --- a/src/lj_opt_loop.c +++ b/src/lj_opt_loop.c @@ -286,7 +286,7 @@ static void loop_unroll(jit_State *J) if (!irt_sametype(t, irr->t)) { if (irt_isnum(t) && irt_isinteger(irr->t)) /* Fix int->num case. */ 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); } } diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index 77a9c0e7..94fc4ad8 100644 --- a/src/lj_opt_mem.c +++ b/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. */ IRRef skref = IR(store->op1)->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)) return 0; /* A nil store with same const key or var key MAY alias. */ /* Different const keys CANNOT alias. */ diff --git a/src/lj_record.c b/src/lj_record.c index e101ba23..68a233b9 100644 --- a/src/lj_record.c +++ b/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); 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) { /* Widen mixed number/int comparisons to number/number comparison. */ 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); 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)); nocheck: if (mt) { @@ -457,6 +457,8 @@ nocheck: copyTV(J->L, &ix->mobjv, mo); ix->mtv = 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); mix.key = lj_ir_kstr(J, mmstr); 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_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); 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]) { TRef base = lj_ir_toint(J, arg[1]); if (!tref_isk(base) || IR(tref_ref(base))->i != 10) - recff_err_ffu(J, rd); + recff_err_nyi(J, rd); } if (tref_isstr(tr)) 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)) { res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); } 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); } +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 -------------------------------------------- */ #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: /* Emit nothing for two numeric or string consts. */ 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; if (ta != tc) { /* Widen mixed number/int comparisons to number/number comparison. */ diff --git a/src/lj_tab.c b/src/lj_tab.c index 633ea20c..9af51027 100644 --- a/src/lj_tab.c +++ b/src/lj_tab.c @@ -191,8 +191,8 @@ GCtab *lj_tab_dup(lua_State *L, const GCtab *kt) Node *kn = &knode[i]; Node *n = &node[i]; 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)); } } diff --git a/src/lj_trace.c b/src/lj_trace.c index 6ceb5633..a0748b40 100644 --- a/src/lj_trace.c +++ b/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. */ void lj_trace_flushproto(global_State *g, GCproto *pt) { 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. */ @@ -241,8 +252,11 @@ int lj_trace_flushall(lua_State *L) ptrdiff_t i; if ((J2G(J)->hookmask & HOOK_GC)) 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 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++) lua_assert(J->trace[i] == NULL); diff --git a/src/lj_trace.h b/src/lj_trace.h index 9d8eb790..466ecc00 100644 --- a/src/lj_trace.h +++ b/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_reenableproto(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 void lj_trace_freestate(global_State *g); diff --git a/src/lj_vm.h b/src/lj_vm.h index f50614bb..095f284a 100644 --- a/src/lj_vm.h +++ b/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_lv(void); LJ_ASMF void lj_gate_c(void); +LJ_ASMF void lj_gate_cwrap(void); /* Continuations for metamethods. */ 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. */ /* 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. */ 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 diff --git a/src/lua.hpp b/src/lua.hpp index ec417f59..07e9002d 100644 --- a/src/lua.hpp +++ b/src/lua.hpp @@ -1,9 +1,9 @@ -// lua.hpp -// Lua header files for C++ -// < > not supplied automatically because Lua also compiles as C++ +// C++ wrapper for LuaJIT header files. extern "C" { #include "lua.h" -#include "lualib.h" #include "lauxlib.h" +#include "lualib.h" +#include "luajit.h" } + diff --git a/src/luaconf.h b/src/luaconf.h index 4d4f1099..dfa0f1d5 100644 --- a/src/luaconf.h +++ b/src/luaconf.h @@ -34,13 +34,22 @@ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" #else #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_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 \ - "./?.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 \ - "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" + "./?.so;" LUA_CDIR"?.so;" LUA_XCPATH LUA_CDIR"loadall.so" #endif /* Environment variable names for path overrides and initialization code. */ diff --git a/src/luajit.c b/src/luajit.c index 9153975b..eec2c0ca 100644 --- a/src/luajit.c +++ b/src/luajit.c @@ -55,16 +55,16 @@ static void laction(int i) static void print_usage(void) { fprintf(stderr, - "usage: %s [options] [script [args]].\n" + "usage: %s [options]... [script [args]...].\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); fflush(stderr); @@ -143,7 +143,7 @@ static void print_jit_status(lua_State *L) fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stderr); for (n++; (s = lua_tostring(L, n)); n++) fprintf(stderr, " %s", s); - fputs("\n", stdout); + fputs("\n", stderr); } static int getargs(lua_State *L, char **argv, int n) diff --git a/src/luajit.h b/src/luajit.h index 01913755..b3617f49 100644 --- a/src/luajit.h +++ b/src/luajit.h @@ -30,9 +30,9 @@ #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_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_URL "http://luajit.org/" @@ -49,12 +49,14 @@ enum { LUAJIT_MODE_TRACE, /* Flush a compiled trace. */ + LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */ + LUAJIT_MODE_MAX }; /* 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. */ /* LuaJIT public C API. */
Search for: » SSA Form
Search for: » Linear Scan Register Allocation
+Here is a list of the » innovative features in LuaJIT.
And, you know, reading the source is of course the only way to enlightenment. :-) @@ -86,6 +87,28 @@ functions from Lua 5.0.
Please convert your code to the vararg syntax. +
-
+