diff options
Diffstat (limited to 'src/lj_err.c')
-rw-r--r-- | src/lj_err.c | 205 |
1 files changed, 128 insertions, 77 deletions
diff --git a/src/lj_err.c b/src/lj_err.c index 6619ad79..83118551 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "lj_ff.h" | 16 | #include "lj_ff.h" |
17 | #include "lj_trace.h" | 17 | #include "lj_trace.h" |
18 | #include "lj_vm.h" | 18 | #include "lj_vm.h" |
19 | #include "lj_strfmt.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | ** LuaJIT can either use internal or external frame unwinding: | 22 | ** LuaJIT can either use internal or external frame unwinding: |
@@ -45,7 +46,8 @@ | |||
45 | ** the wrapper function feature. Lua errors thrown through C++ frames | 46 | ** the wrapper function feature. Lua errors thrown through C++ frames |
46 | ** cannot be caught by C++ code and C++ destructors are not run. | 47 | ** cannot be caught by C++ code and C++ destructors are not run. |
47 | ** | 48 | ** |
48 | ** EXT is the default on x64 systems, INT is the default on all other systems. | 49 | ** EXT is the default on x64 systems and on Windows, INT is the default on all |
50 | ** other systems. | ||
49 | ** | 51 | ** |
50 | ** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack | 52 | ** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack |
51 | ** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled | 53 | ** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled |
@@ -54,7 +56,6 @@ | |||
54 | ** and all C libraries that have callbacks which may be used to call back | 56 | ** and all C libraries that have callbacks which may be used to call back |
55 | ** into Lua. C++ code must *not* be compiled with -fno-exceptions. | 57 | ** into Lua. C++ code must *not* be compiled with -fno-exceptions. |
56 | ** | 58 | ** |
57 | ** EXT cannot be enabled on WIN32 since system exceptions use code-driven SEH. | ||
58 | ** EXT is mandatory on WIN64 since the calling convention has an abundance | 59 | ** EXT is mandatory on WIN64 since the calling convention has an abundance |
59 | ** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). | 60 | ** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). |
60 | ** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). | 61 | ** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). |
@@ -62,7 +63,7 @@ | |||
62 | 63 | ||
63 | #if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND | 64 | #if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND |
64 | #define LJ_UNWIND_EXT 1 | 65 | #define LJ_UNWIND_EXT 1 |
65 | #elif LJ_TARGET_X64 && LJ_TARGET_WINDOWS | 66 | #elif LJ_TARGET_WINDOWS |
66 | #define LJ_UNWIND_EXT 1 | 67 | #define LJ_UNWIND_EXT 1 |
67 | #endif | 68 | #endif |
68 | 69 | ||
@@ -98,14 +99,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
98 | TValue *top = restorestack(L, -nres); | 99 | TValue *top = restorestack(L, -nres); |
99 | if (frame < top) { /* Frame reached? */ | 100 | if (frame < top) { /* Frame reached? */ |
100 | if (errcode) { | 101 | if (errcode) { |
101 | L->cframe = cframe_prev(cf); | ||
102 | L->base = frame+1; | 102 | L->base = frame+1; |
103 | L->cframe = cframe_prev(cf); | ||
103 | unwindstack(L, top); | 104 | unwindstack(L, top); |
104 | } | 105 | } |
105 | return cf; | 106 | return cf; |
106 | } | 107 | } |
107 | } | 108 | } |
108 | if (frame <= tvref(L->stack)) | 109 | if (frame <= tvref(L->stack)+LJ_FR2) |
109 | break; | 110 | break; |
110 | switch (frame_typep(frame)) { | 111 | switch (frame_typep(frame)) { |
111 | case FRAME_LUA: /* Lua frame. */ | 112 | case FRAME_LUA: /* Lua frame. */ |
@@ -113,14 +114,12 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
113 | frame = frame_prevl(frame); | 114 | frame = frame_prevl(frame); |
114 | break; | 115 | break; |
115 | case FRAME_C: /* C frame. */ | 116 | case FRAME_C: /* C frame. */ |
116 | #if LJ_HASFFI | ||
117 | unwind_c: | 117 | unwind_c: |
118 | #endif | ||
119 | #if LJ_UNWIND_EXT | 118 | #if LJ_UNWIND_EXT |
120 | if (errcode) { | 119 | if (errcode) { |
121 | L->cframe = cframe_prev(cf); | ||
122 | L->base = frame_prevd(frame) + 1; | 120 | L->base = frame_prevd(frame) + 1; |
123 | unwindstack(L, frame); | 121 | L->cframe = cframe_prev(cf); |
122 | unwindstack(L, frame - LJ_FR2); | ||
124 | } else if (cf != stopcf) { | 123 | } else if (cf != stopcf) { |
125 | cf = cframe_prev(cf); | 124 | cf = cframe_prev(cf); |
126 | frame = frame_prevd(frame); | 125 | frame = frame_prevd(frame); |
@@ -143,16 +142,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
143 | return cf; | 142 | return cf; |
144 | } | 143 | } |
145 | if (errcode) { | 144 | if (errcode) { |
146 | L->cframe = cframe_prev(cf); | ||
147 | L->base = frame_prevd(frame) + 1; | 145 | L->base = frame_prevd(frame) + 1; |
148 | unwindstack(L, frame); | 146 | L->cframe = cframe_prev(cf); |
147 | unwindstack(L, frame - LJ_FR2); | ||
149 | } | 148 | } |
150 | return cf; | 149 | return cf; |
151 | case FRAME_CONT: /* Continuation frame. */ | 150 | case FRAME_CONT: /* Continuation frame. */ |
152 | #if LJ_HASFFI | 151 | if (frame_iscont_fficb(frame)) |
153 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
154 | goto unwind_c; | 152 | goto unwind_c; |
155 | #endif | ||
156 | /* fallthrough */ | 153 | /* fallthrough */ |
157 | case FRAME_VARG: /* Vararg frame. */ | 154 | case FRAME_VARG: /* Vararg frame. */ |
158 | frame = frame_prevd(frame); | 155 | frame = frame_prevd(frame); |
@@ -166,8 +163,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
166 | } | 163 | } |
167 | if (frame_typep(frame) == FRAME_PCALL) | 164 | if (frame_typep(frame) == FRAME_PCALL) |
168 | hook_leave(G(L)); | 165 | hook_leave(G(L)); |
169 | L->cframe = cf; | ||
170 | L->base = frame_prevd(frame) + 1; | 166 | L->base = frame_prevd(frame) + 1; |
167 | L->cframe = cf; | ||
171 | unwindstack(L, L->base); | 168 | unwindstack(L, L->base); |
172 | } | 169 | } |
173 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); | 170 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); |
@@ -175,8 +172,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
175 | } | 172 | } |
176 | /* No C frame. */ | 173 | /* No C frame. */ |
177 | if (errcode) { | 174 | if (errcode) { |
175 | L->base = tvref(L->stack)+1+LJ_FR2; | ||
178 | L->cframe = NULL; | 176 | L->cframe = NULL; |
179 | L->base = tvref(L->stack)+1; | ||
180 | unwindstack(L, L->base); | 177 | unwindstack(L, L->base); |
181 | if (G(L)->panic) | 178 | if (G(L)->panic) |
182 | G(L)->panic(L); | 179 | G(L)->panic(L); |
@@ -194,13 +191,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
194 | ** since various OS, distros and compilers mess up the header installation. | 191 | ** since various OS, distros and compilers mess up the header installation. |
195 | */ | 192 | */ |
196 | 193 | ||
197 | typedef struct _Unwind_Exception | ||
198 | { | ||
199 | uint64_t exclass; | ||
200 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
201 | uintptr_t p1, p2; | ||
202 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
203 | |||
204 | typedef struct _Unwind_Context _Unwind_Context; | 194 | typedef struct _Unwind_Context _Unwind_Context; |
205 | 195 | ||
206 | #define _URC_OK 0 | 196 | #define _URC_OK 0 |
@@ -210,8 +200,20 @@ typedef struct _Unwind_Context _Unwind_Context; | |||
210 | #define _URC_CONTINUE_UNWIND 8 | 200 | #define _URC_CONTINUE_UNWIND 8 |
211 | #define _URC_FAILURE 9 | 201 | #define _URC_FAILURE 9 |
212 | 202 | ||
203 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
204 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
205 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
206 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
207 | |||
213 | #if !LJ_TARGET_ARM | 208 | #if !LJ_TARGET_ARM |
214 | 209 | ||
210 | typedef struct _Unwind_Exception | ||
211 | { | ||
212 | uint64_t exclass; | ||
213 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
214 | uintptr_t p1, p2; | ||
215 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
216 | |||
215 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 217 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
216 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 218 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
217 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 219 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
@@ -223,11 +225,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
223 | #define _UA_HANDLER_FRAME 4 | 225 | #define _UA_HANDLER_FRAME 4 |
224 | #define _UA_FORCE_UNWIND 8 | 226 | #define _UA_FORCE_UNWIND 8 |
225 | 227 | ||
226 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
227 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
228 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
229 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
230 | |||
231 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | 228 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
232 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 229 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
233 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 230 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
@@ -301,10 +298,22 @@ static void err_raise_ext(int errcode) | |||
301 | } | 298 | } |
302 | #endif | 299 | #endif |
303 | 300 | ||
304 | #else | 301 | #else /* LJ_TARGET_ARM */ |
305 | 302 | ||
306 | extern void _Unwind_DeleteException(void *); | 303 | #define _US_VIRTUAL_UNWIND_FRAME 0 |
307 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 304 | #define _US_UNWIND_FRAME_STARTING 1 |
305 | #define _US_ACTION_MASK 3 | ||
306 | #define _US_FORCE_UNWIND 8 | ||
307 | |||
308 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
309 | |||
310 | struct _Unwind_Control_Block { | ||
311 | uint64_t exclass; | ||
312 | uint32_t misc[20]; | ||
313 | }; | ||
314 | |||
315 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); | ||
316 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); | ||
308 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | 317 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); |
309 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); | 318 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); |
310 | 319 | ||
@@ -320,35 +329,58 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
320 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 329 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
321 | } | 330 | } |
322 | 331 | ||
323 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 332 | extern void lj_vm_unwind_ext(void); |
324 | #define _US_UNWIND_FRAME_STARTING 1 | ||
325 | #define _US_ACTION_MASK 3 | ||
326 | #define _US_FORCE_UNWIND 8 | ||
327 | 333 | ||
328 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 334 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
329 | LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | 335 | LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, |
336 | _Unwind_Context *ctx) | ||
330 | { | 337 | { |
331 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 338 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
332 | lua_State *L = cframe_L(cf); | 339 | lua_State *L = cframe_L(cf); |
333 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 340 | int errcode; |
334 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 341 | |
342 | switch ((state & _US_ACTION_MASK)) { | ||
343 | case _US_VIRTUAL_UNWIND_FRAME: | ||
344 | if ((state & _US_FORCE_UNWIND)) break; | ||
335 | return _URC_HANDLER_FOUND; | 345 | return _URC_HANDLER_FOUND; |
336 | } | 346 | case _US_UNWIND_FRAME_STARTING: |
337 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 347 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
338 | _Unwind_DeleteException(ucb); | 348 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
339 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 349 | } else { |
340 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 350 | errcode = LUA_ERRRUN; |
341 | _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); | 351 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
352 | } | ||
353 | cf = err_unwind(L, cf, errcode); | ||
354 | if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | ||
355 | _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | ||
356 | _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | ||
357 | _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | ||
358 | _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | ||
359 | (uint32_t)lj_vm_unwind_ff_eh : | ||
360 | (uint32_t)lj_vm_unwind_c_eh); | ||
342 | return _URC_INSTALL_CONTEXT; | 361 | return _URC_INSTALL_CONTEXT; |
362 | default: | ||
363 | return _URC_FAILURE; | ||
343 | } | 364 | } |
344 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 365 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
345 | return _URC_FAILURE; | 366 | return _URC_FAILURE; |
346 | return _URC_CONTINUE_UNWIND; | 367 | return _URC_CONTINUE_UNWIND; |
347 | } | 368 | } |
348 | 369 | ||
370 | #if LJ_UNWIND_EXT | ||
371 | static __thread _Unwind_Control_Block static_uex; | ||
372 | |||
373 | static void err_raise_ext(int errcode) | ||
374 | { | ||
375 | memset(&static_uex, 0, sizeof(static_uex)); | ||
376 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | ||
377 | _Unwind_RaiseException(&static_uex); | ||
378 | } | ||
349 | #endif | 379 | #endif |
350 | 380 | ||
351 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 381 | #endif /* LJ_TARGET_ARM */ |
382 | |||
383 | #elif LJ_ABI_WIN | ||
352 | 384 | ||
353 | /* | 385 | /* |
354 | ** Someone in Redmond owes me several days of my life. A lot of this is | 386 | ** Someone in Redmond owes me several days of my life. A lot of this is |
@@ -366,6 +398,7 @@ LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | |||
366 | #define WIN32_LEAN_AND_MEAN | 398 | #define WIN32_LEAN_AND_MEAN |
367 | #include <windows.h> | 399 | #include <windows.h> |
368 | 400 | ||
401 | #if LJ_TARGET_X64 | ||
369 | /* Taken from: http://www.nynaeve.net/?p=99 */ | 402 | /* Taken from: http://www.nynaeve.net/?p=99 */ |
370 | typedef struct UndocumentedDispatcherContext { | 403 | typedef struct UndocumentedDispatcherContext { |
371 | ULONG64 ControlPc; | 404 | ULONG64 ControlPc; |
@@ -380,11 +413,14 @@ typedef struct UndocumentedDispatcherContext { | |||
380 | ULONG ScopeIndex; | 413 | ULONG ScopeIndex; |
381 | ULONG Fill0; | 414 | ULONG Fill0; |
382 | } UndocumentedDispatcherContext; | 415 | } UndocumentedDispatcherContext; |
416 | #else | ||
417 | typedef void *UndocumentedDispatcherContext; | ||
418 | #endif | ||
383 | 419 | ||
384 | /* Another wild guess. */ | 420 | /* Another wild guess. */ |
385 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); | 421 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); |
386 | 422 | ||
387 | #ifdef MINGW_SDK_INIT | 423 | #if LJ_TARGET_X64 && defined(MINGW_SDK_INIT) |
388 | /* Workaround for broken MinGW64 declaration. */ | 424 | /* Workaround for broken MinGW64 declaration. */ |
389 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | 425 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); |
390 | #define RtlUnwindEx RtlUnwindEx_FIXED | 426 | #define RtlUnwindEx RtlUnwindEx_FIXED |
@@ -398,10 +434,15 @@ VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | |||
398 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | 434 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) |
399 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | 435 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) |
400 | 436 | ||
401 | /* Win64 exception handler for interpreter frame. */ | 437 | /* Windows exception handler for interpreter frame. */ |
402 | LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | 438 | LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, |
403 | void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | 439 | void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) |
404 | { | 440 | { |
441 | #if LJ_TARGET_X64 | ||
442 | void *cf = f; | ||
443 | #else | ||
444 | void *cf = (char *)f - CFRAME_OFS_SEH; | ||
445 | #endif | ||
405 | lua_State *L = cframe_L(cf); | 446 | lua_State *L = cframe_L(cf); |
406 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | 447 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? |
407 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | 448 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; |
@@ -419,8 +460,9 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | |||
419 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 460 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
420 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | 461 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { |
421 | /* Don't catch access violations etc. */ | 462 | /* Don't catch access violations etc. */ |
422 | return ExceptionContinueSearch; | 463 | return 1; /* ExceptionContinueSearch */ |
423 | } | 464 | } |
465 | #if LJ_TARGET_X64 | ||
424 | /* Unwind the stack and call all handlers for all lower C frames | 466 | /* Unwind the stack and call all handlers for all lower C frames |
425 | ** (including ourselves) again with EH_UNWINDING set. Then set | 467 | ** (including ourselves) again with EH_UNWINDING set. Then set |
426 | ** rsp = cf, rax = errcode and jump to the specified target. | 468 | ** rsp = cf, rax = errcode and jump to the specified target. |
@@ -430,9 +472,21 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | |||
430 | lj_vm_unwind_c_eh), | 472 | lj_vm_unwind_c_eh), |
431 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | 473 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); |
432 | /* RtlUnwindEx should never return. */ | 474 | /* RtlUnwindEx should never return. */ |
475 | #else | ||
476 | UNUSED(ctx); | ||
477 | UNUSED(dispatch); | ||
478 | /* Call all handlers for all lower C frames (including ourselves) again | ||
479 | ** with EH_UNWINDING set. Then call the specified function, passing cf | ||
480 | ** and errcode. | ||
481 | */ | ||
482 | lj_vm_rtlunwind(cf, (void *)rec, | ||
483 | (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
484 | (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); | ||
485 | /* lj_vm_rtlunwind does not return. */ | ||
486 | #endif | ||
433 | } | 487 | } |
434 | } | 488 | } |
435 | return ExceptionContinueSearch; | 489 | return 1; /* ExceptionContinueSearch */ |
436 | } | 490 | } |
437 | 491 | ||
438 | /* Raise Windows exception. */ | 492 | /* Raise Windows exception. */ |
@@ -450,8 +504,8 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) | |||
450 | { | 504 | { |
451 | global_State *g = G(L); | 505 | global_State *g = G(L); |
452 | lj_trace_abort(g); | 506 | lj_trace_abort(g); |
453 | setgcrefnull(g->jit_L); | 507 | setmref(g->jit_base, NULL); |
454 | L->status = 0; | 508 | L->status = LUA_OK; |
455 | #if LJ_UNWIND_EXT | 509 | #if LJ_UNWIND_EXT |
456 | err_raise_ext(errcode); | 510 | err_raise_ext(errcode); |
457 | /* | 511 | /* |
@@ -495,7 +549,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) | |||
495 | /* Find error function for runtime errors. Requires an extra stack traversal. */ | 549 | /* Find error function for runtime errors. Requires an extra stack traversal. */ |
496 | static ptrdiff_t finderrfunc(lua_State *L) | 550 | static ptrdiff_t finderrfunc(lua_State *L) |
497 | { | 551 | { |
498 | cTValue *frame = L->base-1, *bot = tvref(L->stack); | 552 | cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; |
499 | void *cf = L->cframe; | 553 | void *cf = L->cframe; |
500 | while (frame > bot && cf) { | 554 | while (frame > bot && cf) { |
501 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | 555 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ |
@@ -519,10 +573,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
519 | frame = frame_prevd(frame); | 573 | frame = frame_prevd(frame); |
520 | break; | 574 | break; |
521 | case FRAME_CONT: | 575 | case FRAME_CONT: |
522 | #if LJ_HASFFI | 576 | if (frame_iscont_fficb(frame)) |
523 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
524 | cf = cframe_prev(cf); | 577 | cf = cframe_prev(cf); |
525 | #endif | ||
526 | frame = frame_prevd(frame); | 578 | frame = frame_prevd(frame); |
527 | break; | 579 | break; |
528 | case FRAME_CP: | 580 | case FRAME_CP: |
@@ -533,8 +585,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
533 | break; | 585 | break; |
534 | case FRAME_PCALL: | 586 | case FRAME_PCALL: |
535 | case FRAME_PCALLH: | 587 | case FRAME_PCALLH: |
536 | if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ | 588 | if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) |
537 | return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ | 589 | return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ |
538 | return 0; | 590 | return 0; |
539 | default: | 591 | default: |
540 | lua_assert(0); | 592 | lua_assert(0); |
@@ -557,8 +609,9 @@ LJ_NOINLINE void lj_err_run(lua_State *L) | |||
557 | lj_err_throw(L, LUA_ERRERR); | 609 | lj_err_throw(L, LUA_ERRERR); |
558 | } | 610 | } |
559 | L->status = LUA_ERRERR; | 611 | L->status = LUA_ERRERR; |
560 | copyTV(L, top, top-1); | 612 | copyTV(L, top+LJ_FR2, top-1); |
561 | copyTV(L, top-1, errfunc); | 613 | copyTV(L, top-1, errfunc); |
614 | if (LJ_FR2) setnilV(top++); | ||
562 | L->top = top+1; | 615 | L->top = top+1; |
563 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ | 616 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ |
564 | } | 617 | } |
@@ -572,7 +625,7 @@ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | |||
572 | va_list argp; | 625 | va_list argp; |
573 | va_start(argp, em); | 626 | va_start(argp, em); |
574 | if (curr_funcisL(L)) L->top = curr_topL(L); | 627 | if (curr_funcisL(L)) L->top = curr_topL(L); |
575 | msg = lj_str_pushvf(L, err2msg(em), argp); | 628 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
576 | va_end(argp); | 629 | va_end(argp); |
577 | lj_debug_addloc(L, msg, L->base-1, NULL); | 630 | lj_debug_addloc(L, msg, L->base-1, NULL); |
578 | lj_err_run(L); | 631 | lj_err_run(L); |
@@ -590,11 +643,11 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |||
590 | { | 643 | { |
591 | char buff[LUA_IDSIZE]; | 644 | char buff[LUA_IDSIZE]; |
592 | const char *msg; | 645 | const char *msg; |
593 | lj_debug_shortname(buff, src); | 646 | lj_debug_shortname(buff, src, line); |
594 | msg = lj_str_pushvf(L, err2msg(em), argp); | 647 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
595 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); | 648 | msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg); |
596 | if (tok) | 649 | if (tok) |
597 | lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); | 650 | lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); |
598 | lj_err_throw(L, LUA_ERRSYNTAX); | 651 | lj_err_throw(L, LUA_ERRSYNTAX); |
599 | } | 652 | } |
600 | 653 | ||
@@ -633,8 +686,9 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
633 | const BCIns *pc = cframe_Lpc(L); | 686 | const BCIns *pc = cframe_Lpc(L); |
634 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { | 687 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { |
635 | const char *tname = lj_typename(o); | 688 | const char *tname = lj_typename(o); |
689 | if (LJ_FR2) o++; | ||
636 | setframe_pc(o, pc); | 690 | setframe_pc(o, pc); |
637 | setframe_gc(o, obj2gco(L)); | 691 | setframe_gc(o, obj2gco(L), LJ_TTHREAD); |
638 | L->top = L->base = o+1; | 692 | L->top = L->base = o+1; |
639 | err_msgv(L, LJ_ERR_BADCALL, tname); | 693 | err_msgv(L, LJ_ERR_BADCALL, tname); |
640 | } | 694 | } |
@@ -649,13 +703,10 @@ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | |||
649 | if (frame_islua(frame)) { | 703 | if (frame_islua(frame)) { |
650 | pframe = frame_prevl(frame); | 704 | pframe = frame_prevl(frame); |
651 | } else if (frame_iscont(frame)) { | 705 | } else if (frame_iscont(frame)) { |
652 | #if LJ_HASFFI | 706 | if (frame_iscont_fficb(frame)) { |
653 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) { | ||
654 | pframe = frame; | 707 | pframe = frame; |
655 | frame = NULL; | 708 | frame = NULL; |
656 | } else | 709 | } else { |
657 | #endif | ||
658 | { | ||
659 | pframe = frame_prevd(frame); | 710 | pframe = frame_prevd(frame); |
660 | #if LJ_HASFFI | 711 | #if LJ_HASFFI |
661 | /* Remove frame for FFI metamethods. */ | 712 | /* Remove frame for FFI metamethods. */ |
@@ -678,7 +729,7 @@ LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...) | |||
678 | const char *msg; | 729 | const char *msg; |
679 | va_list argp; | 730 | va_list argp; |
680 | va_start(argp, em); | 731 | va_start(argp, em); |
681 | msg = lj_str_pushvf(L, err2msg(em), argp); | 732 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
682 | va_end(argp); | 733 | va_end(argp); |
683 | lj_err_callermsg(L, msg); | 734 | lj_err_callermsg(L, msg); |
684 | } | 735 | } |
@@ -698,9 +749,9 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg, | |||
698 | if (narg < 0 && narg > LUA_REGISTRYINDEX) | 749 | if (narg < 0 && narg > LUA_REGISTRYINDEX) |
699 | narg = (int)(L->top - L->base) + narg + 1; | 750 | narg = (int)(L->top - L->base) + narg + 1; |
700 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ | 751 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ |
701 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); | 752 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); |
702 | else | 753 | else |
703 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); | 754 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); |
704 | lj_err_callermsg(L, msg); | 755 | lj_err_callermsg(L, msg); |
705 | } | 756 | } |
706 | 757 | ||
@@ -710,7 +761,7 @@ LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...) | |||
710 | const char *msg; | 761 | const char *msg; |
711 | va_list argp; | 762 | va_list argp; |
712 | va_start(argp, em); | 763 | va_start(argp, em); |
713 | msg = lj_str_pushvf(L, err2msg(em), argp); | 764 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
714 | va_end(argp); | 765 | va_end(argp); |
715 | err_argmsg(L, narg, msg); | 766 | err_argmsg(L, narg, msg); |
716 | } | 767 | } |
@@ -740,7 +791,7 @@ LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname) | |||
740 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; | 791 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; |
741 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; | 792 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; |
742 | } | 793 | } |
743 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); | 794 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); |
744 | err_argmsg(L, narg, msg); | 795 | err_argmsg(L, narg, msg); |
745 | } | 796 | } |
746 | 797 | ||
@@ -790,7 +841,7 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |||
790 | const char *msg; | 841 | const char *msg; |
791 | va_list argp; | 842 | va_list argp; |
792 | va_start(argp, fmt); | 843 | va_start(argp, fmt); |
793 | msg = lj_str_pushvf(L, fmt, argp); | 844 | msg = lj_strfmt_pushvf(L, fmt, argp); |
794 | va_end(argp); | 845 | va_end(argp); |
795 | lj_err_callermsg(L, msg); | 846 | lj_err_callermsg(L, msg); |
796 | return 0; /* unreachable */ | 847 | return 0; /* unreachable */ |