<html><head><meta http-equiv="content-type" content="text/html; charset=us-ascii"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">Hi!<div><br></div><div>Thanks for the patch, LGTM as part of original <span style="color: rgba(0, 0, 0, 0.85); font-family: "Helvetica Neue"; font-size: 12px;">[PATCH luajit 1/6] Cleanup and enable external unwinding for more platforms.</span></div><div><font face="Helvetica Neue"><span style="caret-color: rgba(0, 0, 0, 0.85); color: rgba(0, 0, 0, 0.85); font-size: 12px;"><br></span></font></div><div><font face="Helvetica Neue"><span style="caret-color: rgba(0, 0, 0, 0.85); color: rgba(0, 0, 0, 0.85); font-size: 12px;">Sergos.<br></span></font><div><div><br><blockquote type="cite"><div>On 28 Oct 2022, at 12:26, Maksim Kokryashkin <max.kokryashkin@gmail.com> wrote:</div><br class="Apple-interchange-newline"><div><div>(cherry picked from commit e131936133c58de4426c595db2341caf5a1665b5)<br><br>This commit enables external unwinding on all platforms, that<br>create unwind tables by default. Corresponding check is added<br>to the build routine.<br><br>Also, GC64 mode is now enabled on MacOS by default, as<br>non-GC64 mode is forbidden.<br><br>Maxim Kokryashkin:<br>* added the description for the patch<br><br>Needed for tarantool/tarantool#6096<br>Part of tarantool/tarantool#7230<br>---<br> .github/workflows/macos-x86_64.yml |  20 +-<br> CMakeLists.txt                     |   3 +<br> cmake/SetTargetFlags.cmake         |  22 +-<br> doc/extensions.html                |  22 +-<br> src/Makefile.original              |  11 +-<br> src/lj_arch.h                      |  27 ++-<br> src/lj_err.c                       | 321 +++++++++++++++--------------<br> 7 files changed, 214 insertions(+), 212 deletions(-)<br><br>diff --git a/.github/workflows/macos-x86_64.yml b/.github/workflows/macos-x86_64.yml<br>index 840806e3..dafd1796 100644<br>--- a/.github/workflows/macos-x86_64.yml<br>+++ b/.github/workflows/macos-x86_64.yml<br>@@ -35,7 +35,7 @@ jobs:<br>       fail-fast: false<br>       matrix:<br>         BUILDTYPE: [Debug, Release]<br>-        GC64: [ON, OFF]<br>+        GC64: ON<br>         include:<br>           - BUILDTYPE: Debug<br>             CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON<br>@@ -69,15 +69,6 @@ jobs:<br>       - name: test<br>         run: cmake --build . --parallel --target test<br><br>-  test-tarantool-debug-wo-GC64:<br>-    name: Tarantool Debug GC64:OFF<br>-    needs: test-luajit<br>-    uses: tarantool/tarantool/.github/workflows/luajit-integration.yml@master<br>-    with:<br>-      GC64: OFF<br>-      buildtype: Debug<br>-      host: macos-11<br>-      revision: ${{ github.sha }}<br>   test-tarantool-debug-w-GC64:<br>     name: Tarantool Debug GC64:ON<br>     needs: test-luajit<br>@@ -87,15 +78,6 @@ jobs:<br>       buildtype: Debug<br>       host: macos-11<br>       revision: ${{ github.sha }}<br>-  test-tarantool-release-wo-GC64:<br>-    name: Tarantool Release GC64:OFF<br>-    needs: test-luajit<br>-    uses: tarantool/tarantool/.github/workflows/luajit-integration.yml@master<br>-    with:<br>-      GC64: OFF<br>-      buildtype: RelWithDebInfo<br>-      host: macos-11<br>-      revision: ${{ github.sha }}<br>   test-tarantool-release-w-GC64:<br>     name: Tarantool Release GC64:ON<br>     needs: test-luajit<br>diff --git a/CMakeLists.txt b/CMakeLists.txt<br>index 8b49f9d7..c4f3ef62 100644<br>--- a/CMakeLists.txt<br>+++ b/CMakeLists.txt<br>@@ -176,6 +176,9 @@ endif()<br><br> # Enable GC64 mode for x64.<br> option(LUAJIT_ENABLE_GC64 "GC64 mode for x64" OFF)<br>+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")<br>+  set(LUAJIT_ENABLE_GC64 ON)<br>+endif()<br> if(LUAJIT_ENABLE_GC64)<br>   AppendFlags(TARGET_C_FLAGS -DLUAJIT_ENABLE_GC64)<br> endif()<br>diff --git a/cmake/SetTargetFlags.cmake b/cmake/SetTargetFlags.cmake<br>index b544d2ac..36896aff 100644<br>--- a/cmake/SetTargetFlags.cmake<br>+++ b/cmake/SetTargetFlags.cmake<br>@@ -15,6 +15,22 @@ endif()<br> LuaJITTestArch(TESTARCH "${TARGET_C_FLAGS}")<br> LuaJITArch(LUAJIT_ARCH "${TESTARCH}")<br><br>+string(FIND ${TARGET_C_FLAGS} "LJ_NO_UNWIND 1" UNWIND_POS)<br>+if(UNWIND_POS EQUAL -1)<br>+  execute_process(<br>+    COMMAND bash -c "exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | ${CMAKE_C_COMPILER} -c -x c - -o tmpunwind.o && grep -qa -e eh_frame -e __unwind_info tmpunwind.o && echo E; rm -f tmpunwind.o"<br>+    WORKING_DIRECTORY ${LUAJIT_SOURCE_DIR}<br>+    OUTPUT_VARIABLE TESTUNWIND<br>+    RESULT_VARIABLE TESTUNWIND_RC<br>+  )<br>+  if(TESTUNWIND_RC EQUAL 0)<br>+    string(FIND "${TESTUNWIND}" "E" UNW_TEST_POS)<br>+    if(NOT UNW_TEST_POS EQUAL -1)<br>+      AppendFlags(TARGET_C_FLAGS -DLUAJIT_UNWIND_EXTERNAL)<br>+    endif()<br>+  endif()<br>+endif()<br>+<br> # Target-specific compiler options.<br> #<br> # x86/x64 only: For GCC 4.2 or higher and if you don't intend to<br>@@ -25,12 +41,6 @@ if(LUAJIT_ARCH STREQUAL "x86")<br> endif()<br><br> if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")<br>-  if(LUAJIT_ARCH STREQUAL "x64")<br>-    # XXX: Set -pagezero_size to hint <mmap> when allocating 32<br>-    # bit memory on OSX/x64, otherwise the lower 4GB are blocked.<br>-    AppendFlags(TARGET_BIN_FLAGS -pagezero_size 10000 -image_base 100000000)<br>-    AppendFlags(TARGET_SHARED_FLAGS -image_base 7fff04c4a000)<br>-  endif()<br>   AppendFlags(TARGET_SHARED_FLAGS -single_module -undefined dynamic_lookup)<br> else() # Linux and FreeBSD.<br>   AppendFlags(TARGET_BIN_FLAGS -Wl,-E)<br>diff --git a/doc/extensions.html b/doc/extensions.html<br>index e0f136e2..777e9928 100644<br>--- a/doc/extensions.html<br>+++ b/doc/extensions.html<br>@@ -395,29 +395,19 @@ the toolchain used to compile LuaJIT:<br> <td class="excinterop">Interoperability</td><br> </tr><br> <tr class="odd separate"><br>-<td class="excplatform">POSIX/x64, DWARF2 unwinding</td><br>-<td class="exccompiler">GCC 4.3+, Clang</td><br>+<td class="excplatform">External frame unwinding</td><br>+<td class="exccompiler">GCC, Clang, MSVC</td><br> <td class="excinterop"><b style="color: #00a000;">Full</b></td><br> </tr><br> <tr class="even"><br>-<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td><br>-<td class="exccompiler">GCC, Clang</td><br>-<td class="excinterop"><b style="color: #00a000;">Full</b></td><br>-</tr><br>-<tr class="odd"><br>-<td class="excplatform">Other platforms, DWARF2 unwinding</td><br>+<td class="excplatform">Internal frame unwinding + DWARF2</td><br> <td class="exccompiler">GCC, Clang</td><br> <td class="excinterop"><b style="color: #c06000;">Limited</b></td><br> </tr><br>-<tr class="even"><br>-<td class="excplatform">Windows/x64</td><br>-<td class="exccompiler">MSVC or WinSDK</td><br>-<td class="excinterop"><b style="color: #00a000;">Full</b></td><br>-</tr><br> <tr class="odd"><br>-<td class="excplatform">Windows/x86</td><br>-<td class="exccompiler">Any</td><br>-<td class="excinterop"><b style="color: #00a000;">Full</b></td><br>+<td class="excplatform">Windows 64 bit</td><br>+<td class="exccompiler">non-MSVC</td><br>+<td class="excinterop"><b style="color: #c06000;">Limited</b></td><br> </tr><br> <tr class="even"><br> <td class="excplatform">Other platforms</td><br>diff --git a/src/Makefile.original b/src/Makefile.original<br>index dd1c6a76..c9609700 100644<br>--- a/src/Makefile.original<br>+++ b/src/Makefile.original<br>@@ -320,6 +320,13 @@ else<br> ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))<br>   TARGET_XCFLAGS+= -fno-stack-protector<br> endif<br>+ifeq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))<br>+  # Find out whether the target toolchain always generates unwind tables.<br>+  TARGET_TESTUNWIND=$(shell exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | $(TARGET_CC) -c -x c - -o tmpunwind.o && grep -qa -e eh_frame -e __unwind_info tmpunwind.o && echo E; rm -f tmpunwind.o)<br>+  ifneq (,$(findstring E,$(TARGET_TESTUNWIND)))<br>+    TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL<br>+  endif<br>+endif<br> ifeq (Darwin,$(TARGET_SYS))<br>   ifeq (,$(MACOSX_DEPLOYMENT_TARGET))<br>     export MACOSX_DEPLOYMENT_TARGET=10.4<br>@@ -328,10 +335,6 @@ ifeq (Darwin,$(TARGET_SYS))<br>   TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC<br>   TARGET_DYNXLDOPTS=<br>   TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)<br>-  ifeq (x64,$(TARGET_LJARCH))<br>-    TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000<br>-    TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000<br>-  endif<br> else<br> ifeq (iOS,$(TARGET_SYS))<br>   TARGET_STRIP+= -x<br>diff --git a/src/lj_arch.h b/src/lj_arch.h<br>index 40129d9e..730be5bf 100644<br>--- a/src/lj_arch.h<br>+++ b/src/lj_arch.h<br>@@ -152,11 +152,6 @@<br> #define LJ_ARCH_NAME<span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span>"x86"<br> #define LJ_ARCH_BITS<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>32<br> #define LJ_ARCH_ENDIAN<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>LUAJIT_LE<br>-#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN<br>-#define LJ_ABI_WIN<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br>-#else<br>-#define LJ_ABI_WIN<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>0<br>-#endif<br> #define LJ_TARGET_X86<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br> #define LJ_TARGET_X86ORX64<span class="Apple-tab-span" style="white-space:pre">      </span>1<br> #define LJ_TARGET_EHRETREG<span class="Apple-tab-span" style="white-space:pre">      </span>0<br>@@ -170,11 +165,6 @@<br> #define LJ_ARCH_NAME<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>"x64"<br> #define LJ_ARCH_BITS<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>64<br> #define LJ_ARCH_ENDIAN<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>LUAJIT_LE<br>-#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN<br>-#define LJ_ABI_WIN<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br>-#else<br>-#define LJ_ABI_WIN<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>0<br>-#endif<br> #define LJ_TARGET_X64<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br> #define LJ_TARGET_X86ORX64<span class="Apple-tab-span" style="white-space:pre">      </span>1<br> #define LJ_TARGET_EHRETREG<span class="Apple-tab-span" style="white-space:pre">      </span>0<br>@@ -185,6 +175,8 @@<br> #define LJ_ARCH_NUMMODE<span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>LJ_NUMMODE_SINGLE_DUAL<br> #ifdef LUAJIT_ENABLE_GC64<br> #define LJ_TARGET_GC64<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br>+#elif LJ_TARGET_OSX<br>+#error "macOS requires GC64 -- don't disable it"<br> #endif<br><br> #elif LUAJIT_TARGET == LUAJIT_ARCH_ARM<br>@@ -566,15 +558,22 @@<br> #define LJ_NO_SYSTEM<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br> #endif<br><br>-#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__<br>-/* NYI: no support for compact unwind specification, yet. */<br>-#define LUAJIT_NO_UNWIND<span class="Apple-tab-span" style="white-space:pre">       </span>1<br>+#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN<br>+#define LJ_ABI_WIN<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br>+#else<br>+#define LJ_ABI_WIN<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>0<br> #endif<br><br>-#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4<br>+#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4<br> #define LJ_NO_UNWIND<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br> #endif<br><br>+#if !LJ_NO_UNWIND && !defined(LUAJIT_UNWIND_INTERNAL) && (LJ_ABI_WIN || (defined(LUAJIT_UNWIND_EXTERNAL) && (defined(__GNUC__) || defined(__clang__))))<br>+#define LJ_UNWIND_EXT<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br>+#else<br>+#define LJ_UNWIND_EXT<span class="Apple-tab-span" style="white-space:pre">   </span><span class="Apple-tab-span" style="white-space:pre">    </span>0<br>+#endif<br>+<br> /* Compatibility with Lua 5.1 vs. 5.2. */<br> #ifdef LUAJIT_ENABLE_LUA52COMPAT<br> #define LJ_52<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>1<br>diff --git a/src/lj_err.c b/src/lj_err.c<br>index c310daf6..298e5434 100644<br>--- a/src/lj_err.c<br>+++ b/src/lj_err.c<br>@@ -29,12 +29,18 @@<br> ** Pros and Cons:<br> **<br> ** - EXT requires unwind tables for *all* functions on the C stack between<br>-**   the pcall/catch and the error/throw. This is the default on x64,<br>-**   but needs to be manually enabled on x86/PPC for non-C++ code.<br>+**   the pcall/catch and the error/throw. C modules used by Lua code can<br>+**   throw errors, so these need to have unwind tables, too. Transitively<br>+**   this applies to all system libraries used by C modules -- at least<br>+**   when they have callbacks which may throw an error.<br> **<br>-** - INT is faster when actually throwing errors (but this happens rarely).<br>+** - INT is faster when actually throwing errors, but this happens rarely.<br> **   Setting up error handlers is zero-cost in any case.<br> **<br>+** - INT needs to save *all* callee-saved registers when entering the<br>+**   interpreter. EXT only needs to save those actually used inside the<br>+**   interpreter. JIT-compiled code may need to save some more.<br>+**<br> ** - EXT provides full interoperability with C++ exceptions. You can throw<br> **   Lua errors or C++ exceptions through a mix of Lua frames and C++ frames.<br> **   C++ destructors are called as needed. C++ exceptions caught by pcall<br>@@ -46,27 +52,33 @@<br> **   the wrapper function feature. Lua errors thrown through C++ frames<br> **   cannot be caught by C++ code and C++ destructors are not run.<br> **<br>-** EXT is the default on x64 systems and on Windows, INT is the default on all<br>-** other systems.<br>+** EXT is the default on all systems where the toolchain produces unwind<br>+** tables by default (*). This is hard-coded and/or detected in src/Makefile.<br>+** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL<br>+**<br>+** INT is the default on all other systems.<br>+**<br>+** EXT can be manually enabled for toolchains that are able to produce<br>+** conforming unwind tables:<br>+**   "TARGET_XCFLAGS=-funwind-tables -DLUAJIT_UNWIND_EXTERNAL"<br>+** As explained above, *all* C code used directly or indirectly by LuaJIT<br>+** must be compiled with -funwind-tables (or -fexceptions). C++ code must<br>+** *not* be compiled with -fno-exceptions.<br>+**<br>+** If you're unsure whether error handling inside the VM works correctly,<br>+** try running this and check whether it prints "OK":<br> **<br>-** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack<br>-** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled<br>-** with -funwind-tables (or -fexceptions). This includes LuaJIT itself (set<br>-** TARGET_CFLAGS), all of your C/Lua binding code, all loadable C modules<br>-** and all C libraries that have callbacks which may be used to call back<br>-** into Lua. C++ code must *not* be compiled with -fno-exceptions.<br>+**   luajit -e "print(select(2, load('OK')):match('OK'))"<br> **<br>-** EXT is mandatory on WIN64 since the calling convention has an abundance<br>-** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15).<br>-** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4).<br>+** (*) Originally, toolchains only generated unwind tables for C++ code. For<br>+** interoperability reasons, this can be manually enabled for plain C code,<br>+** too (with -funwind-tables). With the introduction of the x64 architecture,<br>+** the corresponding POSIX and Windows ABIs mandated unwind tables for all<br>+** code. Over the following years most desktop and server platforms have<br>+** enabled unwind tables by default on all architectures. OTOH mobile and<br>+** embedded platforms do not consistently mandate unwind tables.<br> */<br><br>-#if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND<br>-#define LJ_UNWIND_EXT<span class="Apple-tab-span" style="white-space:pre">      </span>1<br>-#elif LJ_TARGET_WINDOWS<br>-#define LJ_UNWIND_EXT<span class="Apple-tab-span" style="white-space:pre"> </span>1<br>-#endif<br>-<br> /* -- Error messages ------------------------------------------------------ */<br><br> /* Error message strings. */<br>@@ -183,7 +195,125 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)<br><br> /* -- External frame unwinding -------------------------------------------- */<br><br>-#if defined(__GNUC__) && !LJ_NO_UNWIND && !LJ_ABI_WIN<br>+#if LJ_ABI_WIN<br>+<br>+/*<br>+** Someone in Redmond owes me several days of my life. A lot of this is<br>+** undocumented or just plain wrong on MSDN. Some of it can be gathered<br>+** from 3rd party docs or must be found by trial-and-error. They really<br>+** don't want you to write your own language-specific exception handler<br>+** or to interact gracefully with MSVC. :-(<br>+**<br>+** Apparently MSVC doesn't call C++ destructors for foreign exceptions<br>+** unless you compile your C++ code with /EHa. Unfortunately this means<br>+** catch (...) also catches things like access violations. The use of<br>+** _set_se_translator doesn't really help, because it requires /EHa, too.<br>+*/<br>+<br>+#define WIN32_LEAN_AND_MEAN<br>+#include <windows.h><br>+<br>+#if LJ_TARGET_X86<br>+typedef void *UndocumentedDispatcherContext;  /* Unused on x86. */<br>+#else<br>+/* Taken from: http://www.nynaeve.net/?p=99 */<br>+typedef struct UndocumentedDispatcherContext {<br>+  ULONG64 ControlPc;<br>+  ULONG64 ImageBase;<br>+  PRUNTIME_FUNCTION FunctionEntry;<br>+  ULONG64 EstablisherFrame;<br>+  ULONG64 TargetIp;<br>+  PCONTEXT ContextRecord;<br>+  void (*LanguageHandler)(void);<br>+  PVOID HandlerData;<br>+  PUNWIND_HISTORY_TABLE HistoryTable;<br>+  ULONG ScopeIndex;<br>+  ULONG Fill0;<br>+} UndocumentedDispatcherContext;<br>+#endif<br>+<br>+/* Another wild guess. */<br>+extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);<br>+<br>+#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT)<br>+/* Workaround for broken MinGW64 declaration. */<br>+VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");<br>+#define RtlUnwindEx RtlUnwindEx_FIXED<br>+#endif<br>+<br>+#define LJ_MSVC_EXCODE<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>((DWORD)0xe06d7363)<br>+#define LJ_GCC_EXCODE<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>((DWORD)0x20474343)<br>+<br>+#define LJ_EXCODE<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>((DWORD)0xe24c4a00)<br>+#define LJ_EXCODE_MAKE(c)<span class="Apple-tab-span" style="white-space:pre">     </span>(LJ_EXCODE | (DWORD)(c))<br>+#define LJ_EXCODE_CHECK(cl)<span class="Apple-tab-span" style="white-space:pre">      </span>(((cl) ^ LJ_EXCODE) <= 0xff)<br>+#define LJ_EXCODE_ERRCODE(cl)<span class="Apple-tab-span" style="white-space:pre">     </span>((int)((cl) & 0xff))<br>+<br>+/* Windows exception handler for interpreter frame. */<br>+LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,<br>+  void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)<br>+{<br>+#if LJ_TARGET_X86<br>+  void *cf = (char *)f - CFRAME_OFS_SEH;<br>+#else<br>+  void *cf = f;<br>+#endif<br>+  lua_State *L = cframe_L(cf);<br>+  int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?<br>+<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;<br>+  if ((rec->ExceptionFlags & 6)) {  /* EH_UNWINDING|EH_EXIT_UNWIND */<br>+    /* Unwind internal frames. */<br>+    err_unwind(L, cf, errcode);<br>+  } else {<br>+    void *cf2 = err_unwind(L, cf, 0);<br>+    if (cf2) {  /* We catch it, so start unwinding the upper frames. */<br>+      if (rec->ExceptionCode == LJ_MSVC_EXCODE ||<br>+<span class="Apple-tab-span" style="white-space:pre">       </span>  rec->ExceptionCode == LJ_GCC_EXCODE) {<br>+#if !LJ_TARGET_CYGWIN<br>+<span class="Apple-tab-span" style="white-space:pre"> </span>__DestructExceptionObject(rec, 1);<br>+#endif<br>+<span class="Apple-tab-span" style="white-space:pre">      </span>setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));<br>+      } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {<br>+<span class="Apple-tab-span" style="white-space:pre">    </span>/* Don't catch access violations etc. */<br>+<span class="Apple-tab-span" style="white-space:pre"> </span>return 1;  /* ExceptionContinueSearch */<br>+      }<br>+#if LJ_TARGET_X86<br>+      UNUSED(ctx);<br>+      UNUSED(dispatch);<br>+      /* Call all handlers for all lower C frames (including ourselves) again<br>+      ** with EH_UNWINDING set. Then call the specified function, passing cf<br>+      ** and errcode.<br>+      */<br>+      lj_vm_rtlunwind(cf, (void *)rec,<br>+<span class="Apple-tab-span" style="white-space:pre">    </span>(cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?<br>+<span class="Apple-tab-span" style="white-space:pre">        </span>(void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);<br>+      /* lj_vm_rtlunwind does not return. */<br>+#else<br>+      /* Unwind the stack and call all handlers for all lower C frames<br>+      ** (including ourselves) again with EH_UNWINDING set. Then set<br>+      ** stack pointer = cf, result = errcode and jump to the specified target.<br>+      */<br>+      RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?<br>+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>       lj_vm_unwind_ff_eh :<br>+<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>       lj_vm_unwind_c_eh),<br>+<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>  rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);<br>+      /* RtlUnwindEx should never return. */<br>+#endif<br>+    }<br>+  }<br>+  return 1;  /* ExceptionContinueSearch */<br>+}<br>+<br>+/* Raise Windows exception. */<br>+static void err_raise_ext(global_State *g, int errcode)<br>+{<br>+#if LJ_HASJIT<br>+  setmref(g->jit_base, NULL);<br>+#endif<br>+  RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);<br>+}<br>+<br>+#elif !LJ_NO_UNWIND && (defined(__GNUC__) || defined(__clang__))<br><br> /*<br> ** We have to use our own definitions instead of the mandatory (!) unwind.h,<br>@@ -232,7 +362,6 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,<br>   lua_State *L;<br>   if (version != 1)<br>     return _URC_FATAL_PHASE1_ERROR;<br>-  UNUSED(uexclass);<br>   cf = (void *)_Unwind_GetCFA(ctx);<br>   L = cframe_L(cf);<br>   if ((actions & _UA_SEARCH_PHASE)) {<br>@@ -280,6 +409,9 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,<br>     ** it on non-x64 because the interpreter restores all callee-saved regs.<br>     */<br>     lj_err_throw(L, errcode);<br>+#if LJ_TARGET_X64<br>+#error "Broken build system -- only use the provided Makefiles!"<br>+#endif<br> #endif<br>   }<br>   return _URC_CONTINUE_UNWIND;<br>@@ -292,14 +424,6 @@ static _Unwind_Exception static_uex;<br> #else<br> static __thread _Unwind_Exception static_uex;<br> #endif<br>-<br>-/* Raise DWARF2 exception. */<br>-static void err_raise_ext(int errcode)<br>-{<br>-  static_uex.exclass = LJ_UEXCLASS_MAKE(errcode);<br>-  static_uex.excleanup = NULL;<br>-  _Unwind_RaiseException(&static_uex);<br>-}<br> #endif<br><br> #else /* LJ_TARGET_ARM */<br>@@ -373,132 +497,22 @@ LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb,<br><br> #if LJ_UNWIND_EXT<br> static __thread _Unwind_Control_Block static_uex;<br>+#endif<br>+#endif /* LJ_TARGET_ARM */<br><br>-static void err_raise_ext(int errcode)<br>+#if LJ_UNWIND_EXT<br>+/* Raise external exception. */<br>+static void err_raise_ext(global_State *g, int errcode)<br> {<br>+#if LJ_HASJIT<br>+  setmref(g->jit_base, NULL);<br>+#endif<br>   memset(&static_uex, 0, sizeof(static_uex));<br>   static_uex.exclass = LJ_UEXCLASS_MAKE(errcode);<br>   _Unwind_RaiseException(&static_uex);<br> }<br> #endif<br><br>-#endif /* LJ_TARGET_ARM */<br>-<br>-#elif LJ_ABI_WIN<br>-<br>-/*<br>-** Someone in Redmond owes me several days of my life. A lot of this is<br>-** undocumented or just plain wrong on MSDN. Some of it can be gathered<br>-** from 3rd party docs or must be found by trial-and-error. They really<br>-** don't want you to write your own language-specific exception handler<br>-** or to interact gracefully with MSVC. :-(<br>-**<br>-** Apparently MSVC doesn't call C++ destructors for foreign exceptions<br>-** unless you compile your C++ code with /EHa. Unfortunately this means<br>-** catch (...) also catches things like access violations. The use of<br>-** _set_se_translator doesn't really help, because it requires /EHa, too.<br>-*/<br>-<br>-#define WIN32_LEAN_AND_MEAN<br>-#include <windows.h><br>-<br>-#if LJ_TARGET_X64<br>-/* Taken from: http://www.nynaeve.net/?p=99 */<br>-typedef struct UndocumentedDispatcherContext {<br>-  ULONG64 ControlPc;<br>-  ULONG64 ImageBase;<br>-  PRUNTIME_FUNCTION FunctionEntry;<br>-  ULONG64 EstablisherFrame;<br>-  ULONG64 TargetIp;<br>-  PCONTEXT ContextRecord;<br>-  void (*LanguageHandler)(void);<br>-  PVOID HandlerData;<br>-  PUNWIND_HISTORY_TABLE HistoryTable;<br>-  ULONG ScopeIndex;<br>-  ULONG Fill0;<br>-} UndocumentedDispatcherContext;<br>-#else<br>-typedef void *UndocumentedDispatcherContext;<br>-#endif<br>-<br>-/* Another wild guess. */<br>-extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);<br>-<br>-#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT)<br>-/* Workaround for broken MinGW64 declaration. */<br>-VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");<br>-#define RtlUnwindEx RtlUnwindEx_FIXED<br>-#endif<br>-<br>-#define LJ_MSVC_EXCODE<span class="Apple-tab-span" style="white-space:pre">   </span><span class="Apple-tab-span" style="white-space:pre">    </span>((DWORD)0xe06d7363)<br>-#define LJ_GCC_EXCODE<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>((DWORD)0x20474343)<br>-<br>-#define LJ_EXCODE<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>((DWORD)0xe24c4a00)<br>-#define LJ_EXCODE_MAKE(c)<span class="Apple-tab-span" style="white-space:pre">     </span>(LJ_EXCODE | (DWORD)(c))<br>-#define LJ_EXCODE_CHECK(cl)<span class="Apple-tab-span" style="white-space:pre">      </span>(((cl) ^ LJ_EXCODE) <= 0xff)<br>-#define LJ_EXCODE_ERRCODE(cl)<span class="Apple-tab-span" style="white-space:pre">     </span>((int)((cl) & 0xff))<br>-<br>-/* Windows exception handler for interpreter frame. */<br>-LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,<br>-  void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)<br>-{<br>-#if LJ_TARGET_X64<br>-  void *cf = f;<br>-#else<br>-  void *cf = (char *)f - CFRAME_OFS_SEH;<br>-#endif<br>-  lua_State *L = cframe_L(cf);<br>-  int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?<br>-<span class="Apple-tab-span" style="white-space:pre">      </span><span class="Apple-tab-span" style="white-space:pre">    </span>LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;<br>-  if ((rec->ExceptionFlags & 6)) {  /* EH_UNWINDING|EH_EXIT_UNWIND */<br>-    /* Unwind internal frames. */<br>-    err_unwind(L, cf, errcode);<br>-  } else {<br>-    void *cf2 = err_unwind(L, cf, 0);<br>-    if (cf2) {  /* We catch it, so start unwinding the upper frames. */<br>-      if (rec->ExceptionCode == LJ_MSVC_EXCODE ||<br>-<span class="Apple-tab-span" style="white-space:pre">       </span>  rec->ExceptionCode == LJ_GCC_EXCODE) {<br>-#if LJ_TARGET_WINDOWS<br>-<span class="Apple-tab-span" style="white-space:pre"> </span>__DestructExceptionObject(rec, 1);<br>-#endif<br>-<span class="Apple-tab-span" style="white-space:pre">      </span>setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));<br>-      } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {<br>-<span class="Apple-tab-span" style="white-space:pre">    </span>/* Don't catch access violations etc. */<br>-<span class="Apple-tab-span" style="white-space:pre"> </span>return 1;  /* ExceptionContinueSearch */<br>-      }<br>-#if LJ_TARGET_X64<br>-      /* Unwind the stack and call all handlers for all lower C frames<br>-      ** (including ourselves) again with EH_UNWINDING set. Then set<br>-      ** rsp = cf, rax = errcode and jump to the specified target.<br>-      */<br>-      RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?<br>-<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>       lj_vm_unwind_ff_eh :<br>-<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>       lj_vm_unwind_c_eh),<br>-<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>  rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);<br>-      /* RtlUnwindEx should never return. */<br>-#else<br>-      UNUSED(ctx);<br>-      UNUSED(dispatch);<br>-      /* Call all handlers for all lower C frames (including ourselves) again<br>-      ** with EH_UNWINDING set. Then call the specified function, passing cf<br>-      ** and errcode.<br>-      */<br>-      lj_vm_rtlunwind(cf, (void *)rec,<br>-<span class="Apple-tab-span" style="white-space:pre">        </span>(cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?<br>-<span class="Apple-tab-span" style="white-space:pre">        </span>(void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);<br>-      /* lj_vm_rtlunwind does not return. */<br>-#endif<br>-    }<br>-  }<br>-  return 1;  /* ExceptionContinueSearch */<br>-}<br>-<br>-/* Raise Windows exception. */<br>-static void err_raise_ext(int errcode)<br>-{<br>-  RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);<br>-}<br>-<br> #endif<br><br> /* -- Error handling ------------------------------------------------------ */<br>@@ -508,22 +522,23 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode)<br> {<br>   global_State *g = G(L);<br>   lj_trace_abort(g);<br>-  setmref(g->jit_base, NULL);<br>   L->status = LUA_OK;<br> #if LJ_UNWIND_EXT<br>-  err_raise_ext(errcode);<br>+  err_raise_ext(g, errcode);<br>   /*<br>   ** A return from this function signals a corrupt C stack that cannot be<br>   ** unwound. We have no choice but to call the panic function and exit.<br>   **<br>   ** Usually this is caused by a C function without unwind information.<br>-  ** This should never happen on x64, but may happen if you've manually<br>-  ** enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every*<br>-  ** non-C++ file with -funwind-tables.<br>+  ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL<br>+  ** and forgot to recompile *every* non-C++ file with -funwind-tables.<br>   */<br>   if (G(L)->panic)<br>     G(L)->panic(L);<br> #else<br>+#if LJ_HASJIT<br>+  setmref(g->jit_base, NULL);<br>+#endif<br>   {<br>     void *cf = err_unwind(L, NULL, errcode);<br>     if (cframe_unwind_ff(cf))<br>-- <br>2.37.0 (Apple Git-136)<br><br></div></div></blockquote></div><br></div></div></div></body></html>