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 54f42c37..b6be357e 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 | case FRAME_VARG: /* Vararg frame. */ | 153 | case FRAME_VARG: /* Vararg frame. */ |
157 | frame = frame_prevd(frame); | 154 | frame = frame_prevd(frame); |
158 | break; | 155 | break; |
@@ -165,8 +162,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
165 | } | 162 | } |
166 | if (frame_typep(frame) == FRAME_PCALL) | 163 | if (frame_typep(frame) == FRAME_PCALL) |
167 | hook_leave(G(L)); | 164 | hook_leave(G(L)); |
168 | L->cframe = cf; | ||
169 | L->base = frame_prevd(frame) + 1; | 165 | L->base = frame_prevd(frame) + 1; |
166 | L->cframe = cf; | ||
170 | unwindstack(L, L->base); | 167 | unwindstack(L, L->base); |
171 | } | 168 | } |
172 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); | 169 | return (void *)((intptr_t)cf | CFRAME_UNWIND_FF); |
@@ -174,8 +171,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
174 | } | 171 | } |
175 | /* No C frame. */ | 172 | /* No C frame. */ |
176 | if (errcode) { | 173 | if (errcode) { |
174 | L->base = tvref(L->stack)+1+LJ_FR2; | ||
177 | L->cframe = NULL; | 175 | L->cframe = NULL; |
178 | L->base = tvref(L->stack)+1; | ||
179 | unwindstack(L, L->base); | 176 | unwindstack(L, L->base); |
180 | if (G(L)->panic) | 177 | if (G(L)->panic) |
181 | G(L)->panic(L); | 178 | G(L)->panic(L); |
@@ -193,13 +190,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
193 | ** since various OS, distros and compilers mess up the header installation. | 190 | ** since various OS, distros and compilers mess up the header installation. |
194 | */ | 191 | */ |
195 | 192 | ||
196 | typedef struct _Unwind_Exception | ||
197 | { | ||
198 | uint64_t exclass; | ||
199 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
200 | uintptr_t p1, p2; | ||
201 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
202 | |||
203 | typedef struct _Unwind_Context _Unwind_Context; | 193 | typedef struct _Unwind_Context _Unwind_Context; |
204 | 194 | ||
205 | #define _URC_OK 0 | 195 | #define _URC_OK 0 |
@@ -209,8 +199,20 @@ typedef struct _Unwind_Context _Unwind_Context; | |||
209 | #define _URC_CONTINUE_UNWIND 8 | 199 | #define _URC_CONTINUE_UNWIND 8 |
210 | #define _URC_FAILURE 9 | 200 | #define _URC_FAILURE 9 |
211 | 201 | ||
202 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
203 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
204 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
205 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
206 | |||
212 | #if !LJ_TARGET_ARM | 207 | #if !LJ_TARGET_ARM |
213 | 208 | ||
209 | typedef struct _Unwind_Exception | ||
210 | { | ||
211 | uint64_t exclass; | ||
212 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
213 | uintptr_t p1, p2; | ||
214 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
215 | |||
214 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 216 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
215 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 217 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
216 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 218 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
@@ -222,11 +224,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
222 | #define _UA_HANDLER_FRAME 4 | 224 | #define _UA_HANDLER_FRAME 4 |
223 | #define _UA_FORCE_UNWIND 8 | 225 | #define _UA_FORCE_UNWIND 8 |
224 | 226 | ||
225 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
226 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
227 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
228 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
229 | |||
230 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | 227 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
231 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 228 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
232 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 229 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
@@ -305,10 +302,22 @@ static void err_raise_ext(int errcode) | |||
305 | } | 302 | } |
306 | #endif | 303 | #endif |
307 | 304 | ||
308 | #else | 305 | #else /* LJ_TARGET_ARM */ |
309 | 306 | ||
310 | extern void _Unwind_DeleteException(void *); | 307 | #define _US_VIRTUAL_UNWIND_FRAME 0 |
311 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 308 | #define _US_UNWIND_FRAME_STARTING 1 |
309 | #define _US_ACTION_MASK 3 | ||
310 | #define _US_FORCE_UNWIND 8 | ||
311 | |||
312 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
313 | |||
314 | struct _Unwind_Control_Block { | ||
315 | uint64_t exclass; | ||
316 | uint32_t misc[20]; | ||
317 | }; | ||
318 | |||
319 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); | ||
320 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); | ||
312 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | 321 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); |
313 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); | 322 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); |
314 | 323 | ||
@@ -324,35 +333,58 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
324 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 333 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
325 | } | 334 | } |
326 | 335 | ||
327 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 336 | extern void lj_vm_unwind_ext(void); |
328 | #define _US_UNWIND_FRAME_STARTING 1 | ||
329 | #define _US_ACTION_MASK 3 | ||
330 | #define _US_FORCE_UNWIND 8 | ||
331 | 337 | ||
332 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 338 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
333 | LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | 339 | LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, |
340 | _Unwind_Context *ctx) | ||
334 | { | 341 | { |
335 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 342 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
336 | lua_State *L = cframe_L(cf); | 343 | lua_State *L = cframe_L(cf); |
337 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 344 | int errcode; |
338 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 345 | |
346 | switch ((state & _US_ACTION_MASK)) { | ||
347 | case _US_VIRTUAL_UNWIND_FRAME: | ||
348 | if ((state & _US_FORCE_UNWIND)) break; | ||
339 | return _URC_HANDLER_FOUND; | 349 | return _URC_HANDLER_FOUND; |
340 | } | 350 | case _US_UNWIND_FRAME_STARTING: |
341 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 351 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
342 | _Unwind_DeleteException(ucb); | 352 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
343 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 353 | } else { |
344 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 354 | errcode = LUA_ERRRUN; |
345 | _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); | 355 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
356 | } | ||
357 | cf = err_unwind(L, cf, errcode); | ||
358 | if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | ||
359 | _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | ||
360 | _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | ||
361 | _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | ||
362 | _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | ||
363 | (uint32_t)lj_vm_unwind_ff_eh : | ||
364 | (uint32_t)lj_vm_unwind_c_eh); | ||
346 | return _URC_INSTALL_CONTEXT; | 365 | return _URC_INSTALL_CONTEXT; |
366 | default: | ||
367 | return _URC_FAILURE; | ||
347 | } | 368 | } |
348 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 369 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
349 | return _URC_FAILURE; | 370 | return _URC_FAILURE; |
350 | return _URC_CONTINUE_UNWIND; | 371 | return _URC_CONTINUE_UNWIND; |
351 | } | 372 | } |
352 | 373 | ||
374 | #if LJ_UNWIND_EXT | ||
375 | static __thread _Unwind_Control_Block static_uex; | ||
376 | |||
377 | static void err_raise_ext(int errcode) | ||
378 | { | ||
379 | memset(&static_uex, 0, sizeof(static_uex)); | ||
380 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | ||
381 | _Unwind_RaiseException(&static_uex); | ||
382 | } | ||
353 | #endif | 383 | #endif |
354 | 384 | ||
355 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 385 | #endif /* LJ_TARGET_ARM */ |
386 | |||
387 | #elif LJ_ABI_WIN | ||
356 | 388 | ||
357 | /* | 389 | /* |
358 | ** Someone in Redmond owes me several days of my life. A lot of this is | 390 | ** Someone in Redmond owes me several days of my life. A lot of this is |
@@ -370,6 +402,7 @@ LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | |||
370 | #define WIN32_LEAN_AND_MEAN | 402 | #define WIN32_LEAN_AND_MEAN |
371 | #include <windows.h> | 403 | #include <windows.h> |
372 | 404 | ||
405 | #if LJ_TARGET_X64 | ||
373 | /* Taken from: http://www.nynaeve.net/?p=99 */ | 406 | /* Taken from: http://www.nynaeve.net/?p=99 */ |
374 | typedef struct UndocumentedDispatcherContext { | 407 | typedef struct UndocumentedDispatcherContext { |
375 | ULONG64 ControlPc; | 408 | ULONG64 ControlPc; |
@@ -384,11 +417,14 @@ typedef struct UndocumentedDispatcherContext { | |||
384 | ULONG ScopeIndex; | 417 | ULONG ScopeIndex; |
385 | ULONG Fill0; | 418 | ULONG Fill0; |
386 | } UndocumentedDispatcherContext; | 419 | } UndocumentedDispatcherContext; |
420 | #else | ||
421 | typedef void *UndocumentedDispatcherContext; | ||
422 | #endif | ||
387 | 423 | ||
388 | /* Another wild guess. */ | 424 | /* Another wild guess. */ |
389 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); | 425 | extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); |
390 | 426 | ||
391 | #ifdef MINGW_SDK_INIT | 427 | #if LJ_TARGET_X64 && defined(MINGW_SDK_INIT) |
392 | /* Workaround for broken MinGW64 declaration. */ | 428 | /* Workaround for broken MinGW64 declaration. */ |
393 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | 429 | VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); |
394 | #define RtlUnwindEx RtlUnwindEx_FIXED | 430 | #define RtlUnwindEx RtlUnwindEx_FIXED |
@@ -402,10 +438,15 @@ VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); | |||
402 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) | 438 | #define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) |
403 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) | 439 | #define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) |
404 | 440 | ||
405 | /* Win64 exception handler for interpreter frame. */ | 441 | /* Windows exception handler for interpreter frame. */ |
406 | LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | 442 | LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, |
407 | void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) | 443 | void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) |
408 | { | 444 | { |
445 | #if LJ_TARGET_X64 | ||
446 | void *cf = f; | ||
447 | #else | ||
448 | void *cf = (char *)f - CFRAME_OFS_SEH; | ||
449 | #endif | ||
409 | lua_State *L = cframe_L(cf); | 450 | lua_State *L = cframe_L(cf); |
410 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? | 451 | int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? |
411 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; | 452 | LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; |
@@ -423,8 +464,9 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | |||
423 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 464 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
424 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { | 465 | } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { |
425 | /* Don't catch access violations etc. */ | 466 | /* Don't catch access violations etc. */ |
426 | return ExceptionContinueSearch; | 467 | return 1; /* ExceptionContinueSearch */ |
427 | } | 468 | } |
469 | #if LJ_TARGET_X64 | ||
428 | /* Unwind the stack and call all handlers for all lower C frames | 470 | /* Unwind the stack and call all handlers for all lower C frames |
429 | ** (including ourselves) again with EH_UNWINDING set. Then set | 471 | ** (including ourselves) again with EH_UNWINDING set. Then set |
430 | ** rsp = cf, rax = errcode and jump to the specified target. | 472 | ** rsp = cf, rax = errcode and jump to the specified target. |
@@ -434,9 +476,21 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, | |||
434 | lj_vm_unwind_c_eh), | 476 | lj_vm_unwind_c_eh), |
435 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); | 477 | rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); |
436 | /* RtlUnwindEx should never return. */ | 478 | /* RtlUnwindEx should never return. */ |
479 | #else | ||
480 | UNUSED(ctx); | ||
481 | UNUSED(dispatch); | ||
482 | /* Call all handlers for all lower C frames (including ourselves) again | ||
483 | ** with EH_UNWINDING set. Then call the specified function, passing cf | ||
484 | ** and errcode. | ||
485 | */ | ||
486 | lj_vm_rtlunwind(cf, (void *)rec, | ||
487 | (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? | ||
488 | (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); | ||
489 | /* lj_vm_rtlunwind does not return. */ | ||
490 | #endif | ||
437 | } | 491 | } |
438 | } | 492 | } |
439 | return ExceptionContinueSearch; | 493 | return 1; /* ExceptionContinueSearch */ |
440 | } | 494 | } |
441 | 495 | ||
442 | /* Raise Windows exception. */ | 496 | /* Raise Windows exception. */ |
@@ -454,8 +508,8 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) | |||
454 | { | 508 | { |
455 | global_State *g = G(L); | 509 | global_State *g = G(L); |
456 | lj_trace_abort(g); | 510 | lj_trace_abort(g); |
457 | setgcrefnull(g->jit_L); | 511 | setmref(g->jit_base, NULL); |
458 | L->status = 0; | 512 | L->status = LUA_OK; |
459 | #if LJ_UNWIND_EXT | 513 | #if LJ_UNWIND_EXT |
460 | err_raise_ext(errcode); | 514 | err_raise_ext(errcode); |
461 | /* | 515 | /* |
@@ -499,7 +553,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) | |||
499 | /* Find error function for runtime errors. Requires an extra stack traversal. */ | 553 | /* Find error function for runtime errors. Requires an extra stack traversal. */ |
500 | static ptrdiff_t finderrfunc(lua_State *L) | 554 | static ptrdiff_t finderrfunc(lua_State *L) |
501 | { | 555 | { |
502 | cTValue *frame = L->base-1, *bot = tvref(L->stack); | 556 | cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; |
503 | void *cf = L->cframe; | 557 | void *cf = L->cframe; |
504 | while (frame > bot && cf) { | 558 | while (frame > bot && cf) { |
505 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ | 559 | while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ |
@@ -523,10 +577,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
523 | frame = frame_prevd(frame); | 577 | frame = frame_prevd(frame); |
524 | break; | 578 | break; |
525 | case FRAME_CONT: | 579 | case FRAME_CONT: |
526 | #if LJ_HASFFI | 580 | if (frame_iscont_fficb(frame)) |
527 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) | ||
528 | cf = cframe_prev(cf); | 581 | cf = cframe_prev(cf); |
529 | #endif | ||
530 | frame = frame_prevd(frame); | 582 | frame = frame_prevd(frame); |
531 | break; | 583 | break; |
532 | case FRAME_CP: | 584 | case FRAME_CP: |
@@ -537,8 +589,8 @@ static ptrdiff_t finderrfunc(lua_State *L) | |||
537 | break; | 589 | break; |
538 | case FRAME_PCALL: | 590 | case FRAME_PCALL: |
539 | case FRAME_PCALLH: | 591 | case FRAME_PCALLH: |
540 | if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ | 592 | if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) |
541 | return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ | 593 | return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ |
542 | return 0; | 594 | return 0; |
543 | default: | 595 | default: |
544 | lua_assert(0); | 596 | lua_assert(0); |
@@ -561,8 +613,9 @@ LJ_NOINLINE void lj_err_run(lua_State *L) | |||
561 | lj_err_throw(L, LUA_ERRERR); | 613 | lj_err_throw(L, LUA_ERRERR); |
562 | } | 614 | } |
563 | L->status = LUA_ERRERR; | 615 | L->status = LUA_ERRERR; |
564 | copyTV(L, top, top-1); | 616 | copyTV(L, top+LJ_FR2, top-1); |
565 | copyTV(L, top-1, errfunc); | 617 | copyTV(L, top-1, errfunc); |
618 | if (LJ_FR2) setnilV(top++); | ||
566 | L->top = top+1; | 619 | L->top = top+1; |
567 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ | 620 | lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ |
568 | } | 621 | } |
@@ -576,7 +629,7 @@ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) | |||
576 | va_list argp; | 629 | va_list argp; |
577 | va_start(argp, em); | 630 | va_start(argp, em); |
578 | if (curr_funcisL(L)) L->top = curr_topL(L); | 631 | if (curr_funcisL(L)) L->top = curr_topL(L); |
579 | msg = lj_str_pushvf(L, err2msg(em), argp); | 632 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
580 | va_end(argp); | 633 | va_end(argp); |
581 | lj_debug_addloc(L, msg, L->base-1, NULL); | 634 | lj_debug_addloc(L, msg, L->base-1, NULL); |
582 | lj_err_run(L); | 635 | lj_err_run(L); |
@@ -594,11 +647,11 @@ LJ_NOINLINE void lj_err_lex(lua_State *L, GCstr *src, const char *tok, | |||
594 | { | 647 | { |
595 | char buff[LUA_IDSIZE]; | 648 | char buff[LUA_IDSIZE]; |
596 | const char *msg; | 649 | const char *msg; |
597 | lj_debug_shortname(buff, src); | 650 | lj_debug_shortname(buff, src, line); |
598 | msg = lj_str_pushvf(L, err2msg(em), argp); | 651 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
599 | msg = lj_str_pushf(L, "%s:%d: %s", buff, line, msg); | 652 | msg = lj_strfmt_pushf(L, "%s:%d: %s", buff, line, msg); |
600 | if (tok) | 653 | if (tok) |
601 | lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); | 654 | lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tok); |
602 | lj_err_throw(L, LUA_ERRSYNTAX); | 655 | lj_err_throw(L, LUA_ERRSYNTAX); |
603 | } | 656 | } |
604 | 657 | ||
@@ -637,8 +690,9 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
637 | const BCIns *pc = cframe_Lpc(L); | 690 | const BCIns *pc = cframe_Lpc(L); |
638 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { | 691 | if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { |
639 | const char *tname = lj_typename(o); | 692 | const char *tname = lj_typename(o); |
693 | if (LJ_FR2) o++; | ||
640 | setframe_pc(o, pc); | 694 | setframe_pc(o, pc); |
641 | setframe_gc(o, obj2gco(L)); | 695 | setframe_gc(o, obj2gco(L), LJ_TTHREAD); |
642 | L->top = L->base = o+1; | 696 | L->top = L->base = o+1; |
643 | err_msgv(L, LJ_ERR_BADCALL, tname); | 697 | err_msgv(L, LJ_ERR_BADCALL, tname); |
644 | } | 698 | } |
@@ -653,13 +707,10 @@ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | |||
653 | if (frame_islua(frame)) { | 707 | if (frame_islua(frame)) { |
654 | pframe = frame_prevl(frame); | 708 | pframe = frame_prevl(frame); |
655 | } else if (frame_iscont(frame)) { | 709 | } else if (frame_iscont(frame)) { |
656 | #if LJ_HASFFI | 710 | if (frame_iscont_fficb(frame)) { |
657 | if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK) { | ||
658 | pframe = frame; | 711 | pframe = frame; |
659 | frame = NULL; | 712 | frame = NULL; |
660 | } else | 713 | } else { |
661 | #endif | ||
662 | { | ||
663 | pframe = frame_prevd(frame); | 714 | pframe = frame_prevd(frame); |
664 | #if LJ_HASFFI | 715 | #if LJ_HASFFI |
665 | /* Remove frame for FFI metamethods. */ | 716 | /* Remove frame for FFI metamethods. */ |
@@ -682,7 +733,7 @@ LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...) | |||
682 | const char *msg; | 733 | const char *msg; |
683 | va_list argp; | 734 | va_list argp; |
684 | va_start(argp, em); | 735 | va_start(argp, em); |
685 | msg = lj_str_pushvf(L, err2msg(em), argp); | 736 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
686 | va_end(argp); | 737 | va_end(argp); |
687 | lj_err_callermsg(L, msg); | 738 | lj_err_callermsg(L, msg); |
688 | } | 739 | } |
@@ -702,9 +753,9 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg, | |||
702 | if (narg < 0 && narg > LUA_REGISTRYINDEX) | 753 | if (narg < 0 && narg > LUA_REGISTRYINDEX) |
703 | narg = (int)(L->top - L->base) + narg + 1; | 754 | narg = (int)(L->top - L->base) + narg + 1; |
704 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ | 755 | if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */ |
705 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); | 756 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg); |
706 | else | 757 | else |
707 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); | 758 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADARG), narg, fname, msg); |
708 | lj_err_callermsg(L, msg); | 759 | lj_err_callermsg(L, msg); |
709 | } | 760 | } |
710 | 761 | ||
@@ -714,7 +765,7 @@ LJ_NOINLINE void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...) | |||
714 | const char *msg; | 765 | const char *msg; |
715 | va_list argp; | 766 | va_list argp; |
716 | va_start(argp, em); | 767 | va_start(argp, em); |
717 | msg = lj_str_pushvf(L, err2msg(em), argp); | 768 | msg = lj_strfmt_pushvf(L, err2msg(em), argp); |
718 | va_end(argp); | 769 | va_end(argp); |
719 | err_argmsg(L, narg, msg); | 770 | err_argmsg(L, narg, msg); |
720 | } | 771 | } |
@@ -744,7 +795,7 @@ LJ_NOINLINE void lj_err_argtype(lua_State *L, int narg, const char *xname) | |||
744 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; | 795 | TValue *o = narg < 0 ? L->top + narg : L->base + narg-1; |
745 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; | 796 | tname = o < L->top ? lj_typename(o) : lj_obj_typename[0]; |
746 | } | 797 | } |
747 | msg = lj_str_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); | 798 | msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_BADTYPE), xname, tname); |
748 | err_argmsg(L, narg, msg); | 799 | err_argmsg(L, narg, msg); |
749 | } | 800 | } |
750 | 801 | ||
@@ -794,7 +845,7 @@ LUALIB_API int luaL_error(lua_State *L, const char *fmt, ...) | |||
794 | const char *msg; | 845 | const char *msg; |
795 | va_list argp; | 846 | va_list argp; |
796 | va_start(argp, fmt); | 847 | va_start(argp, fmt); |
797 | msg = lj_str_pushvf(L, fmt, argp); | 848 | msg = lj_strfmt_pushvf(L, fmt, argp); |
798 | va_end(argp); | 849 | va_end(argp); |
799 | lj_err_callermsg(L, msg); | 850 | lj_err_callermsg(L, msg); |
800 | return 0; /* unreachable */ | 851 | return 0; /* unreachable */ |