aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2009-12-08 19:49:20 +0100
committerMike Pall <mike>2009-12-08 19:49:20 +0100
commit1d1fed48a002dfc0919135911057ebc255a53e0a (patch)
treec5c6643908374bb8f02f4c7691332d32f6645986 /src
parent55b16959717084884fd4a0cbae6d19e3786c20c7 (diff)
downloadluajit-1d1fed48a002dfc0919135911057ebc255a53e0a.tar.gz
luajit-1d1fed48a002dfc0919135911057ebc255a53e0a.tar.bz2
luajit-1d1fed48a002dfc0919135911057ebc255a53e0a.zip
RELEASE LuaJIT-2.0.0-beta2v2.0.0-beta2
Diffstat (limited to 'src')
-rw-r--r--src/Makefile322
-rw-r--r--src/Makefile.dep4
-rw-r--r--src/buildvm_asm.c7
-rw-r--r--src/buildvm_fold.c7
-rw-r--r--src/buildvm_peobj.c3
-rw-r--r--src/buildvm_x86.dasc111
-rw-r--r--src/lib_aux.c96
-rw-r--r--src/lib_io.c9
-rw-r--r--src/lib_jit.c5
-rw-r--r--src/lib_math.c19
-rw-r--r--src/lib_package.c1
-rw-r--r--src/lib_string.c7
-rw-r--r--src/lib_table.c24
-rw-r--r--src/lj_api.c136
-rw-r--r--src/lj_asm.c11
-rw-r--r--src/lj_dispatch.c17
-rw-r--r--src/lj_err.c46
-rw-r--r--src/lj_errmsg.h4
-rw-r--r--src/lj_func.c2
-rw-r--r--src/lj_gc.c3
-rw-r--r--src/lj_ir.c1
-rw-r--r--src/lj_lib.h9
-rw-r--r--src/lj_obj.h3
-rw-r--r--src/lj_opt_fold.c8
-rw-r--r--src/lj_opt_loop.c2
-rw-r--r--src/lj_opt_mem.c4
-rw-r--r--src/lj_record.c70
-rw-r--r--src/lj_tab.c4
-rw-r--r--src/lj_trace.c82
-rw-r--r--src/lj_trace.h2
-rw-r--r--src/lj_vm.h6
-rw-r--r--src/lua.hpp8
-rw-r--r--src/luaconf.h15
-rw-r--r--src/luajit.c20
-rw-r--r--src/luajit.h10
35 files changed, 749 insertions, 329 deletions
diff --git a/src/Makefile b/src/Makefile
index bb1839d1..c0deb774 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -8,10 +8,17 @@
8# Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h 8# Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
9############################################################################## 9##############################################################################
10 10
11MAJVER= 2
12MINVER= 0
13RELVER= 0
14ABIVER= 5.1
15NODOTABIVER= 51
16
11############################################################################## 17##############################################################################
12# Compiler options: change them as needed. This mainly affects the speed of 18# Compiler options: change them as needed. This mainly affects the speed of
13# the JIT compiler itself, not the speed of the JIT compiled code. 19# the JIT compiler itself, not the speed of the JIT compiled code.
14# Turn any of the optional settings on by removing the '#' in front of them. 20# Turn any of the optional settings on by removing the '#' in front of them.
21# You need to 'make clean' and 'make' again, if you change any options.
15# 22#
16# Note: LuaJIT can only be compiled for x86, and not for x64 (yet)! 23# Note: LuaJIT can only be compiled for x86, and not for x64 (yet)!
17# In the meantime, the x86 binary runs fine under a x64 OS. 24# In the meantime, the x86 binary runs fine under a x64 OS.
@@ -81,89 +88,142 @@ XCFLAGS=
81#XCFLAGS+= -DLUA_USE_ASSERT 88#XCFLAGS+= -DLUA_USE_ASSERT
82# 89#
83############################################################################## 90##############################################################################
91
92##############################################################################
93# Build mode: override the mode as needed. Default is mixed mode on POSIX.
94# On Windows this is the same as dynamic mode.
95#
96# Mixed mode creates a static + dynamic library and a statically linked luajit.
97BUILDMODE= mixed
98#
99# Static mode creates a static library and a statically linked luajit.
100#BUILDMODE= static
101#
102# Dynamic mode creates a dynamic library and a dynamically linked luajit.
103# Note: this executable will only run when the library is installed!
104#BUILDMODE= dynamic
105##############################################################################
84# You probably don't need to change anything below this line. 106# You probably don't need to change anything below this line.
85############################################################################## 107##############################################################################
86 108
109##############################################################################
110# Flags and options for host and target.
111##############################################################################
112
87CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(CFLAGS) $(XCFLAGS) 113CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(CFLAGS) $(XCFLAGS)
88LDOPTIONS= $(CCDEBUG) $(LDFLAGS) 114LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
89 115
90HOST_CC= $(CC) 116HOST_CC= $(CC)
91HOST_RM= rm -f 117HOST_RM= rm -f
118# NOTE: The LuaJIT distribution comes with a pre-generated buildvm_*.h.
119# You DO NOT NEED an installed copy of (plain) Lua 5.1 to run DynASM unless
120# you want to MODIFY the corresponding *.dasc file. You can also use LuaJIT
121# itself (bootstrapped from the pre-generated file) to run DynASM of course.
122HOST_LUA= lua
123
92HOST_XCFLAGS= 124HOST_XCFLAGS=
93HOST_XLDFLAGS= 125HOST_XLDFLAGS=
94HOST_XLIBS= 126HOST_XLIBS=
127HOST_CFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH)
128HOST_LDFLAGS= $(LDOPTIONS) $(HOST_XLDFLAGS)
129HOST_LIBS= $(HOST_XLIBS)
130
131# Cross-compilation example: make CROSS=i586-mingw32msvc- TARGET_SYS=Windows
132CROSS=
133STATIC_CC = $(CROSS)$(CC)
134DYNAMIC_CC = $(CROSS)$(CC) -fPIC
135TARGET_CC= $(STATIC_CC)
136TARGET_STCC= $(STATIC_CC)
137TARGET_DYNCC= $(DYNAMIC_CC)
138TARGET_LD= $(CROSS)$(CC)
139TARGET_AR= $(CROSS)ar rcus
140TARGET_STRIP= $(CROSS)strip
141
142TARGET_SONAME= libluajit-$(ABIVER).so.$(MAJVER)
143TARGET_DYLIBNAME= libluajit-$(NODOTABIVER).$(MAJVER).$(MINVER).$(RELVER).dylib
144TARGET_DLLNAME= lua$(NODOTABIVER).dll
145TARGET_XSHLDFLAGS= -shared -fPIC -Wl,-soname,$(TARGET_SONAME)
146TARGET_DYNXLDOPTS=
95 147
96TARGET_CC= $(CC)
97TARGET_STRIP= strip
98TARGET_XCFLAGS= -D_FILE_OFFSET_BITS=64
99TARGET_XLDFLAGS=
100TARGET_XSHLDFLAGS= -shared
101TARGET_XLIBS=
102TARGET_ARCH= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET)) 148TARGET_ARCH= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET))
103TARGET_DISABLE= -U_FORTIFY_SOURCE 149TARGET_DISABLE= -U_FORTIFY_SOURCE
104ifneq (,$(findstring stack-protector,$(shell $(CC) -dumpspecs))) 150ifneq (,$(findstring stack-protector,$(shell $(TARGET_CC) -dumpspecs)))
105 TARGET_DISABLE+= -fno-stack-protector 151 TARGET_DISABLE+= -fno-stack-protector
106endif 152endif
107 153
154TARGET_XCFLAGS= -D_FILE_OFFSET_BITS=64
155TARGET_XLDFLAGS=
156TARGET_XLDOPTS=
157TARGET_XLIBS=
158TARGET_CFLAGS= $(CCOPTIONS) $(TARGET_DISABLE) $(TARGET_XCFLAGS)
159TARGET_LDFLAGS= $(LDOPTIONS) $(TARGET_XLDFLAGS) $(TARGET_XLDOPTS)
160TARGET_SHLDFLAGS= $(LDOPTIONS) $(TARGET_XSHLDFLAGS)
161TARGET_LIBS= -lm $(TARGET_XLIBS)
162
163ifneq (,$(PREFIX))
164ifneq (/usr/local,$(PREFIX))
165 TARGET_XCFLAGS+= -DLUA_XROOT=\"$(PREFIX)/\"
166 ifneq (/usr,$(PREFIX))
167 TARGET_DYNXLDOPTS= -Wl,-rpath,$(PREFIX)/lib
168 endif
169endif
170endif
171
172##############################################################################
173# System detection.
174##############################################################################
175
108ifneq (,$(findstring Windows,$(OS))) 176ifneq (,$(findstring Windows,$(OS)))
109 TARGET_SYS= Windows 177 HOST_SYS= Windows
110else 178else
111 TARGET_SYS:= $(shell uname -s) 179 HOST_SYS:= $(shell uname -s)
112 ifneq (,$(findstring CYGWIN,$(TARGET_SYS))) 180 ifneq (,$(findstring CYGWIN,$(TARGET_SYS)))
113 TARGET_SYS= Windows 181 HOST_SYS= Windows
114 endif 182 endif
115endif 183endif
184ifeq (Windows,$(HOST_SYS))
185 HOST_RM= del
186endif
116 187
117ifeq (Linux,$(TARGET_SYS)) 188TARGET_SYS= $(HOST_SYS)
118 TARGET_XLIBS= -ldl
119 TARGET_XLDFLAGS= -Wl,-E
120else
121ifeq (Windows,$(TARGET_SYS)) 189ifeq (Windows,$(TARGET_SYS))
122 HOST_RM= del 190 TARGET_STRIP+= --strip-unneeded
123 TARGET_STRIP= strip --strip-unneeded 191 TARGET_XSHLDFLAGS= -shared
192 TARGET_DYNXLDOPTS=
124else 193else
125ifeq (Darwin,$(TARGET_SYS)) 194ifeq (Darwin,$(TARGET_SYS))
126 TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup 195 export MACOSX_DEPLOYMENT_TARGET=10.4
127 TARGET_STRIP= strip -x 196 TARGET_STRIP+= -x
128 export MACOSX_DEPLOYMENT_TARGET=10.3 197 TARGET_AR+= 2>/dev/null
198 TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
199 ifneq (,$(TARGET_DYNXLDOPTS))
200 TARGET_DYNXLDOPTS=
201 TARGET_XSHLDFLAGS+= -install_name $(PREFIX)/lib/$(TARGET_DYLIBNAME)
202 endif
129else 203else
130 TARGET_XLDFLAGS= -Wl,-E 204 TARGET_XLDFLAGS= -Wl,-E
205 ifeq (Linux,$(TARGET_SYS))
206 TARGET_XLIBS= -ldl
207 endif
131endif 208endif
132endif 209endif
133endif
134
135# NOTE: The LuaJIT distribution comes with a pre-generated buildvm_*.h.
136# You DO NOT NEED an installed copy of (plain) Lua 5.1 to run DynASM unless
137# you want to MODIFY the corresponding *.dasc file. You can also use LuaJIT
138# itself (bootstrapped from the pre-generated file) to run DynASM of course.
139DASM_LUA= lua
140
141Q= @
142E= @echo
143#Q=
144#E= @:
145
146##############################################################################
147 210
148TARGET_CFLAGS= $(CCOPTIONS) $(TARGET_DISABLE) $(TARGET_XCFLAGS)
149TARGET_LDFLAGS= $(LDOPTIONS) $(TARGET_XLDFLAGS)
150TARGET_SHLDFLAGS= $(LDOPTIONS) $(TARGET_XSHLDFLAGS)
151TARGET_LIBS= -lm $(TARGET_XLIBS)
152ifneq (,$(CCDEBUG)) 211ifneq (,$(CCDEBUG))
153 TARGET_STRIP= @: 212 TARGET_STRIP= @:
154endif 213endif
155 214
156HOST_CFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH) 215##############################################################################
157HOST_LDFLAGS= $(LDOPTIONS) $(HOST_XLDFLAGS) 216# Files and pathnames.
158HOST_LIBS= $(HOST_XLIBS) 217##############################################################################
159 218
160DASM_DIR= ../dynasm 219DASM_DIR= ../dynasm
161DASM= $(DASM_LUA) $(DASM_DIR)/dynasm.lua 220DASM= $(HOST_LUA) $(DASM_DIR)/dynasm.lua
162DASM_FLAGS= 221DASM_FLAGS=
163DASM_DISTFLAGS= -LN 222DASM_DISTFLAGS= -LN
164 223
165BUILDVM_O= buildvm.o buildvm_asm.o buildvm_peobj.o buildvm_lib.o buildvm_fold.o 224BUILDVM_O= buildvm.o buildvm_asm.o buildvm_peobj.o buildvm_lib.o buildvm_fold.o
166BUILDVM_T= buildvm 225BUILDVM_T= buildvm
226BUILDVM_X= ./$(BUILDVM_T)
167 227
168HOST_O= $(BUILDVM_O) 228HOST_O= $(BUILDVM_O)
169HOST_T= $(BUILDVM_T) 229HOST_T= $(BUILDVM_T)
@@ -188,54 +248,114 @@ LJCORE_O= lj_gc.o lj_err.o lj_ctype.o lj_bc.o lj_obj.o \
188 $(LJLIB_O) lib_init.o 248 $(LJLIB_O) lib_init.o
189 249
190LJVMCORE_O= $(LJVM_O) $(LJCORE_O) 250LJVMCORE_O= $(LJVM_O) $(LJCORE_O)
251LJVMCORE_DYNO= $(LJVMCORE_O:.o=_dyn.o)
252
253LIB_VMDEF= ../lib/vmdef.lua
254LIB_VMDEFP= $(LIB_VMDEF)
191 255
192# NYI: Need complete support for building as a shared library on POSIX.
193# This is currently *only* suitable for MinGW and Cygwin, see below.
194LUAJIT_O= luajit.o 256LUAJIT_O= luajit.o
195LUAJIT_SO= luajit.so 257LUAJIT_A= libluajit.a
258LUAJIT_SO= libluajit.so
196LUAJIT_T= luajit 259LUAJIT_T= luajit
197 260
198LIB_VMDEF= ../lib/vmdef.lua 261ALL_T= $(LUAJIT_T) $(LUAJIT_A) $(LUAJIT_SO) $(BUILDVM_T)
262ALL_GEN= $(LJVM_S) lj_ffdef.h lj_libdef.h lj_recdef.h $(LIB_VMDEFP) lj_folddef.h
263ALL_DYNGEN= buildvm_x86.h
264WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk
265ALL_RM= $(ALL_T) $(ALL_GEN) *.o $(WIN_RM)
199 266
200TARGET_DEP= $(LIB_VMDEF) 267##############################################################################
201TARGET_O= $(LJVMCORE_O) $(LUAJIT_O) 268# Build mode handling.
202TARGET_T= $(LUAJIT_T) 269##############################################################################
203 270
204ALL_GEN= $(LJVM_S) lj_ffdef.h lj_libdef.h lj_recdef.h $(LIB_VMDEF) lj_folddef.h 271# Mixed mode defaults.
205ALL_DYNGEN= buildvm_x86.h 272TARGET_O= $(LUAJIT_A)
206WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest 273TARGET_T= $(LUAJIT_T) $(LUAJIT_SO)
207ALL_RM= $(LUAJIT_T) $(LUAJIT_SO) $(HOST_T) $(ALL_GEN) *.o $(WIN_RM) 274TARGET_DEP= $(LIB_VMDEF) $(LUAJIT_SO)
208 275
276ifeq (Windows,$(HOST_SYS))
277 BUILDVM_T= buildvm.exe
278 LIB_VMDEFP= $(subst /,\\,$(LIB_VMDEF))
279endif
209ifeq (Windows,$(TARGET_SYS)) 280ifeq (Windows,$(TARGET_SYS))
281 DYNAMIC_CC= $(STATIC_CC)
210 LJVM_BOUT= $(LJVM_O) 282 LJVM_BOUT= $(LJVM_O)
211 LJVM_MODE= peobj 283 LJVM_MODE= peobj
212 LIB_VMDEF= ..\lib\vmdef.lua 284 LUAJIT_SO= $(TARGET_DLLNAME)
213 # Imported symbols are bound to a specific DLL name under Windows.
214 LUAJIT_SO= lua51.dll
215 LUAJIT_T= luajit.exe 285 LUAJIT_T= luajit.exe
216 BUILDVM_T= buildvm.exe 286 ifneq ($(HOST_SYS),$(TARGET_SYS))
217 # 287 HOST_XCFLAGS+= -malign-double
218 # You can comment out the following two lines to build a static executable. 288 endif
219 # But then you won't be able to dynamically load any C modules, because 289 # Mixed mode is not supported on Windows. And static mode doesn't work well.
220 # they bind to lua51.dll. 290 # C modules cannot be loaded, because they bind to lua51.dll.
221 # 291 ifneq (static,$(BUILDMODE))
222 TARGET_XCFLAGS+= -DLUA_BUILD_AS_DLL 292 BUILDMODE= dynamic
223 TARGET_O= $(LUAJIT_SO) $(LUAJIT_O) 293 TARGET_XCFLAGS+= -DLUA_BUILD_AS_DLL
294 endif
224endif 295endif
225 296
226############################################################################## 297ifeq (static,$(BUILDMODE))
298 TARGET_DYNCC= @:
299 TARGET_T= $(LUAJIT_T)
300 TARGET_DEP= $(LIB_VMDEF)
301else
302ifeq (dynamic,$(BUILDMODE))
303 TARGET_CC= $(DYNAMIC_CC)
304 TARGET_DYNCC= @:
305 LJVMCORE_DYNO= $(LJVMCORE_O)
306 TARGET_O= $(LUAJIT_SO)
307 TARGET_XLDOPTS= $(TARGET_DYNXLDOPTS)
308else
309ifeq (Darwin,$(TARGET_SYS))
310 TARGET_DYNCC= @:
311 LJVMCORE_DYNO= $(LJVMCORE_O)
312endif
313endif
314endif
227 315
228default: $(TARGET_T) 316Q= @
317E= @echo
318#Q=
319#E= @:
229 320
230all: $(TARGET_T) 321##############################################################################
322# Make targets.
323##############################################################################
324
325default all: $(TARGET_T)
231 326
232amalg: 327amalg:
233 @grep "^[+|]" ljamalg.c 328 @grep "^[+|]" ljamalg.c
234 $(MAKE) all "LJCORE_O=ljamalg.o" 329 $(MAKE) all "LJCORE_O=ljamalg.o"
235 330
236MAKE_TARGETS= amalg 331clean:
332 $(HOST_RM) $(ALL_RM)
333
334cleaner:
335 $(HOST_RM) $(ALL_RM) $(ALL_DYNGEN)
336
337distclean: clean
338 $(E) "DYNASM $@"
339 $(Q)$(DASM) $(DASM_DISTFLAGS) -o buildvm_x86.h buildvm_x86.dasc
340
341depend:
342 @test -f lj_ffdef.h || touch lj_ffdef.h
343 @test -f lj_libdef.h || touch lj_libdef.h
344 @test -f lj_recdef.h || touch lj_recdef.h
345 @test -f lj_folddef.h || touch lj_folddef.h
346 @test -f buildvm_x86.h || touch buildvm_x86.h
347 @$(HOST_CC) $(HOST_CFLAGS) -MM *.c | sed "s|$(DASM_DIR)|\$$(DASM_DIR)|g" >Makefile.dep
348 @test -s lj_ffdef.h || $(HOST_RM) lj_ffdef.h
349 @test -s lj_libdef.h || $(HOST_RM) lj_libdef.h
350 @test -s lj_recdef.h || $(HOST_RM) lj_recdef.h
351 @test -s lj_folddef.h || $(HOST_RM) lj_folddef.h
352 @test -s buildvm_x86.h || $(HOST_RM) buildvm_x86.h
353
354.PHONY: default all amalg clean cleaner distclean depend
237 355
238############################################################################## 356##############################################################################
357# Rules for generated files.
358##############################################################################
239 359
240buildvm_x86.h: buildvm_x86.dasc 360buildvm_x86.h: buildvm_x86.dasc
241 $(E) "DYNASM $@" 361 $(E) "DYNASM $@"
@@ -247,49 +367,46 @@ $(BUILDVM_T): $(BUILDVM_O)
247 367
248$(LJVM_BOUT): $(BUILDVM_T) 368$(LJVM_BOUT): $(BUILDVM_T)
249 $(E) "BUILDVM $@" 369 $(E) "BUILDVM $@"
250 $(Q)./$(BUILDVM_T) -m $(LJVM_MODE) -o $@ 370 $(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@
251 371
252lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C) 372lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
253 $(E) "BUILDVM $@" 373 $(E) "BUILDVM $@"
254 $(Q)./$(BUILDVM_T) -m ffdef -o $@ $(LJLIB_C) 374 $(Q)$(BUILDVM_X) -m ffdef -o $@ $(LJLIB_C)
255 375
256lj_libdef.h: $(BUILDVM_T) $(LJLIB_C) 376lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
257 $(E) "BUILDVM $@" 377 $(E) "BUILDVM $@"
258 $(Q)./$(BUILDVM_T) -m libdef -o $@ $(LJLIB_C) 378 $(Q)$(BUILDVM_X) -m libdef -o $@ $(LJLIB_C)
259 379
260lj_recdef.h: $(BUILDVM_T) $(LJLIB_C) 380lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
261 $(E) "BUILDVM $@" 381 $(E) "BUILDVM $@"
262 $(Q)./$(BUILDVM_T) -m recdef -o $@ $(LJLIB_C) 382 $(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C)
263 383
264$(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C) 384$(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
265 $(E) "BUILDVM $@" 385 $(E) "BUILDVM $@"
266 $(Q)./$(BUILDVM_T) -m vmdef -o $@ $(LJLIB_C) 386 $(Q)$(BUILDVM_X) -m vmdef -o $(LIB_VMDEFP) $(LJLIB_C)
267 387
268lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c 388lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
269 $(E) "BUILDVM $@" 389 $(E) "BUILDVM $@"
270 $(Q)./$(BUILDVM_T) -m folddef -o $@ lj_opt_fold.c 390 $(Q)$(BUILDVM_X) -m folddef -o $@ lj_opt_fold.c
271
272$(LUAJIT_SO): $(LJVMCORE_O)
273 $(E) "LINK $@"
274 $(Q)$(TARGET_CC) $(TARGET_SHLDFLAGS) -o $@ $(LJVMCORE_O) $(TARGET_LIBS)
275 $(Q)$(TARGET_STRIP) $@
276
277$(LUAJIT_T): $(TARGET_O) $(TARGET_DEP)
278 $(E) "LINK $@"
279 $(Q)$(TARGET_CC) $(TARGET_LDFLAGS) -o $@ $(TARGET_O) $(TARGET_LIBS)
280 $(Q)$(TARGET_STRIP) $@
281 $(E) "OK Successfully built LuaJIT"
282 391
283############################################################################## 392##############################################################################
393# Object file rules.
394##############################################################################
284 395
285%.o: %.c 396%.o: %.c
286 $(E) "CC $@" 397 $(E) "CC $@"
398 $(Q)$(TARGET_DYNCC) $(TARGET_CFLAGS) -c -o $(@:.o=_dyn.o) $<
287 $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $< 399 $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
288 400
289%.o: %.s 401%.o: %.s
290 $(E) "ASM $@" 402 $(E) "ASM $@"
403 $(Q)$(TARGET_DYNCC) $(TARGET_CFLAGS) -c -o $(@:.o=_dyn.o) $<
291 $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $< 404 $(Q)$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
292 405
406$(LUAJIT_O):
407 $(E) "CC $@"
408 $(Q)$(TARGET_STCC) $(TARGET_CFLAGS) -c -o $@ $<
409
293$(HOST_O): %.o: %.c 410$(HOST_O): %.o: %.c
294 $(E) "HOSTCC $@" 411 $(E) "HOSTCC $@"
295 $(Q)$(HOST_CC) $(HOST_CFLAGS) -c -o $@ $< 412 $(Q)$(HOST_CC) $(HOST_CFLAGS) -c -o $@ $<
@@ -297,30 +414,23 @@ $(HOST_O): %.o: %.c
297include Makefile.dep 414include Makefile.dep
298 415
299############################################################################## 416##############################################################################
417# Target file rules.
418##############################################################################
300 419
301clean: 420$(LUAJIT_A): $(LJVMCORE_O)
302 $(HOST_RM) $(ALL_RM) 421 $(E) "AR $@"
303 422 $(Q)$(TARGET_AR) $@ $(LJVMCORE_O)
304cleaner: clean
305 $(HOST_RM) $(ALL_DYNGEN)
306 423
307distclean: clean 424# The dependency on _O, but linking with _DYNO is intentional.
308 $(E) "DYNASM $@" 425$(LUAJIT_SO): $(LJVMCORE_O)
309 $(Q)$(DASM) $(DASM_DISTFLAGS) -o buildvm_x86.h buildvm_x86.dasc 426 $(E) "DYNLINK $@"
310 427 $(Q)$(TARGET_LD) $(TARGET_SHLDFLAGS) -o $@ $(LJVMCORE_DYNO) $(TARGET_LIBS)
311depend: 428 $(Q)$(TARGET_STRIP) $@
312 @test -f lj_ffdef.h || touch lj_ffdef.h
313 @test -f lj_libdef.h || touch lj_libdef.h
314 @test -f lj_recdef.h || touch lj_recdef.h
315 @test -f lj_folddef.h || touch lj_folddef.h
316 @test -f buildvm_x86.h || touch buildvm_x86.h
317 @$(HOST_CC) $(HOST_CFLAGS) -MM *.c | sed "s|$(DASM_DIR)|\$$(DASM_DIR)|g" >Makefile.dep
318 @test -s lj_ffdef.h || $(HOST_RM) lj_ffdef.h
319 @test -s lj_libdef.h || $(HOST_RM) lj_libdef.h
320 @test -s lj_recdef.h || $(HOST_RM) lj_recdef.h
321 @test -s lj_folddef.h || $(HOST_RM) lj_folddef.h
322 @test -s buildvm_x86.h || $(HOST_RM) buildvm_x86.h
323 429
324.PHONY: default all $(MAKE_TARGETS) clean cleaner distclean depend 430$(LUAJIT_T): $(TARGET_O) $(LUAJIT_O) $(TARGET_DEP)
431 $(E) "LINK $@"
432 $(Q)$(TARGET_LD) $(TARGET_LDFLAGS) -o $@ $(LUAJIT_O) $(TARGET_O) $(TARGET_LIBS)
433 $(Q)$(TARGET_STRIP) $@
434 $(E) "OK Successfully built LuaJIT"
325 435
326############################################################################## 436##############################################################################
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 \
34lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 34lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
35 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h 35 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h
36lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 36lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
37 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_state.h \ 37 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h \
38 lj_ff.h lj_ffdef.h lj_ctype.h lj_lib.h lj_libdef.h 38 lj_state.h lj_ff.h lj_ffdef.h lj_ctype.h lj_lib.h lj_libdef.h
39lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 39lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
40 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \ 40 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \
41 lj_libdef.h 41 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:
71 exit(1); 71 exit(1);
72 } 72 }
73 emit_asm_bytes(ctx, cp, n); 73 emit_asm_bytes(ctx, cp, n);
74 if (!strncmp(sym, LABEL_PREFIX, sizeof(LABEL_PREFIX)-1)) 74 fprintf(ctx->fp, "\t%s _%s\n", opname, sym);
75 fprintf(ctx->fp, "\t%s _%s\n", opname, sym);
76 else
77 fprintf(ctx->fp, "\t%s _" LABEL_PREFIX "wrapper_%s\n", opname, sym);
78} 75}
79 76
80/* Emit an assembler label. */ 77/* Emit an assembler label. */
@@ -135,7 +132,7 @@ void emit_asm(BuildCtx *ctx)
135 fprintf(ctx->fp, "\t.text\n"); 132 fprintf(ctx->fp, "\t.text\n");
136 emit_asm_align(ctx, 4); 133 emit_asm_align(ctx, 4);
137 134
138 emit_asm_label(ctx, LABEL_ASM_BEGIN, 0, 1); 135 emit_asm_label(ctx, LABEL_ASM_BEGIN, 0, 0);
139 if (ctx->mode == BUILD_elfasm) 136 if (ctx->mode == BUILD_elfasm)
140 fprintf(ctx->fp, ".Lbegin:\n"); 137 fprintf(ctx->fp, ".Lbegin:\n");
141 138
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)
188 } else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) { 188 } else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) {
189 p += 2; 189 p += 2;
190 *q = '\0'; 190 *q = '\0';
191 fprintf(ctx->fp, funcidx ? ",\n %s" : " %s", p); 191 if (funcidx)
192 fprintf(ctx->fp, ",\n");
193 if (p[-2] == 'X')
194 fprintf(ctx->fp, " %s", p);
195 else
196 fprintf(ctx->fp, " fold_%s", p);
192 funcidx++; 197 funcidx++;
193 } else { 198 } else {
194 buf[strlen(buf)-1] = '\0'; 199 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)
264 emit_peobj_sym(ctx, name, 0, 264 emit_peobj_sym(ctx, name, 0,
265 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); 265 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
266 } 266 }
267 emit_peobj_sym_func(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0); 267 emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0,
268 PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
268 for (i = nzsym; i < ctx->nsym; i++) { 269 for (i = nzsym; i < ctx->nsym; i++) {
269 int pi = ctx->perm[i]; 270 int pi = ctx->perm[i];
270 if (pi >= ctx->npc) { 271 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)
287 | lea RA, [BASE+RA*8] 287 | lea RA, [BASE+RA*8]
288 | jmp <9 288 | jmp <9
289 | 289 |
290 |->gate_cwrap: // Call gate for wrapped C functions.
291 | // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return
292 | mov [RA-4], PC
293 | mov KBASE, CFUNC:RB->f
294 | mov L:RB, SAVE_L
295 | lea RC, [RA+NARGS:RC*8-8]
296 | mov L:RB->base, RA
297 | lea RA, [RC+8*LUA_MINSTACK]
298 | mov ARG2, KBASE
299 | mov ARG1, L:RB
300 | mov L:RB->top, RC
301 | cmp RA, L:RB->maxstack
302 | ja ->gate_c_growstack // Need to grow stack.
303 | set_vmstate C
304 | // (lua_State *L, lua_CFunction f)
305 | call aword [DISPATCH+DISPATCH_GL(wrapf)]
306 | set_vmstate INTERP
307 | // nresults returned in eax (RD).
308 | mov BASE, L:RB->base
309 | lea RA, [BASE+RD*8]
310 | neg RA
311 | add RA, L:RB->top // RA = (L->top-(L->base+nresults))*8
312 |->vm_returnc:
313 | add RD, 1 // RD = nresults+1
314 | mov NRESULTS, RD
315 | test PC, FRAME_TYPE
316 | jz ->BC_RET_Z // Handle regular return to Lua.
317 | jmp ->vm_return
318 |
290 |->gate_c: // Call gate for C functions. 319 |->gate_c: // Call gate for C functions.
291 | // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return 320 | // RA = new base, RB = CFUNC, RC = nargs+1, (BASE = old base), PC = return
292 | mov [RA-4], PC 321 | mov [RA-4], PC
@@ -312,6 +341,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
312 | mov NRESULTS, RD 341 | mov NRESULTS, RD
313 | test PC, FRAME_TYPE 342 | test PC, FRAME_TYPE
314 | jz ->BC_RET_Z // Handle regular return to Lua. 343 | jz ->BC_RET_Z // Handle regular return to Lua.
344 | // Fallthrough.
315 | 345 |
316 |//-- Return handling (non-inline) --------------------------------------- 346 |//-- Return handling (non-inline) ---------------------------------------
317 | 347 |
@@ -1455,7 +1485,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov)
1455 | mov ARG5, RA 1485 | mov ARG5, RA
1456 | fstp FPARG1 1486 | fstp FPARG1
1457 | mov RB, BASE 1487 | mov RB, BASE
1458 | call extern func 1488 | call extern lj_wrapper_ .. func
1459 | mov RA, ARG5 1489 | mov RA, ARG5
1460 | mov BASE, RB 1490 | mov BASE, RB
1461 | jmp ->fff_resn 1491 | jmp ->fff_resn
@@ -3584,6 +3614,85 @@ static void emit_asm_debug(BuildCtx *ctx)
3584 "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ 3614 "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */
3585 "\t.align 4\n" 3615 "\t.align 4\n"
3586 ".LEFDE0:\n\n", (int)ctx->codesz); 3616 ".LEFDE0:\n\n", (int)ctx->codesz);
3617 fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
3618 fprintf(ctx->fp,
3619 ".Lframe1:\n"
3620 "\t.long .LECIE1-.LSCIE1\n"
3621 ".LSCIE1:\n"
3622 "\t.long 0\n"
3623 "\t.byte 0x1\n"
3624 "\t.string \"zPR\"\n"
3625 "\t.uleb128 0x1\n"
3626 "\t.sleb128 -4\n"
3627 "\t.byte 0x8\n"
3628 "\t.uleb128 6\n" /* augmentation length */
3629 "\t.byte 0x1b\n" /* pcrel|sdata4 */
3630 "\t.long lj_err_unwind_dwarf-.\n"
3631 "\t.byte 0x1b\n" /* pcrel|sdata4 */
3632 "\t.byte 0xc\n\t.uleb128 0x4\n\t.uleb128 0x4\n"
3633 "\t.byte 0x88\n\t.uleb128 0x1\n"
3634 "\t.align 4\n"
3635 ".LECIE1:\n\n");
3636 fprintf(ctx->fp,
3637 ".LSFDE1:\n"
3638 "\t.long .LEFDE1-.LASFDE1\n"
3639 ".LASFDE1:\n"
3640 "\t.long .LASFDE1-.Lframe1\n"
3641 "\t.long .Lbegin-.\n"
3642 "\t.long %d\n"
3643 "\t.uleb128 0\n" /* augmentation length */
3644 "\t.byte 0xe\n\t.uleb128 0x30\n" /* def_cfa_offset */
3645 "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */
3646 "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */
3647 "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */
3648 "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */
3649 "\t.align 4\n"
3650 ".LEFDE1:\n\n", (int)ctx->codesz);
3651 break;
3652 case BUILD_machasm:
3653 /* NYI: OSX ignores it. Something must be missing. */
3654 fprintf(ctx->fp, "\t.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support\n");
3655 fprintf(ctx->fp,
3656 "EH_frame1:\n"
3657 "\t.set L$set$0,LECIE1-LSCIE1\n"
3658 "\t.long L$set$0\n"
3659 "LSCIE1:\n"
3660 "\t.long 0\n"
3661 "\t.byte 0x1\n"
3662 "\t.ascii \"zPR\"\n"
3663 "\t.byte 0x1\n"
3664 "\t.byte 128-4\n"
3665 "\t.byte 0x8\n"
3666 "\t.byte 6\n" /* augmentation length */
3667 "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */
3668 "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n"
3669 "\t.byte 0x1b\n" /* pcrel|sdata4 */
3670 "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */
3671 "\t.byte 0x88\n\t.byte 0x1\n"
3672 "\t.align 2\n"
3673 "LECIE1:\n\n");
3674 fprintf(ctx->fp,
3675 "_lj_vm_asm_begin.eh:\n"
3676 "LSFDE1:\n"
3677 "\t.set L$set$1,LEFDE1-LASFDE1\n"
3678 "\t.long L$set$1\n"
3679 "LASFDE1:\n"
3680 "\t.long LASFDE1-EH_frame1\n"
3681 "\t.long _lj_vm_asm_begin-.\n"
3682 "\t.long %d\n"
3683 "\t.byte 0\n" /* augmentation length */
3684 "\t.byte 0xe\n\t.byte 0x30\n" /* def_cfa_offset */
3685 "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/
3686 "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */
3687 "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */
3688 "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */
3689 "\t.align 2\n"
3690 "LEFDE1:\n\n", (int)ctx->codesz);
3691 fprintf(ctx->fp,
3692 "\t.non_lazy_symbol_pointer\n"
3693 "L_lj_err_unwind_dwarf$non_lazy_ptr:\n"
3694 ".indirect_symbol _lj_err_unwind_dwarf\n"
3695 ".long 0\n");
3587 break; 3696 break;
3588 default: /* Difficult for other modes. */ 3697 default: /* Difficult for other modes. */
3589 break; 3698 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 @@
20#include "lj_err.h" 20#include "lj_err.h"
21#include "lj_lib.h" 21#include "lj_lib.h"
22 22
23/* convert a stack index to positive */
24#define abs_index(L, i) \
25 ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
26
27/* -- Type checks --------------------------------------------------------- */
28
29LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
30{
31 if (!lua_checkstack(L, size))
32 lj_err_callerv(L, LJ_ERR_STKOVM, msg);
33}
34
35LUALIB_API void luaL_checktype(lua_State *L, int narg, int tt)
36{
37 if (lua_type(L, narg) != tt)
38 lj_err_argt(L, narg, tt);
39}
40
41LUALIB_API void luaL_checkany(lua_State *L, int narg)
42{
43 lj_lib_checkany(L, narg);
44}
45
46LUALIB_API const char *luaL_checklstring(lua_State *L, int narg, size_t *len)
47{
48 GCstr *s = lj_lib_checkstr(L, narg);
49 if (len != NULL) *len = s->len;
50 return strdata(s);
51}
52
53LUALIB_API const char *luaL_optlstring(lua_State *L, int narg,
54 const char *def, size_t *len)
55{
56 GCstr *s = lj_lib_optstr(L, narg);
57 if (s) {
58 if (len != NULL) *len = s->len;
59 return strdata(s);
60 }
61 if (len != NULL) *len = def ? strlen(def) : 0;
62 return def;
63}
64
65LUALIB_API lua_Number luaL_checknumber(lua_State *L, int narg)
66{
67 return lj_lib_checknum(L, narg);
68}
69
70LUALIB_API lua_Number luaL_optnumber(lua_State *L, int narg, lua_Number def)
71{
72 lj_lib_opt(L, narg,
73 return lj_lib_checknum(L, narg);
74 ,
75 return def;
76 )
77}
78
79LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int narg)
80{
81#if LJ_64
82 return (lua_Integer)lj_lib_checknum(L, narg);
83#else
84 return lj_lib_checkint(L, narg);
85#endif
86}
87
88LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int narg, lua_Integer def)
89{
90#if LJ_64
91 lj_lib_opt(L, narg,
92 return (lua_Integer)lj_lib_checknum(L, narg);
93 ,
94 return def;
95 )
96#else
97 return lj_lib_optint(L, narg, def);
98#endif
99}
100
101LUALIB_API int luaL_checkoption(lua_State *L, int narg, const char *def,
102 const char *const lst[])
103{
104 GCstr *s = lj_lib_optstr(L, narg);
105 const char *opt = s ? strdata(s) : def;
106 uint32_t i;
107 if (!opt) lj_err_argt(L, narg, LUA_TSTRING);
108 for (i = 0; lst[i]; i++)
109 if (strcmp(lst[i], opt) == 0)
110 return (int)i;
111 lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
112}
113
114/* -- Module registration ------------------------------------------------- */ 23/* -- Module registration ------------------------------------------------- */
115 24
116LUALIB_API const char *luaL_findtable(lua_State *L, int idx, 25LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
@@ -149,6 +58,7 @@ static int libsize(const luaL_Reg *l)
149LUALIB_API void luaL_openlib(lua_State *L, const char *libname, 58LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
150 const luaL_Reg *l, int nup) 59 const luaL_Reg *l, int nup)
151{ 60{
61 lj_lib_checkfpu(L);
152 if (libname) { 62 if (libname) {
153 int size = libsize(l); 63 int size = libsize(l);
154 /* check whether lib already exists */ 64 /* check whether lib already exists */
@@ -285,6 +195,10 @@ LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
285 195
286#define FREELIST_REF 0 196#define FREELIST_REF 0
287 197
198/* Convert a stack index to an absolute index. */
199#define abs_index(L, i) \
200 ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
201
288LUALIB_API int luaL_ref(lua_State *L, int t) 202LUALIB_API int luaL_ref(lua_State *L, int t)
289{ 203{
290 int ref; 204 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)
523 523
524LUALIB_API int luaopen_io(lua_State *L) 524LUALIB_API int luaopen_io(lua_State *L)
525{ 525{
526 LJ_LIB_REG_(L, NULL, io_method); 526 lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
527 lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); 527 if (tvisnil(L->top-1)) {
528 LJ_LIB_REG_(L, NULL, io_method);
529 lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
530 }
528 io_fenv_new(L, 0, lj_cf_io_pipe_close); /* top-3 */ 531 io_fenv_new(L, 0, lj_cf_io_pipe_close); /* top-3 */
529 io_fenv_new(L, 2, lj_cf_io_file_close); /* top-2 */ 532 io_fenv_new(L, 2, lj_cf_io_file_close); /* top-2 */
530 LJ_LIB_REG(L, io); 533 LJ_LIB_REG(L, io);
@@ -532,7 +535,7 @@ LUALIB_API int luaopen_io(lua_State *L)
532 io_std_new(L, stdin, IO_INPUT, "stdin"); 535 io_std_new(L, stdin, IO_INPUT, "stdin");
533 io_std_new(L, stdout, IO_OUTPUT, "stdout"); 536 io_std_new(L, stdout, IO_OUTPUT, "stdout");
534 io_std_new(L, stderr, 0, "stderr"); 537 io_std_new(L, stderr, 0, "stderr");
535 lua_pop(L, 1); 538 L->top--;
536 return 1; 539 return 1;
537} 540}
538 541
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)
73#if LJ_HASJIT 73#if LJ_HASJIT
74 if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) { 74 if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) {
75 int traceno = lj_lib_checkint(L, 1); 75 int traceno = lj_lib_checkint(L, 1);
76 luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE); 76 setboolV(L->top-1,
77 return 0; 77 luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE));
78 return 1;
78 } 79 }
79#endif 80#endif
80 return setjitmode(L, LUAJIT_MODE_FLUSH); 81 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)
69LJLIB_PUSH(3.14159265358979323846) LJLIB_SET(pi) 69LJLIB_PUSH(3.14159265358979323846) LJLIB_SET(pi)
70LJLIB_PUSH(1e310) LJLIB_SET(huge) 70LJLIB_PUSH(1e310) LJLIB_SET(huge)
71 71
72#ifdef __MACH__
73LJ_FUNCA double lj_wrapper_sinh(double x) { return sinh(x); } 72LJ_FUNCA double lj_wrapper_sinh(double x) { return sinh(x); }
74LJ_FUNCA double lj_wrapper_cosh(double x) { return cosh(x); } 73LJ_FUNCA double lj_wrapper_cosh(double x) { return cosh(x); }
75LJ_FUNCA double lj_wrapper_tanh(double x) { return tanh(x); } 74LJ_FUNCA double lj_wrapper_tanh(double x) { return tanh(x); }
76#endif
77 75
78/* ------------------------------------------------------------------------ */ 76/* ------------------------------------------------------------------------ */
79 77
@@ -98,8 +96,8 @@ typedef union { uint64_t u64; double d; } U64double;
98 z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \ 96 z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
99 r ^= z; tw->gen[i] = z; 97 r ^= z; tw->gen[i] = z;
100 98
101/* PRNG step function. Returns a double in the range 0.0 <= d < 1.0. */ 99/* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */
102static double tw223_step(TW223State *tw) 100static LJ_NOINLINE double tw223_step(TW223State *tw)
103{ 101{
104 uint64_t z, r = 0; 102 uint64_t z, r = 0;
105 U64double u; 103 U64double u;
@@ -108,16 +106,7 @@ static double tw223_step(TW223State *tw)
108 TW223_GEN(2, 55, 24, 7) 106 TW223_GEN(2, 55, 24, 7)
109 TW223_GEN(3, 47, 21, 8) 107 TW223_GEN(3, 47, 21, 8)
110 u.u64 = (r & (((uint64_t)1 << 52)-1)) | ((uint64_t)0x3ff << 52); 108 u.u64 = (r & (((uint64_t)1 << 52)-1)) | ((uint64_t)0x3ff << 52);
111#if defined(__GNUC__) && LJ_TARGET_X86 && __pic__ 109 return u.d;
112 /* Compensate for unbelievable GCC pessimization. */
113 {
114 volatile U64double u1;
115 u1.u64 = (uint64_t)0x3f8 << 52;
116 return u.d - u1.d;
117 }
118#else
119 return u.d - 1.0;
120#endif
121} 110}
122 111
123/* PRNG initialization function. */ 112/* PRNG initialization function. */
@@ -146,7 +135,7 @@ LJLIB_CF(math_random)
146 TW223State *tw = (TW223State *)(uddata(udataV(lj_lib_upvalue(L, 1)))); 135 TW223State *tw = (TW223State *)(uddata(udataV(lj_lib_upvalue(L, 1))));
147 double d; 136 double d;
148 if (LJ_UNLIKELY(!tw->valid)) tw223_init(tw, 0.0); 137 if (LJ_UNLIKELY(!tw->valid)) tw223_init(tw, 0.0);
149 d = tw223_step(tw); 138 d = tw223_step(tw) - 1.0;
150 if (n > 0) { 139 if (n > 0) {
151 double r1 = lj_lib_checknum(L, 1); 140 double r1 = lj_lib_checknum(L, 1);
152 if (n == 1) { 141 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)
354 lua_pushvalue(L, -1); /* extra copy to be returned */ 354 lua_pushvalue(L, -1); /* extra copy to be returned */
355 lua_setfield(L, 2, name); /* _LOADED[name] = true */ 355 lua_setfield(L, 2, name); /* _LOADED[name] = true */
356 } 356 }
357 lj_lib_checkfpu(L);
357 return 1; 358 return 1;
358} 359}
359 360
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 @@
16#include "lualib.h" 16#include "lualib.h"
17 17
18#include "lj_obj.h" 18#include "lj_obj.h"
19#include "lj_gc.h"
19#include "lj_err.h" 20#include "lj_err.h"
20#include "lj_str.h" 21#include "lj_str.h"
21#include "lj_tab.h" 22#include "lj_tab.h"
@@ -774,6 +775,7 @@ LJLIB_CF(string_format)
774LUALIB_API int luaopen_string(lua_State *L) 775LUALIB_API int luaopen_string(lua_State *L)
775{ 776{
776 GCtab *mt; 777 GCtab *mt;
778 GCstr *mmstr;
777 LJ_LIB_REG(L, string); 779 LJ_LIB_REG(L, string);
778#if defined(LUA_COMPAT_GFIND) 780#if defined(LUA_COMPAT_GFIND)
779 lua_getfield(L, -1, "gmatch"); 781 lua_getfield(L, -1, "gmatch");
@@ -782,8 +784,9 @@ LUALIB_API int luaopen_string(lua_State *L)
782 mt = lj_tab_new(L, 0, 1); 784 mt = lj_tab_new(L, 0, 1);
783 /* NOBARRIER: G(L)->mmname[] is a GC root. */ 785 /* NOBARRIER: G(L)->mmname[] is a GC root. */
784 setgcref(G(L)->basemt[~LJ_TSTR], obj2gco(mt)); 786 setgcref(G(L)->basemt[~LJ_TSTR], obj2gco(mt));
785 settabV(L, lj_tab_setstr(L, mt, strref(G(L)->mmname[MM_index])), 787 mmstr = strref(G(L)->mmname[MM_index]);
786 tabV(L->top-1)); 788 if (isdead(G(L), obj2gco(mmstr))) flipwhite(obj2gco(mmstr));
789 settabV(L, lj_tab_setstr(L, mt, mmstr), tabV(L->top-1));
787 mt->nomm = cast_byte(~(1u<<MM_index)); 790 mt->nomm = cast_byte(~(1u<<MM_index));
788 return 1; 791 return 1;
789} 792}
diff --git a/src/lib_table.c b/src/lib_table.c
index 68dc825b..df9007c8 100644
--- a/src/lib_table.c
+++ b/src/lib_table.c
@@ -74,21 +74,21 @@ LJLIB_CF(table_maxn)
74 TValue *array = tvref(t->array); 74 TValue *array = tvref(t->array);
75 Node *node; 75 Node *node;
76 lua_Number m = 0; 76 lua_Number m = 0;
77 uint32_t i; 77 ptrdiff_t i;
78 for (i = 0; i < t->asize; i++) 78 for (i = (ptrdiff_t)t->asize - 1; i >= 0; i--)
79 if (!tvisnil(&array[i])) { 79 if (!tvisnil(&array[i])) {
80 m = (lua_Number)i; 80 m = (lua_Number)(int32_t)i;
81 break; 81 break;
82 } 82 }
83 node = noderef(t->node); 83 node = noderef(t->node);
84 for (i = 0; i <= t->hmask; i++) 84 for (i = (ptrdiff_t)t->hmask; i >= 0; i--)
85 if (tvisnum(&node[i].key) && numV(&node[i].key) > m) 85 if (tvisnum(&node[i].key) && numV(&node[i].key) > m)
86 m = numV(&node[i].key); 86 m = numV(&node[i].key);
87 setnumV(L->top-1, m); 87 setnumV(L->top-1, m);
88 return 1; 88 return 1;
89} 89}
90 90
91LJLIB_CF(table_insert) 91LJLIB_CF(table_insert) LJLIB_REC(.)
92{ 92{
93 GCtab *t = lj_lib_checktab(L, 1); 93 GCtab *t = lj_lib_checktab(L, 1);
94 int32_t n, i = (int32_t)lj_tab_len(t) + 1; 94 int32_t n, i = (int32_t)lj_tab_len(t) + 1;
@@ -111,20 +111,20 @@ LJLIB_CF(table_insert)
111 } 111 }
112 { 112 {
113 TValue *dst = lj_tab_setint(L, t, i); 113 TValue *dst = lj_tab_setint(L, t, i);
114 copyTV(L, dst, L->top-1); 114 copyTV(L, dst, L->top-1); /* Set new value. */
115 lj_gc_barriert(L, t, dst); 115 lj_gc_barriert(L, t, dst);
116 } 116 }
117 return 0; 117 return 0;
118} 118}
119 119
120LJLIB_CF(table_remove) 120LJLIB_CF(table_remove) LJLIB_REC(.)
121{ 121{
122 GCtab *t = lj_lib_checktab(L, 1); 122 GCtab *t = lj_lib_checktab(L, 1);
123 int32_t e = (int32_t)lj_tab_len(t); 123 int32_t e = (int32_t)lj_tab_len(t);
124 int32_t pos = lj_lib_optint(L, 2, e); 124 int32_t pos = lj_lib_optint(L, 2, e);
125 if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ 125 if (!(1 <= pos && pos <= e)) /* Nothing to remove? */
126 return 0; /* nothing to remove */ 126 return 0;
127 lua_rawgeti(L, 1, pos); 127 lua_rawgeti(L, 1, pos); /* Get previous value. */
128 /* NOBARRIER: This just moves existing elements around. */ 128 /* NOBARRIER: This just moves existing elements around. */
129 for (; pos < e; pos++) { 129 for (; pos < e; pos++) {
130 cTValue *src = lj_tab_getint(t, pos+1); 130 cTValue *src = lj_tab_getint(t, pos+1);
@@ -135,8 +135,8 @@ LJLIB_CF(table_remove)
135 setnilV(dst); 135 setnilV(dst);
136 } 136 }
137 } 137 }
138 setnilV(lj_tab_setint(L, t, e)); 138 setnilV(lj_tab_setint(L, t, e)); /* Remove (last) value. */
139 return 1; 139 return 1; /* Return previous value. */
140} 140}
141 141
142LJLIB_CF(table_concat) 142LJLIB_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)
91 return 1; 91 return 1;
92} 92}
93 93
94LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
95{
96 if (!lua_checkstack(L, size))
97 lj_err_callerv(L, LJ_ERR_STKOVM, msg);
98}
99
94LUA_API void lua_xmove(lua_State *from, lua_State *to, int n) 100LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
95{ 101{
96 TValue *f, *t; 102 TValue *f, *t;
@@ -193,6 +199,18 @@ LUA_API int lua_type(lua_State *L, int idx)
193 } 199 }
194} 200}
195 201
202LUALIB_API void luaL_checktype(lua_State *L, int idx, int tt)
203{
204 if (lua_type(L, idx) != tt)
205 lj_err_argt(L, idx, tt);
206}
207
208LUALIB_API void luaL_checkany(lua_State *L, int idx)
209{
210 if (index2adr(L, idx) == niltv(L))
211 lj_err_arg(L, idx, LJ_ERR_NOVAL);
212}
213
196LUA_API const char *lua_typename(lua_State *L, int t) 214LUA_API const char *lua_typename(lua_State *L, int t)
197{ 215{
198 UNUSED(L); 216 UNUSED(L);
@@ -202,7 +220,7 @@ LUA_API const char *lua_typename(lua_State *L, int t)
202LUA_API int lua_iscfunction(lua_State *L, int idx) 220LUA_API int lua_iscfunction(lua_State *L, int idx)
203{ 221{
204 cTValue *o = index2adr(L, idx); 222 cTValue *o = index2adr(L, idx);
205 return !isluafunc(funcV(o)); 223 return tvisfunc(o) && !isluafunc(funcV(o));
206} 224}
207 225
208LUA_API int lua_isnumber(lua_State *L, int idx) 226LUA_API int lua_isnumber(lua_State *L, int idx)
@@ -295,6 +313,30 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
295 return 0; 313 return 0;
296} 314}
297 315
316LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
317{
318 cTValue *o = index2adr(L, idx);
319 TValue tmp;
320 if (tvisnum(o))
321 return numV(o);
322 else if (!(tvisstr(o) && lj_str_numconv(strVdata(o), &tmp)))
323 lj_err_argt(L, idx, LUA_TNUMBER);
324 return numV(&tmp);
325}
326
327LUALIB_API lua_Number luaL_optnumber(lua_State *L, int idx, lua_Number def)
328{
329 cTValue *o = index2adr(L, idx);
330 TValue tmp;
331 if (tvisnum(o))
332 return numV(o);
333 else if (tvisnil(o))
334 return def;
335 else if (!(tvisstr(o) && lj_str_numconv(strVdata(o), &tmp)))
336 lj_err_argt(L, idx, LUA_TNUMBER);
337 return numV(&tmp);
338}
339
298LUA_API lua_Integer lua_tointeger(lua_State *L, int idx) 340LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
299{ 341{
300 cTValue *o = index2adr(L, idx); 342 cTValue *o = index2adr(L, idx);
@@ -313,6 +355,44 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
313#endif 355#endif
314} 356}
315 357
358LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
359{
360 cTValue *o = index2adr(L, idx);
361 TValue tmp;
362 lua_Number n;
363 if (LJ_LIKELY(tvisnum(o)))
364 n = numV(o);
365 else if (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp))
366 n = numV(&tmp);
367 else
368 lj_err_argt(L, idx, LUA_TNUMBER);
369#if LJ_64
370 return (lua_Integer)n;
371#else
372 return lj_num2int(n);
373#endif
374}
375
376LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def)
377{
378 cTValue *o = index2adr(L, idx);
379 TValue tmp;
380 lua_Number n;
381 if (LJ_LIKELY(tvisnum(o)))
382 n = numV(o);
383 else if (tvisnil(o))
384 return def;
385 else if (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp))
386 n = numV(&tmp);
387 else
388 lj_err_argt(L, idx, LUA_TNUMBER);
389#if LJ_64
390 return (lua_Integer)n;
391#else
392 return lj_num2int(n);
393#endif
394}
395
316LUA_API int lua_toboolean(lua_State *L, int idx) 396LUA_API int lua_toboolean(lua_State *L, int idx)
317{ 397{
318 cTValue *o = index2adr(L, idx); 398 cTValue *o = index2adr(L, idx);
@@ -337,6 +417,57 @@ LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
337 return strdata(s); 417 return strdata(s);
338} 418}
339 419
420LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len)
421{
422 TValue *o = index2adr(L, idx);
423 GCstr *s;
424 if (LJ_LIKELY(tvisstr(o))) {
425 s = strV(o);
426 } else if (tvisnum(o)) {
427 lj_gc_check(L);
428 o = index2adr(L, idx); /* GC may move the stack. */
429 s = lj_str_fromnum(L, &o->n);
430 } else {
431 lj_err_argt(L, idx, LUA_TSTRING);
432 }
433 if (len != NULL) *len = s->len;
434 return strdata(s);
435}
436
437LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
438 const char *def, size_t *len)
439{
440 TValue *o = index2adr(L, idx);
441 GCstr *s;
442 if (LJ_LIKELY(tvisstr(o))) {
443 s = strV(o);
444 } else if (tvisnil(o)) {
445 if (len != NULL) *len = def ? strlen(def) : 0;
446 return def;
447 } else if (tvisnum(o)) {
448 lj_gc_check(L);
449 o = index2adr(L, idx); /* GC may move the stack. */
450 s = lj_str_fromnum(L, &o->n);
451 } else {
452 lj_err_argt(L, idx, LUA_TSTRING);
453 }
454 if (len != NULL) *len = s->len;
455 return strdata(s);
456}
457
458LUALIB_API int luaL_checkoption(lua_State *L, int idx, const char *def,
459 const char *const lst[])
460{
461 ptrdiff_t i;
462 const char *s = lua_tolstring(L, idx, NULL);
463 if (s == NULL && (s = def) == NULL)
464 lj_err_argt(L, idx, LUA_TSTRING);
465 for (i = 0; lst[i]; i++)
466 if (strcmp(lst[i], s) == 0)
467 return (int)i;
468 lj_err_argv(L, idx, LJ_ERR_INVOPTM, s);
469}
470
340LUA_API size_t lua_objlen(lua_State *L, int idx) 471LUA_API size_t lua_objlen(lua_State *L, int idx)
341{ 472{
342 TValue *o = index2adr(L, idx); 473 TValue *o = index2adr(L, idx);
@@ -355,7 +486,8 @@ LUA_API size_t lua_objlen(lua_State *L, int idx)
355LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx) 486LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx)
356{ 487{
357 cTValue *o = index2adr(L, idx); 488 cTValue *o = index2adr(L, idx);
358 return funcV(o)->c.gate == lj_gate_c ? funcV(o)->c.f : NULL; 489 ASMFunction gate = funcV(o)->c.gate;
490 return (gate == lj_gate_c || gate == lj_gate_cwrap) ? funcV(o)->c.f : NULL;
359} 491}
360 492
361LUA_API void *lua_touserdata(lua_State *L, int idx) 493LUA_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)
738 } 738 }
739 RA_DBGX((as, "hintmiss $f $r", ref, r)); 739 RA_DBGX((as, "hintmiss $f $r", ref, r));
740 } 740 }
741 /* Invariants should preferably get unused registers. */ 741 /* Invariants should preferably get unmodified registers. */
742 if (ref < as->loopref && !irt_isphi(ir->t)) 742 if (ref < as->loopref && !irt_isphi(ir->t)) {
743 r = rset_pickbot(pick); 743 if ((pick & ~as->modset))
744 else 744 pick &= ~as->modset;
745 r = rset_pickbot(pick); /* Reduce conflicts with inverse allocation. */
746 } else {
745 r = rset_picktop(pick); 747 r = rset_picktop(pick);
748 }
746 } else { 749 } else {
747 r = ra_evict(as, allow); 750 r = ra_evict(as, allow);
748 } 751 }
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)
153 case LUAJIT_MODE_TRACE: 153 case LUAJIT_MODE_TRACE:
154 if (!(mode & LUAJIT_MODE_FLUSH)) 154 if (!(mode & LUAJIT_MODE_FLUSH))
155 return 0; /* Failed. */ 155 return 0; /* Failed. */
156 lj_trace_flush(G2J(g), idx); 156 return lj_trace_flush(G2J(g), idx);
157 break;
158#else 157#else
159 case LUAJIT_MODE_ENGINE: 158 case LUAJIT_MODE_ENGINE:
160 case LUAJIT_MODE_FUNC: 159 case LUAJIT_MODE_FUNC:
@@ -165,6 +164,20 @@ int luaJIT_setmode(lua_State *L, int idx, int mode)
165 return 0; /* Failed. */ 164 return 0; /* Failed. */
166 break; 165 break;
167#endif 166#endif
167 case LUAJIT_MODE_WRAPCFUNC:
168 if ((mode & LUAJIT_MODE_ON)) {
169 if (idx != 0) {
170 cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx;
171 if (tvislightud(tv) && lightudV(tv) != NULL)
172 g->wrapf = (lua_CFunction)lightudV(tv);
173 else
174 return 0; /* Failed. */
175 }
176 g->wrapmode = 1;
177 } else {
178 g->wrapmode = 0;
179 }
180 break;
168 default: 181 default:
169 return 0; /* Failed. */ 182 return 0; /* Failed. */
170 } 183 }
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,
676{ 676{
677 const char *fname = "?"; 677 const char *fname = "?";
678 const char *ftype = getfuncname(L, L->base - 1, &fname); 678 const char *ftype = getfuncname(L, L->base - 1, &fname);
679 if (narg < 0 && narg > LUA_REGISTRYINDEX)
680 narg = (L->top - L->base) + narg + 1;
679 if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ 681 if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */
680 msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); 682 msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg);
681 else 683 else
@@ -761,3 +763,47 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...)
761 return 0; /* unreachable */ 763 return 0; /* unreachable */
762} 764}
763 765
766/* -- C++ exception support ----------------------------------------------- */
767
768#if defined(__ELF__) || defined(__MACH__)
769typedef enum
770{
771 _URC_NO_REASON,
772 _URC_FOREIGN_EXCEPTION_CAUGHT,
773 _URC_FATAL_PHASE2_ERROR,
774 _URC_FATAL_PHASE1_ERROR,
775 _URC_NORMAL_STOP,
776 _URC_END_OF_STACK,
777 _URC_HANDLER_FOUND,
778 _URC_INSTALL_CONTEXT,
779 _URC_CONTINUE_UNWIND
780} _Unwind_Reason_Code;
781
782#define _UA_SEARCH_PHASE 1
783#define _UA_CLEANUP_PHASE 2
784#define _UA_HANDLER_FRAME 4
785#define _UA_FORCE_UNWIND 8
786#define _UA_END_OF_STACK 16
787
788extern void *_Unwind_GetCFA(void *ctx);
789extern void _Unwind_DeleteException(void *uex);
790
791/* DWARF2 personality handler referenced from .eh_frame. */
792LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, uint64_t uexclass,
793 void *uex, void *ctx)
794{
795 if (version != 1)
796 return _URC_FATAL_PHASE1_ERROR;
797 UNUSED(uexclass);
798 if ((actions & _UA_SEARCH_PHASE))
799 return _URC_HANDLER_FOUND;
800 if ((actions & _UA_HANDLER_FRAME)) {
801 void *cf = _Unwind_GetCFA(ctx);
802 lua_State *L = cframe_L(cf);
803 _Unwind_DeleteException(uex);
804 lj_err_msg(L, LJ_ERR_ERRCPP);
805 }
806 return _URC_CONTINUE_UNWIND;
807}
808#endif
809
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 @@
8/* Basic error handling. */ 8/* Basic error handling. */
9ERRDEF(ERRMEM, "not enough memory") 9ERRDEF(ERRMEM, "not enough memory")
10ERRDEF(ERRERR, "error in error handling") 10ERRDEF(ERRERR, "error in error handling")
11ERRDEF(ERRCPP, "C++ exception")
11 12
12/* Allocations. */ 13/* Allocations. */
13ERRDEF(STROV, "string length overflow") 14ERRDEF(STROV, "string length overflow")
@@ -56,6 +57,9 @@ ERRDEF(NOENV, "no calling environment")
56ERRDEF(CYIELD, "attempt to yield across C-call boundary") 57ERRDEF(CYIELD, "attempt to yield across C-call boundary")
57ERRDEF(BADLU, "bad light userdata pointer") 58ERRDEF(BADLU, "bad light userdata pointer")
58ERRDEF(NOGCMM, "bad action while in __gc metamethod") 59ERRDEF(NOGCMM, "bad action while in __gc metamethod")
60#ifdef LUA_USE_WIN
61ERRDEF(BADFPU, "bad FPU precision (use D3DCREATE_FPU_PRESERVE with DirectX)")
62#endif
59 63
60/* Standard library function errors. */ 64/* Standard library function errors. */
61ERRDEF(ASSERT, "assertion failed!") 65ERRDEF(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)
138 fn->c.nupvalues = cast_byte(nelems); 138 fn->c.nupvalues = cast_byte(nelems);
139 /* NOBARRIER: The GCfunc is new (marked white). */ 139 /* NOBARRIER: The GCfunc is new (marked white). */
140 setgcref(fn->c.env, obj2gco(env)); 140 setgcref(fn->c.env, obj2gco(env));
141 fn->c.gate = lj_gate_c; 141 fn->c.gate = G(L)->wrapmode ? lj_gate_cwrap : lj_gate_c;
142 return fn; 142 return fn;
143} 143}
144 144
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)
230 230
231/* The current trace is a GC root while not anchored in the prototype (yet). */ 231/* The current trace is a GC root while not anchored in the prototype (yet). */
232#define gc_mark_curtrace(g) \ 232#define gc_mark_curtrace(g) \
233 { if (G2J(g)->state != LJ_TRACE_IDLE && G2J(g)->curtrace != 0) \ 233 { if (G2J(g)->curtrace != 0) gc_traverse_trace(g, &G2J(g)->cur); }
234 gc_traverse_trace(g, &G2J(g)->cur); }
235#else 234#else
236#define gc_mark_curtrace(g) UNUSED(g) 235#define gc_mark_curtrace(g) UNUSED(g)
237#endif 236#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)
252{ 252{
253 IRIns *ir, *cir = J->cur.ir; 253 IRIns *ir, *cir = J->cur.ir;
254 IRRef ref; 254 IRRef ref;
255 lua_assert(!isdead(J2G(J), o));
255 for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) 256 for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev)
256 if (ir_kgc(&cir[ref]) == o) 257 if (ir_kgc(&cir[ref]) == o)
257 goto found; 258 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);
48#define lj_lib_upvalue(L, n) \ 48#define lj_lib_upvalue(L, n) \
49 (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1]) 49 (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1])
50 50
51#ifdef LUA_USE_WIN
52#define lj_lib_checkfpu(L) \
53 do { setnumV(L->top++, (lua_Number)1437217655); \
54 if (lua_tointeger(L, -1) != 1437217655) lj_err_caller(L, LJ_ERR_BADFPU); \
55 L->top--; } while (0)
56#else
57#define lj_lib_checkfpu(L) UNUSED(L)
58#endif
59
51/* Library function declarations. Scanned by buildvm. */ 60/* Library function declarations. Scanned by buildvm. */
52#define LJLIB_CF(name) static int lj_cf_##name(lua_State *L) 61#define LJLIB_CF(name) static int lj_cf_##name(lua_State *L)
53#define LJLIB_ASM(name) static int lj_ffh_##name(lua_State *L) 62#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 {
531 uint8_t hookmask; /* Hook mask. */ 531 uint8_t hookmask; /* Hook mask. */
532 uint8_t dispatchmode; /* Dispatch mode. */ 532 uint8_t dispatchmode; /* Dispatch mode. */
533 uint8_t vmevmask; /* VM event mask. */ 533 uint8_t vmevmask; /* VM event mask. */
534 uint8_t unused1; 534 uint8_t wrapmode; /* Wrap mode. */
535 GCRef mainthref; /* Link to main thread. */ 535 GCRef mainthref; /* Link to main thread. */
536 TValue registrytv; /* Anchor for registry. */ 536 TValue registrytv; /* Anchor for registry. */
537 TValue tmptv; /* Temporary TValue. */ 537 TValue tmptv; /* Temporary TValue. */
@@ -539,6 +539,7 @@ typedef struct global_State {
539 int32_t hookcount; /* Instruction hook countdown. */ 539 int32_t hookcount; /* Instruction hook countdown. */
540 int32_t hookcstart; /* Start count for instruction hook counter. */ 540 int32_t hookcstart; /* Start count for instruction hook counter. */
541 lua_Hook hookf; /* Hook function. */ 541 lua_Hook hookf; /* Hook function. */
542 lua_CFunction wrapf; /* Wrapper for C function calls. */
542 lua_CFunction panic; /* Called as a last resort for errors. */ 543 lua_CFunction panic; /* Called as a last resort for errors. */
543 volatile int32_t vmstate; /* VM state or current JIT code trace number. */ 544 volatile int32_t vmstate; /* VM state or current JIT code trace number. */
544 GCRef jit_L; /* Current JIT code lua_State or NULL. */ 545 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);
138/* Macros for the fold specs, so buildvm can recognize them. */ 138/* Macros for the fold specs, so buildvm can recognize them. */
139#define LJFOLD(x) 139#define LJFOLD(x)
140#define LJFOLDX(x) 140#define LJFOLDX(x)
141#define LJFOLDF(name) static TRef LJ_FASTCALL name(jit_State *J) 141#define LJFOLDF(name) static TRef LJ_FASTCALL fold_##name(jit_State *J)
142/* Note: They must be at the start of a line or buildvm ignores them! */ 142/* Note: They must be at the start of a line or buildvm ignores them! */
143 143
144/* Barrier to prevent using operands across PHIs. */ 144/* Barrier to prevent using operands across PHIs. */
@@ -979,7 +979,7 @@ LJFOLDF(comm_equal)
979 /* For non-numbers only: x == x ==> drop; x ~= x ==> fail */ 979 /* For non-numbers only: x == x ==> drop; x ~= x ==> fail */
980 if (fins->op1 == fins->op2 && !irt_isnum(fins->t)) 980 if (fins->op1 == fins->op2 && !irt_isnum(fins->t))
981 return CONDFOLD(fins->o == IR_EQ); 981 return CONDFOLD(fins->o == IR_EQ);
982 return comm_swap(J); 982 return fold_comm_swap(J);
983} 983}
984 984
985LJFOLD(LT any any) 985LJFOLD(LT any any)
@@ -1013,7 +1013,7 @@ LJFOLDF(comm_dup)
1013{ 1013{
1014 if (fins->op1 == fins->op2) /* x o x ==> x */ 1014 if (fins->op1 == fins->op2) /* x o x ==> x */
1015 return LEFTFOLD; 1015 return LEFTFOLD;
1016 return comm_swap(J); 1016 return fold_comm_swap(J);
1017} 1017}
1018 1018
1019LJFOLD(BXOR any any) 1019LJFOLD(BXOR any any)
@@ -1021,7 +1021,7 @@ LJFOLDF(comm_bxor)
1021{ 1021{
1022 if (fins->op1 == fins->op2) /* i xor i ==> 0 */ 1022 if (fins->op1 == fins->op2) /* i xor i ==> 0 */
1023 return INTFOLD(0); 1023 return INTFOLD(0);
1024 return comm_swap(J); 1024 return fold_comm_swap(J);
1025} 1025}
1026 1026
1027/* -- Simplification of compound expressions ------------------------------ */ 1027/* -- 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)
286 if (!irt_sametype(t, irr->t)) { 286 if (!irt_sametype(t, irr->t)) {
287 if (irt_isnum(t) && irt_isinteger(irr->t)) /* Fix int->num case. */ 287 if (irt_isnum(t) && irt_isinteger(irr->t)) /* Fix int->num case. */
288 subst[ins] = tref_ref(emitir(IRTN(IR_TONUM), ref, 0)); 288 subst[ins] = tref_ref(emitir(IRTN(IR_TONUM), ref, 0));
289 else 289 else if (!(irt_isinteger(t) && irt_isinteger(irr->t)))
290 lj_trace_err(J, LJ_TRERR_TYPEINS); 290 lj_trace_err(J, LJ_TRERR_TYPEINS);
291 } 291 }
292 } 292 }
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)
519 } else if (irt_isnil(store->t)) { /* Must check any nil store. */ 519 } else if (irt_isnil(store->t)) { /* Must check any nil store. */
520 IRRef skref = IR(store->op1)->op2; 520 IRRef skref = IR(store->op1)->op2;
521 IRRef xkref = IR(xref)->op2; 521 IRRef xkref = IR(xref)->op2;
522 /* Same key type MAY alias. */ 522 /* Same key type MAY alias. Need ALOAD check due to multiple int types. */
523 if (irt_sametype(IR(skref)->t, IR(xkref)->t)) { 523 if (loadop == IR_ALOAD || irt_sametype(IR(skref)->t, IR(xkref)->t)) {
524 if (skref == xkref || !irref_isk(skref) || !irref_isk(xkref)) 524 if (skref == xkref || !irref_isk(skref) || !irref_isk(xkref))
525 return 0; /* A nil store with same const key or var key MAY alias. */ 525 return 0; /* A nil store with same const key or var key MAY alias. */
526 /* Different const keys CANNOT alias. */ 526 /* 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)
168{ 168{
169 int diff = !lj_obj_equal(av, bv); 169 int diff = !lj_obj_equal(av, bv);
170 if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */ 170 if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */
171 IRType ta = tref_type(a); 171 IRType ta = tref_isinteger(a) ? IRT_INT : tref_type(a);
172 IRType tb = tref_type(b); 172 IRType tb = tref_isinteger(b) ? IRT_INT : tref_type(b);
173 if (ta != tb) { 173 if (ta != tb) {
174 /* Widen mixed number/int comparisons to number/number comparison. */ 174 /* Widen mixed number/int comparisons to number/number comparison. */
175 if (ta == IRT_INT && tb == IRT_NUM) { 175 if (ta == IRT_INT && tb == IRT_NUM) {
@@ -447,7 +447,7 @@ static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
447 mix.tab = lj_ir_ktab(J, mt); 447 mix.tab = lj_ir_ktab(J, mt);
448 goto nocheck; 448 goto nocheck;
449 } 449 }
450 ix->mt = mix.tab; 450 ix->mt = mt ? mix.tab : TREF_NIL;
451 emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB)); 451 emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB));
452nocheck: 452nocheck:
453 if (mt) { 453 if (mt) {
@@ -457,6 +457,8 @@ nocheck:
457 copyTV(J->L, &ix->mobjv, mo); 457 copyTV(J->L, &ix->mobjv, mo);
458 ix->mtv = mt; 458 ix->mtv = mt;
459 settabV(J->L, &mix.tabv, mt); 459 settabV(J->L, &mix.tabv, mt);
460 if (isdead(J2G(J), obj2gco(mmstr)))
461 flipwhite(obj2gco(mmstr)); /* Need same logic as lj_str_new(). */
460 setstrV(J->L, &mix.keyv, mmstr); 462 setstrV(J->L, &mix.keyv, mmstr);
461 mix.key = lj_ir_kstr(J, mmstr); 463 mix.key = lj_ir_kstr(J, mmstr);
462 mix.val = 0; 464 mix.val = 0;
@@ -880,7 +882,7 @@ static void recff_nyi(jit_State *J, TRef *res, RecordFFData *rd)
880 lj_trace_err_info(J, LJ_TRERR_NYIFF); 882 lj_trace_err_info(J, LJ_TRERR_NYIFF);
881} 883}
882 884
883LJ_NORET static void recff_err_ffu(jit_State *J, RecordFFData *rd) 885LJ_NORET static void recff_err_nyi(jit_State *J, RecordFFData *rd)
884{ 886{
885 setfuncV(J->L, &J->errinfo, rd->fn); 887 setfuncV(J->L, &J->errinfo, rd->fn);
886 lj_trace_err_info(J, LJ_TRERR_NYIFFU); 888 lj_trace_err_info(J, LJ_TRERR_NYIFFU);
@@ -986,7 +988,7 @@ static void recff_tonumber(jit_State *J, TRef *res, RecordFFData *rd)
986 if (arg[1]) { 988 if (arg[1]) {
987 TRef base = lj_ir_toint(J, arg[1]); 989 TRef base = lj_ir_toint(J, arg[1]);
988 if (!tref_isk(base) || IR(tref_ref(base))->i != 10) 990 if (!tref_isk(base) || IR(tref_ref(base))->i != 10)
989 recff_err_ffu(J, rd); 991 recff_err_nyi(J, rd);
990 } 992 }
991 if (tref_isstr(tr)) 993 if (tref_isstr(tr))
992 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); 994 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
@@ -1016,7 +1018,7 @@ static void recff_tostring(jit_State *J, TRef *res, RecordFFData *rd)
1016 } else if (tref_isnumber(tr)) { 1018 } else if (tref_isnumber(tr)) {
1017 res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); 1019 res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
1018 } else { 1020 } else {
1019 recff_err_ffu(J, rd); 1021 recff_err_nyi(J, rd);
1020 } 1022 }
1021 } 1023 }
1022} 1024}
@@ -1338,6 +1340,58 @@ static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd)
1338 UNUSED(rd); 1340 UNUSED(rd);
1339} 1341}
1340 1342
1343static void recff_table_remove(jit_State *J, TRef *res, RecordFFData *rd)
1344{
1345 if (tref_istab(arg[0])) {
1346 if (!arg[1] || tref_isnil(arg[1])) { /* Simple pop: t[#t] = nil */
1347 TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0);
1348 GCtab *t = tabV(&rd->argv[0]);
1349 MSize len = lj_tab_len(t);
1350 emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0));
1351 if (len) {
1352 RecordIndex ix;
1353 ix.tab = arg[0];
1354 ix.key = trlen;
1355 settabV(J->L, &ix.tabv, t);
1356 setintV(&ix.keyv, len);
1357 ix.idxchain = 0;
1358 if (rd->cres != 0) { /* Specialize load only if result needed. */
1359 ix.val = 0;
1360 res[0] = rec_idx(J, &ix); /* Load previous value. */
1361 /* Assumes ix.key/ix.tab is not modified for raw rec_idx(). */
1362 }
1363 ix.val = TREF_NIL;
1364 rec_idx(J, &ix); /* Remove value. */
1365 } else {
1366 rd->nres = 0;
1367 }
1368 } else { /* Complex case: remove in the middle. */
1369 recff_err_nyi(J, rd);
1370 }
1371 } /* else: Interpreter will throw. */
1372}
1373
1374static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd)
1375{
1376 rd->nres = 0;
1377 if (tref_istab(arg[0]) && arg[1]) {
1378 if (!arg[2]) { /* Simple push: t[#t+1] = v */
1379 TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0);
1380 GCtab *t = tabV(&rd->argv[0]);
1381 RecordIndex ix;
1382 ix.tab = arg[0];
1383 ix.val = arg[1];
1384 ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
1385 settabV(J->L, &ix.tabv, t);
1386 setintV(&ix.keyv, lj_tab_len(t) + 1);
1387 ix.idxchain = 0;
1388 rec_idx(J, &ix); /* Set new value. */
1389 } else { /* Complex case: insert in the middle. */
1390 recff_err_nyi(J, rd);
1391 }
1392 } /* else: Interpreter will throw. */
1393}
1394
1341/* -- Record calls and returns -------------------------------------------- */ 1395/* -- Record calls and returns -------------------------------------------- */
1342 1396
1343#undef arg 1397#undef arg
@@ -1618,8 +1672,8 @@ void lj_record_ins(jit_State *J)
1618 case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: 1672 case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
1619 /* Emit nothing for two numeric or string consts. */ 1673 /* Emit nothing for two numeric or string consts. */
1620 if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) { 1674 if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
1621 IRType ta = tref_type(ra); 1675 IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
1622 IRType tc = tref_type(rc); 1676 IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc);
1623 int irop; 1677 int irop;
1624 if (ta != tc) { 1678 if (ta != tc) {
1625 /* Widen mixed number/int comparisons to number/number comparison. */ 1679 /* 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)
191 Node *kn = &knode[i]; 191 Node *kn = &knode[i];
192 Node *n = &node[i]; 192 Node *n = &node[i];
193 Node *next = nextnode(kn); 193 Node *next = nextnode(kn);
194 copyTV(L, &n->val, &kn->val); 194 /* Don't use copyTV here, since it asserts on a copy of a DEADKEY. */
195 copyTV(L, &n->key, &kn->key); 195 n->val = kn->val; n->key = kn->key;
196 setmref(n->next, next == NULL? next : (Node *)((char *)next + d)); 196 setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
197 } 197 }
198 } 198 }
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)
191 } 191 }
192} 192}
193 193
194/* Flush a root trace and any attached side traces. */ 194/* Free a root trace and any attached side traces. */
195void lj_trace_flush(jit_State *J, TraceNo traceno) 195static void trace_freeroot(jit_State *J, Trace *T, TraceNo traceno)
196{ 196{
197 Trace *T = NULL; 197 GCproto *pt = &gcref(T->startpt)->pt;
198 GCproto *pt; 198 TraceNo side;
199 if (traceno > 0 && traceno <= J->sizetrace) 199 lua_assert(T->root == 0 && pt != NULL);
200 T = J->trace[traceno]; 200 /* First unpatch any modified bytecode. */
201 if (T == NULL) 201 trace_unpatch(J, T);
202 return; 202 /* Unlink root trace from chain anchored in prototype. */
203 pt = &gcref(T->startpt)->pt; 203 if (pt->trace == traceno) { /* Trace is first in chain. Easy. */
204 if (T->root == 0 && pt != NULL) { 204 pt->trace = T->nextroot;
205 TraceNo side; 205 } else { /* Otherwise search in chain of root traces. */
206 /* First unpatch any modified bytecode. */ 206 Trace *T2 = J->trace[pt->trace];
207 trace_unpatch(J, T); 207 while (T2->nextroot != traceno) {
208 /* Unlink root trace from chain anchored in prototype. */ 208 lua_assert(T2->nextroot != 0);
209 if (pt->trace == traceno) { /* Trace is first in chain. Easy. */ 209 T2 = J->trace[T2->nextroot];
210 pt->trace = T->nextroot;
211 } else { /* Otherwise search in chain of root traces. */
212 Trace *T2 = J->trace[pt->trace];
213 while (T2->nextroot != traceno) {
214 lua_assert(T2->nextroot != 0);
215 T2 = J->trace[T2->nextroot];
216 }
217 T2->nextroot = T->nextroot; /* Unlink from chain. */
218 } 210 }
219 /* Free all side traces. */ 211 T2->nextroot = T->nextroot; /* Unlink from chain. */
220 for (side = T->nextside; side != 0; ) { 212 }
221 TraceNo next = J->trace[side]->nextside; 213 /* Free all side traces. */
222 trace_free(J, side); 214 for (side = T->nextside; side != 0; ) {
223 side = next; 215 TraceNo next = J->trace[side]->nextside;
216 trace_free(J, side);
217 side = next;
218 }
219 /* Now free the trace itself. */
220 trace_free(J, traceno);
221}
222
223/* Flush a root trace + side traces, if there are no links to it. */
224int lj_trace_flush(jit_State *J, TraceNo traceno)
225{
226 if (traceno > 0 && traceno < J->sizetrace) {
227 Trace *T = J->trace[traceno];
228 if (T && T->root == 0) {
229 ptrdiff_t i;
230 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--)
231 if (i != (ptrdiff_t)traceno && J->trace[i] &&
232 J->trace[i]->root != traceno && J->trace[i]->link == traceno)
233 return 0; /* Failed: existing link to trace. */
234 trace_freeroot(J, T, traceno);
235 return 1; /* Ok. */
224 } 236 }
225 /* Now free the trace itself. */ 237 }
226 trace_free(J, traceno); 238 return 0; /* Failed. */
227 } /* Flush for non-root traces is currently ignored. */
228} 239}
229 240
230/* Flush all traces associated with a prototype. */ 241/* Flush all traces associated with a prototype. */
231void lj_trace_flushproto(global_State *g, GCproto *pt) 242void lj_trace_flushproto(global_State *g, GCproto *pt)
232{ 243{
233 while (pt->trace != 0) 244 while (pt->trace != 0)
234 lj_trace_flush(G2J(g), pt->trace); 245 trace_freeroot(G2J(g), G2J(g)->trace[pt->trace], pt->trace);
235} 246}
236 247
237/* Flush all traces. */ 248/* Flush all traces. */
@@ -241,8 +252,11 @@ int lj_trace_flushall(lua_State *L)
241 ptrdiff_t i; 252 ptrdiff_t i;
242 if ((J2G(J)->hookmask & HOOK_GC)) 253 if ((J2G(J)->hookmask & HOOK_GC))
243 return 1; 254 return 1;
244 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) 255 for (i = (ptrdiff_t)J->sizetrace-1; i > 0; i--) {
245 lj_trace_flush(J, (TraceNo)i); 256 Trace *T = J->trace[i];
257 if (T && T->root == 0)
258 trace_freeroot(J, T, (TraceNo)i);
259 }
246#ifdef LUA_USE_ASSERT 260#ifdef LUA_USE_ASSERT
247 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++) 261 for (i = 0; i < (ptrdiff_t)J->sizetrace; i++)
248 lua_assert(J->trace[i] == NULL); 262 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);
26LJ_FUNC void lj_trace_freeproto(global_State *g, GCproto *pt); 26LJ_FUNC void lj_trace_freeproto(global_State *g, GCproto *pt);
27LJ_FUNC void lj_trace_reenableproto(GCproto *pt); 27LJ_FUNC void lj_trace_reenableproto(GCproto *pt);
28LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt); 28LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt);
29LJ_FUNC void lj_trace_flush(jit_State *J, TraceNo traceno); 29LJ_FUNC int lj_trace_flush(jit_State *J, TraceNo traceno);
30LJ_FUNC int lj_trace_flushall(lua_State *L); 30LJ_FUNC int lj_trace_flushall(lua_State *L);
31LJ_FUNC void lj_trace_freestate(global_State *g); 31LJ_FUNC void lj_trace_freestate(global_State *g);
32 32
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);
46LJ_ASMF void lj_gate_lf(void); 46LJ_ASMF void lj_gate_lf(void);
47LJ_ASMF void lj_gate_lv(void); 47LJ_ASMF void lj_gate_lv(void);
48LJ_ASMF void lj_gate_c(void); 48LJ_ASMF void lj_gate_c(void);
49LJ_ASMF void lj_gate_cwrap(void);
49 50
50/* Continuations for metamethods. */ 51/* Continuations for metamethods. */
51LJ_ASMF void lj_cont_cat(void); /* Continue with concatenation. */ 52LJ_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. */
55LJ_ASMF void lj_cont_condf(void); /* Branch if result is false. */ 56LJ_ASMF void lj_cont_condf(void); /* Branch if result is false. */
56 57
57/* Start of the ASM code. */ 58/* Start of the ASM code. */
58LJ_ASMF void lj_vm_asm_begin(void); 59LJ_ASMF char lj_vm_asm_begin[];
59 60
60/* Opcode handler offsets, relative to lj_vm_asm_begin. */ 61/* Opcode handler offsets, relative to lj_vm_asm_begin. */
61LJ_ASMF const uint16_t lj_vm_op_ofs[]; 62LJ_ASMF const uint16_t lj_vm_op_ofs[];
62 63
63#define makeasmfunc(ofs) \ 64#define makeasmfunc(ofs) ((ASMFunction)(lj_vm_asm_begin + (ofs)))
64 ((ASMFunction)((char *)lj_vm_asm_begin + (ofs)))
65 65
66#endif 66#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 @@
1// lua.hpp 1// C++ wrapper for LuaJIT header files.
2// Lua header files for C++
3// <<extern "C">> not supplied automatically because Lua also compiles as C++
4 2
5extern "C" { 3extern "C" {
6#include "lua.h" 4#include "lua.h"
7#include "lualib.h"
8#include "lauxlib.h" 5#include "lauxlib.h"
6#include "lualib.h"
7#include "luajit.h"
9} 8}
9
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 @@
34 ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" 34 ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
35#else 35#else
36#define LUA_ROOT "/usr/local/" 36#define LUA_ROOT "/usr/local/"
37#define LUA_JDIR LUA_ROOT "share/luajit-2.0.0-beta1/"
38#define LUA_LDIR LUA_ROOT "share/lua/5.1/" 37#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
39#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" 38#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
39#ifdef LUA_XROOT
40#define LUA_JDIR LUA_XROOT "share/luajit-2.0.0-beta2/"
41#define LUA_XPATH \
42 ";" LUA_XROOT "share/lua/5.1/?.lua;" LUA_XROOT "share/lua/5.1/?/init.lua"
43#define LUA_XCPATH LUA_XROOT "lib/lua/5.1/?.lua;"
44#else
45#define LUA_JDIR LUA_ROOT "share/luajit-2.0.0-beta2/"
46#define LUA_XPATH
47#define LUA_XCPATH
48#endif
40#define LUA_PATH_DEFAULT \ 49#define LUA_PATH_DEFAULT \
41 "./?.lua;" LUA_JDIR"?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" 50 "./?.lua;" LUA_JDIR"?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua" LUA_XPATH
42#define LUA_CPATH_DEFAULT \ 51#define LUA_CPATH_DEFAULT \
43 "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" 52 "./?.so;" LUA_CDIR"?.so;" LUA_XCPATH LUA_CDIR"loadall.so"
44#endif 53#endif
45 54
46/* Environment variable names for path overrides and initialization code. */ 55/* 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)
55static void print_usage(void) 55static void print_usage(void)
56{ 56{
57 fprintf(stderr, 57 fprintf(stderr,
58 "usage: %s [options] [script [args]].\n" 58 "usage: %s [options]... [script [args]...].\n"
59 "Available options are:\n" 59 "Available options are:\n"
60 " -e stat execute string " LUA_QL("stat") "\n" 60 " -e chunk Execute string " LUA_QL("chunk") ".\n"
61 " -l name require library " LUA_QL("name") "\n" 61 " -l name Require library " LUA_QL("name") ".\n"
62 " -j cmd perform LuaJIT control command\n" 62 " -j cmd Perform LuaJIT control command.\n"
63 " -O[lvl] set LuaJIT optimization level\n" 63 " -O[opt] Control LuaJIT optimizations.\n"
64 " -i enter interactive mode after executing " LUA_QL("script") "\n" 64 " -i Enter interactive mode after executing " LUA_QL("script") ".\n"
65 " -v show version information\n" 65 " -v Show version information.\n"
66 " -- stop handling options\n" 66 " -- Stop handling options.\n"
67 " - execute stdin and stop handling options\n" 67 " - Execute stdin and stop handling options.\n"
68 , 68 ,
69 progname); 69 progname);
70 fflush(stderr); 70 fflush(stderr);
@@ -143,7 +143,7 @@ static void print_jit_status(lua_State *L)
143 fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stderr); 143 fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stderr);
144 for (n++; (s = lua_tostring(L, n)); n++) 144 for (n++; (s = lua_tostring(L, n)); n++)
145 fprintf(stderr, " %s", s); 145 fprintf(stderr, " %s", s);
146 fputs("\n", stdout); 146 fputs("\n", stderr);
147} 147}
148 148
149static int getargs(lua_State *L, char **argv, int n) 149static 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 @@
30 30
31#include "lua.h" 31#include "lua.h"
32 32
33#define LUAJIT_VERSION "LuaJIT 2.0.0-beta1" 33#define LUAJIT_VERSION "LuaJIT 2.0.0-beta2"
34#define LUAJIT_VERSION_NUM 20000 /* Version 2.0.0 = 02.00.00. */ 34#define LUAJIT_VERSION_NUM 20000 /* Version 2.0.0 = 02.00.00. */
35#define LUAJIT_VERSION_SYM luaJIT_version_2_0_0_beta1 35#define LUAJIT_VERSION_SYM luaJIT_version_2_0_0_beta2
36#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2009 Mike Pall" 36#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2009 Mike Pall"
37#define LUAJIT_URL "http://luajit.org/" 37#define LUAJIT_URL "http://luajit.org/"
38 38
@@ -49,12 +49,14 @@ enum {
49 49
50 LUAJIT_MODE_TRACE, /* Flush a compiled trace. */ 50 LUAJIT_MODE_TRACE, /* Flush a compiled trace. */
51 51
52 LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */
53
52 LUAJIT_MODE_MAX 54 LUAJIT_MODE_MAX
53}; 55};
54 56
55/* Flags or'ed in to the mode. */ 57/* Flags or'ed in to the mode. */
56#define LUAJIT_MODE_OFF 0x0000 /* Disable JIT compilation. */ 58#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */
57#define LUAJIT_MODE_ON 0x0100 /* (Re-)enable JIT compilation. */ 59#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */
58#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */ 60#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */
59 61
60/* LuaJIT public C API. */ 62/* LuaJIT public C API. */