From 1d1fed48a002dfc0919135911057ebc255a53e0a Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 8 Dec 2009 19:49:20 +0100 Subject: RELEASE LuaJIT-2.0.0-beta2 --- src/Makefile | 322 ++++++++++++++++++++++++++++++++++----------------- src/Makefile.dep | 4 +- src/buildvm_asm.c | 7 +- src/buildvm_fold.c | 7 +- src/buildvm_peobj.c | 3 +- src/buildvm_x86.dasc | 111 +++++++++++++++++- src/lib_aux.c | 96 +-------------- src/lib_io.c | 9 +- src/lib_jit.c | 5 +- src/lib_math.c | 19 +-- src/lib_package.c | 1 + src/lib_string.c | 7 +- src/lib_table.c | 24 ++-- src/lj_api.c | 136 +++++++++++++++++++++- src/lj_asm.c | 11 +- src/lj_dispatch.c | 17 ++- src/lj_err.c | 46 ++++++++ src/lj_errmsg.h | 4 + src/lj_func.c | 2 +- src/lj_gc.c | 3 +- src/lj_ir.c | 1 + src/lj_lib.h | 9 ++ src/lj_obj.h | 3 +- src/lj_opt_fold.c | 8 +- src/lj_opt_loop.c | 2 +- src/lj_opt_mem.c | 4 +- src/lj_record.c | 70 +++++++++-- src/lj_tab.c | 4 +- src/lj_trace.c | 82 +++++++------ src/lj_trace.h | 2 +- src/lj_vm.h | 6 +- src/lua.hpp | 8 +- src/luaconf.h | 15 ++- src/luajit.c | 20 ++-- src/luajit.h | 10 +- 35 files changed, 749 insertions(+), 329 deletions(-) (limited to 'src') 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 +# 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_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_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))) +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))) - TARGET_SYS= Windows + HOST_SYS= Windows else - TARGET_SYS:= $(shell uname -s) + HOST_SYS:= $(shell uname -s) ifneq (,$(findstring CYGWIN,$(TARGET_SYS))) - TARGET_SYS= Windows + HOST_SYS= Windows 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)) - HOST_RM= del - TARGET_STRIP= strip --strip-unneeded + TARGET_STRIP+= --strip-unneeded + TARGET_XSHLDFLAGS= -shared + TARGET_DYNXLDOPTS= else 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 TARGET_XLDFLAGS= -Wl,-E + ifeq (Linux,$(TARGET_SYS)) + TARGET_XLIBS= -ldl + 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)) TARGET_STRIP= @: endif -HOST_CFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH) -HOST_LDFLAGS= $(LDOPTIONS) $(HOST_XLDFLAGS) -HOST_LIBS= $(HOST_XLIBS) +############################################################################## +# 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,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 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_SO= luajit.so +LUAJIT_A= libluajit.a +LUAJIT_SO= libluajit.so 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)) + DYNAMIC_CC= $(STATIC_CC) 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_SO= $(TARGET_DLLNAME) 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 -############################################################################## +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: @grep "^[+|]" ljamalg.c $(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 @@ -247,80 +367,70 @@ $(BUILDVM_T): $(BUILDVM_O) $(LJVM_BOUT): $(BUILDVM_T) $(E) "BUILDVM $@" - $(Q)./$(BUILDVM_T) -m $(LJVM_MODE) -o $@ + $(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@ lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C) $(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) $(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) $(E) "BUILDVM $@" - $(Q)./$(BUILDVM_T) -m recdef -o $@ $(LJLIB_C) + $(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C) $(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C) $(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 $(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 $(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. ############################################################################## -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" ############################################################################## 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. */ -- cgit v1.2.3-55-g6feb