From 18c1bf02b74479f20f00fcd6b08586f21a53e62d Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Tue, 4 Jun 2013 12:54:08 +0000
Subject: [PATCH] Upgraded LuaJIT to 2.0.2 Fixed strange luajit speed issue

git-svn-id: http://svn.net-core.org/repos/t-engine4@6821 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/thirdparty/jit/bc.lua     |  2 +-
 game/thirdparty/jit/bcsave.lua |  2 +-
 game/thirdparty/jit/dump.lua   |  2 +-
 game/thirdparty/jit/v.lua      |  2 +-
 src/luajit2/README             |  2 +-
 src/luajit2/dynasm/dasm_arm.h  |  3 +-
 src/luajit2/dynasm/dasm_mips.h |  3 +-
 src/luajit2/dynasm/dasm_ppc.h  |  3 +-
 src/luajit2/dynasm/dasm_x86.h  |  3 +-
 src/luajit2/src/host/buildvm.c |  6 +++
 src/luajit2/src/jit/bc.lua     |  2 +-
 src/luajit2/src/jit/bcsave.lua |  2 +-
 src/luajit2/src/jit/dump.lua   |  2 +-
 src/luajit2/src/jit/v.lua      |  2 +-
 src/luajit2/src/lib_ffi.c      |  2 +-
 src/luajit2/src/lib_io.c       |  4 ++
 src/luajit2/src/lib_table.c    |  4 +-
 src/luajit2/src/lj_alloc.c     | 17 ++++++---
 src/luajit2/src/lj_asm.c       | 32 ++++++++++++++--
 src/luajit2/src/lj_asm_arm.h   | 16 +++++---
 src/luajit2/src/lj_asm_mips.h  |  6 ++-
 src/luajit2/src/lj_asm_ppc.h   |  5 ++-
 src/luajit2/src/lj_asm_x86.h   | 13 +++----
 src/luajit2/src/lj_carith.c    |  2 +-
 src/luajit2/src/lj_ccall.c     | 70 ++++++++++++++++++++++++++++++++--
 src/luajit2/src/lj_ccallback.c |  4 +-
 src/luajit2/src/lj_cparse.c    | 18 ++++-----
 src/luajit2/src/lj_crecord.c   | 18 ++++-----
 src/luajit2/src/lj_def.h       | 10 ++---
 src/luajit2/src/lj_err.c       | 16 +++++---
 src/luajit2/src/lj_ffrecord.c  |  6 +--
 src/luajit2/src/lj_mcode.c     |  3 +-
 src/luajit2/src/lj_opt_fold.c  | 13 ++++---
 src/luajit2/src/lj_opt_mem.c   |  2 +-
 src/luajit2/src/lj_opt_split.c | 46 +++++++++++++---------
 src/luajit2/src/lj_record.c    | 33 ++--------------
 src/luajit2/src/lj_snap.c      |  2 +
 src/luajit2/src/lj_str.c       |  4 +-
 src/luajit2/src/lj_strscan.c   |  5 ++-
 src/luajit2/src/luaconf.h      |  8 +++-
 src/luajit2/src/luajit.c       | 15 ++++----
 src/luajit2/src/luajit.h       |  6 +--
 src/luajit2/src/vm_ppc.dasc    |  4 +-
 src/luajit2/src/vm_ppcspe.dasc | 14 +++----
 src/luajit2/src/vm_x86.dasc    |  4 ++
 45 files changed, 276 insertions(+), 162 deletions(-)

diff --git a/game/thirdparty/jit/bc.lua b/game/thirdparty/jit/bc.lua
index 5c00ebe317..cef4752467 100644
--- a/game/thirdparty/jit/bc.lua
+++ b/game/thirdparty/jit/bc.lua
@@ -41,7 +41,7 @@
 
 -- Cache some library functions and objects.
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local jutil = require("jit.util")
 local vmdef = require("jit.vmdef")
 local bit = require("bit")
diff --git a/game/thirdparty/jit/bcsave.lua b/game/thirdparty/jit/bcsave.lua
index 25bd604259..e6d566e534 100644
--- a/game/thirdparty/jit/bcsave.lua
+++ b/game/thirdparty/jit/bcsave.lua
@@ -11,7 +11,7 @@
 ------------------------------------------------------------------------------
 
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local bit = require("bit")
 
 -- Symbol name prefix for LuaJIT bytecode.
diff --git a/game/thirdparty/jit/dump.lua b/game/thirdparty/jit/dump.lua
index 70a59280e1..7441b74dbf 100644
--- a/game/thirdparty/jit/dump.lua
+++ b/game/thirdparty/jit/dump.lua
@@ -54,7 +54,7 @@
 
 -- Cache some library functions and objects.
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local jutil = require("jit.util")
 local vmdef = require("jit.vmdef")
 local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc
diff --git a/game/thirdparty/jit/v.lua b/game/thirdparty/jit/v.lua
index f4a9b054d7..d7df71262b 100644
--- a/game/thirdparty/jit/v.lua
+++ b/game/thirdparty/jit/v.lua
@@ -59,7 +59,7 @@
 
 -- Cache some library functions and objects.
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local jutil = require("jit.util")
 local vmdef = require("jit.vmdef")
 local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
diff --git a/src/luajit2/README b/src/luajit2/README
index e68604b72c..d837fd2ff6 100644
--- a/src/luajit2/README
+++ b/src/luajit2/README
@@ -1,4 +1,4 @@
-README for LuaJIT 2.0.1
+README for LuaJIT 2.0.2
 -----------------------
 
 LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
diff --git a/src/luajit2/dynasm/dasm_arm.h b/src/luajit2/dynasm/dasm_arm.h
index 691cfdd717..d83cbbb339 100644
--- a/src/luajit2/dynasm/dasm_arm.h
+++ b/src/luajit2/dynasm/dasm_arm.h
@@ -211,7 +211,8 @@ void dasm_put(Dst_DECL, int start, ...)
       case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
       case DASM_REL_LG:
 	n = (ins & 2047) - 10; pl = D->lglabels + n;
-	if (n >= 0) { CKPL(lg, LG); goto putrel; }  /* Bkwd rel or global. */
+	/* Bkwd rel or global. */
+	if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
 	pl += 10; n = *pl;
 	if (n < 0) n = 0;  /* Start new chain for fwd rel if label exists. */
 	goto linkrel;
diff --git a/src/luajit2/dynasm/dasm_mips.h b/src/luajit2/dynasm/dasm_mips.h
index 77a8eb5254..0866beb8bf 100644
--- a/src/luajit2/dynasm/dasm_mips.h
+++ b/src/luajit2/dynasm/dasm_mips.h
@@ -202,7 +202,8 @@ void dasm_put(Dst_DECL, int start, ...)
       case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
       case DASM_REL_LG:
 	n = (ins & 2047) - 10; pl = D->lglabels + n;
-	if (n >= 0) { CKPL(lg, LG); goto putrel; }  /* Bkwd rel or global. */
+	/* Bkwd rel or global. */
+	if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
 	pl += 10; n = *pl;
 	if (n < 0) n = 0;  /* Start new chain for fwd rel if label exists. */
 	goto linkrel;
diff --git a/src/luajit2/dynasm/dasm_ppc.h b/src/luajit2/dynasm/dasm_ppc.h
index 774ee6edf9..13c446110c 100644
--- a/src/luajit2/dynasm/dasm_ppc.h
+++ b/src/luajit2/dynasm/dasm_ppc.h
@@ -202,7 +202,8 @@ void dasm_put(Dst_DECL, int start, ...)
       case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
       case DASM_REL_LG:
 	n = (ins & 2047) - 10; pl = D->lglabels + n;
-	if (n >= 0) { CKPL(lg, LG); goto putrel; }  /* Bkwd rel or global. */
+	/* Bkwd rel or global. */
+	if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
 	pl += 10; n = *pl;
 	if (n < 0) n = 0;  /* Start new chain for fwd rel if label exists. */
 	goto linkrel;
diff --git a/src/luajit2/dynasm/dasm_x86.h b/src/luajit2/dynasm/dasm_x86.h
index eb2bc76840..c91bfdd53f 100644
--- a/src/luajit2/dynasm/dasm_x86.h
+++ b/src/luajit2/dynasm/dasm_x86.h
@@ -213,7 +213,8 @@ void dasm_put(Dst_DECL, int start, ...)
       case DASM_REL_LG:
       case DASM_IMM_LG:
 	n = *p++; pl = D->lglabels + n;
-	if (n <= 246) { CKPL(lg, LG); goto putrel; }  /* Bkwd rel or global. */
+	/* Bkwd rel or global. */
+	if (n <= 246) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
 	pl -= 246; n = *pl;
 	if (n < 0) n = 0;  /* Start new chain for fwd rel if label exists. */
 	goto linkrel;
diff --git a/src/luajit2/src/host/buildvm.c b/src/luajit2/src/host/buildvm.c
index ba8fbcba57..2ce3b63803 100644
--- a/src/luajit2/src/host/buildvm.c
+++ b/src/luajit2/src/host/buildvm.c
@@ -108,10 +108,16 @@ static const char *sym_decorate(BuildCtx *ctx,
   sprintf(name, "%s%s%s", symprefix, prefix, suffix);
   p = strchr(name, '@');
   if (p) {
+#if LJ_TARGET_X86ORX64
     if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
       name[0] = '@';
     else
       *p = '\0';
+#elif (LJ_TARGET_PPC  || LJ_TARGET_PPCSPE) && !LJ_TARGET_CONSOLE
+    /* Keep @plt. */
+#else
+    *p = '\0';
+#endif
   }
   p = (char *)malloc(strlen(name)+1);  /* MSVC doesn't like strdup. */
   strcpy(p, name);
diff --git a/src/luajit2/src/jit/bc.lua b/src/luajit2/src/jit/bc.lua
index 5c00ebe317..cef4752467 100644
--- a/src/luajit2/src/jit/bc.lua
+++ b/src/luajit2/src/jit/bc.lua
@@ -41,7 +41,7 @@
 
 -- Cache some library functions and objects.
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local jutil = require("jit.util")
 local vmdef = require("jit.vmdef")
 local bit = require("bit")
diff --git a/src/luajit2/src/jit/bcsave.lua b/src/luajit2/src/jit/bcsave.lua
index 25bd604259..e6d566e534 100644
--- a/src/luajit2/src/jit/bcsave.lua
+++ b/src/luajit2/src/jit/bcsave.lua
@@ -11,7 +11,7 @@
 ------------------------------------------------------------------------------
 
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local bit = require("bit")
 
 -- Symbol name prefix for LuaJIT bytecode.
diff --git a/src/luajit2/src/jit/dump.lua b/src/luajit2/src/jit/dump.lua
index 70a59280e1..7441b74dbf 100644
--- a/src/luajit2/src/jit/dump.lua
+++ b/src/luajit2/src/jit/dump.lua
@@ -54,7 +54,7 @@
 
 -- Cache some library functions and objects.
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local jutil = require("jit.util")
 local vmdef = require("jit.vmdef")
 local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc
diff --git a/src/luajit2/src/jit/v.lua b/src/luajit2/src/jit/v.lua
index f4a9b054d7..d7df71262b 100644
--- a/src/luajit2/src/jit/v.lua
+++ b/src/luajit2/src/jit/v.lua
@@ -59,7 +59,7 @@
 
 -- Cache some library functions and objects.
 local jit = require("jit")
-assert(jit.version_num == 20001, "LuaJIT core/library version mismatch")
+assert(jit.version_num == 20002, "LuaJIT core/library version mismatch")
 local jutil = require("jit.util")
 local vmdef = require("jit.vmdef")
 local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
diff --git a/src/luajit2/src/lib_ffi.c b/src/luajit2/src/lib_ffi.c
index 46f27e0135..f61fabc049 100644
--- a/src/luajit2/src/lib_ffi.c
+++ b/src/luajit2/src/lib_ffi.c
@@ -576,7 +576,7 @@ LJLIB_CF(ffi_istype)	LJLIB_REC(.)
       if (ctype_ispointer(ct1->info))
 	b = lj_cconv_compatptr(cts, ct1, ct2, CCF_IGNQUAL);
       else if (ctype_isnum(ct1->info) || ctype_isvoid(ct1->info))
-	b = (((ct1->info ^ ct2->info) & ~CTF_QUAL) == 0);
+	b = (((ct1->info ^ ct2->info) & ~(CTF_QUAL|CTF_LONG)) == 0);
     } else if (ctype_isstruct(ct1->info) && ctype_isptr(ct2->info) &&
 	       ct1 == ctype_rawchild(cts, ct2)) {
       b = 1;
diff --git a/src/luajit2/src/lib_io.c b/src/luajit2/src/lib_io.c
index 8858683fbd..e0c6908fae 100644
--- a/src/luajit2/src/lib_io.c
+++ b/src/luajit2/src/lib_io.c
@@ -17,6 +17,7 @@
 #include "lualib.h"
 
 #include "lj_obj.h"
+#include "lj_gc.h"
 #include "lj_err.h"
 #include "lj_str.h"
 #include "lj_state.h"
@@ -152,6 +153,7 @@ static int io_file_readline(lua_State *L, FILE *fp, MSize chop)
     if (n >= m - 64) m += m;
   }
   setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
+  lj_gc_check(L);
   return (int)ok;
 }
 
@@ -163,6 +165,7 @@ static void io_file_readall(lua_State *L, FILE *fp)
     n += (MSize)fread(buf+n, 1, m-n, fp);
     if (n != m) {
       setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
+      lj_gc_check(L);
       return;
     }
   }
@@ -174,6 +177,7 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
     char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
     MSize n = (MSize)fread(buf, 1, m, fp);
     setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
+    lj_gc_check(L);
     return (n > 0 || m == 0);
   } else {
     int c = getc(fp);
diff --git a/src/luajit2/src/lib_table.c b/src/luajit2/src/lib_table.c
index ba132f7c7c..e6bcfa5597 100644
--- a/src/luajit2/src/lib_table.c
+++ b/src/luajit2/src/lib_table.c
@@ -148,8 +148,8 @@ LJLIB_CF(table_concat)
   GCstr *sep = lj_lib_optstr(L, 2);
   MSize seplen = sep ? sep->len : 0;
   int32_t i = lj_lib_optint(L, 3, 1);
-  int32_t e = L->base+3 < L->top ? lj_lib_checkint(L, 4) :
-				   (int32_t)lj_tab_len(t);
+  int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ?
+	      lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t);
   luaL_buffinit(L, &b);
   if (i <= e) {
     for (;;) {
diff --git a/src/luajit2/src/lj_alloc.c b/src/luajit2/src/lj_alloc.c
index 82b4e5b165..8f285d174b 100644
--- a/src/luajit2/src/lj_alloc.c
+++ b/src/luajit2/src/lj_alloc.c
@@ -188,21 +188,24 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
   return ptr;
 }
 
-#elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
+#elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__sun__)
 
 /* OSX and FreeBSD mmap() use a naive first-fit linear search.
 ** That's perfect for us. Except that -pagezero_size must be set for OSX,
 ** otherwise the lower 4GB are blocked. And the 32GB RLIMIT_DATA needs
 ** to be reduced to 250MB on FreeBSD.
 */
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
-#include <sys/resource.h>
-#define MMAP_REGION_START	((uintptr_t)0x10000000)
-#else
+#if LJ_TARGET_OSX
 #define MMAP_REGION_START	((uintptr_t)0x10000)
+#else
+#define MMAP_REGION_START	((uintptr_t)0x10000000)
 #endif
 #define MMAP_REGION_END		((uintptr_t)0x80000000)
 
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <sys/resource.h>
+#endif
+
 static LJ_AINLINE void *CALL_MMAP(size_t size)
 {
   int olderr = errno;
@@ -227,6 +230,10 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
       return p;
     }
     if (p != CMFAIL) munmap(p, size);
+#ifdef __sun__
+    alloc_hint += 0x1000000;  /* Need near-exhaustive linear scan. */
+    if (alloc_hint + size < MMAP_REGION_END) continue;
+#endif
     if (retry) break;
     retry = 1;
     alloc_hint = MMAP_REGION_START;
diff --git a/src/luajit2/src/lj_asm.c b/src/luajit2/src/lj_asm.c
index c73654041e..316e81d6a8 100644
--- a/src/luajit2/src/lj_asm.c
+++ b/src/luajit2/src/lj_asm.c
@@ -30,6 +30,10 @@
 #include "lj_vm.h"
 #include "lj_target.h"
 
+#ifdef LUA_USE_ASSERT
+#include <stdio.h>
+#endif
+
 /* -- Assembler state and common macros ----------------------------------- */
 
 /* Assembler state. */
@@ -38,6 +42,9 @@ typedef struct ASMState {
 
   MCode *mcp;		/* Current MCode pointer (grows down). */
   MCode *mclim;		/* Lower limit for MCode memory + red zone. */
+#ifdef LUA_USE_ASSERT
+  MCode *mcp_prev;	/* Red zone overflow check. */
+#endif
 
   IRIns *ir;		/* Copy of pointer to IR instructions/constants. */
   jit_State *J;		/* JIT compiler state. */
@@ -110,14 +117,28 @@ typedef struct ASMState {
 
 /* Sparse limit checks using a red zone before the actual limit. */
 #define MCLIM_REDZONE	64
-#define checkmclim(as) \
-  if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as)
 
 static LJ_NORET LJ_NOINLINE void asm_mclimit(ASMState *as)
 {
   lj_mcode_limiterr(as->J, (size_t)(as->mctop - as->mcp + 4*MCLIM_REDZONE));
 }
 
+static LJ_AINLINE void checkmclim(ASMState *as)
+{
+#ifdef LUA_USE_ASSERT
+  if (as->mcp + MCLIM_REDZONE < as->mcp_prev) {
+    IRIns *ir = IR(as->curins+1);
+    fprintf(stderr, "RED ZONE OVERFLOW: %p IR %04d  %02d %04d %04d\n", as->mcp,
+	    as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS);
+    lua_assert(0);
+  }
+#endif
+  if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as);
+#ifdef LUA_USE_ASSERT
+  as->mcp_prev = as->mcp;
+#endif
+}
+
 #ifdef RID_NUM_KREF
 #define ra_iskref(ref)		((ref) < RID_NUM_KREF)
 #define ra_krefreg(ref)		((Reg)(RID_MIN_KREF + (Reg)(ref)))
@@ -927,7 +948,7 @@ static void asm_collectargs(ASMState *as, IRIns *ir,
 			    const CCallInfo *ci, IRRef *args)
 {
   uint32_t n = CCI_NARGS(ci);
-  lua_assert(n <= CCI_NARGS_MAX);
+  lua_assert(n <= CCI_NARGS_MAX*2);  /* Account for split args. */
   if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
   while (n-- > 1) {
     ir = IR(ir->op1);
@@ -1181,6 +1202,7 @@ static void asm_phi_copyspill(ASMState *as)
 	if (ra_hasspill(irl->s) && !irt_isfp(ir->t)) {
 	  emit_spstore(as, irl, r, sps_scale(irl->s));
 	  emit_spload(as, ir, r, sps_scale(ir->s));
+	  checkmclim(as);
 	}
       }
     }
@@ -1206,6 +1228,7 @@ static void asm_phi_copyspill(ASMState *as)
 	if (ra_hasspill(irl->s) && irt_isfp(ir->t)) {
 	  emit_spstore(as, irl, r, sps_scale(irl->s));
 	  emit_spload(as, ir, r, sps_scale(ir->s));
+	  checkmclim(as);
 	}
       }
     }
@@ -1822,6 +1845,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
 
   do {
     as->mcp = as->mctop;
+#ifdef LUA_USE_ASSERT
+    as->mcp_prev = as->mcp;
+#endif
     as->curins = T->nins;
     RA_DBG_START();
     RA_DBGX((as, "===== STOP ====="));
diff --git a/src/luajit2/src/lj_asm_arm.h b/src/luajit2/src/lj_asm_arm.h
index afb1054e88..a66573c0a3 100644
--- a/src/luajit2/src/lj_asm_arm.h
+++ b/src/luajit2/src/lj_asm_arm.h
@@ -91,6 +91,7 @@ static MCode *asm_exitstub_gen(ASMState *as, ExitNo group)
   *mxp++ = group*EXITSTUBS_PER_GROUP;
   for (i = 0; i < EXITSTUBS_PER_GROUP; i++)
     *mxp++ = ARMI_B|((-6-i)&0x00ffffffu);
+  lj_mcode_sync(as->mcbot, mxp);
   lj_mcode_commitbot(as->J, mxp);
   as->mcbot = mxp;
   as->mclim = as->mcbot + MCLIM_REDZONE;
@@ -463,7 +464,7 @@ static void asm_call(ASMState *as, IRIns *ir)
 
 static void asm_callx(ASMState *as, IRIns *ir)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   CCallInfo ci;
   IRRef func;
   IRIns *irf;
@@ -1816,6 +1817,7 @@ notst:
     as->flagmcp = as->mcp;  /* Allow elimination of the compare. */
 }
 
+#if LJ_HASFFI
 /* 64 bit integer comparisons. */
 static void asm_int64comp(ASMState *as, IRIns *ir)
 {
@@ -1851,6 +1853,7 @@ static void asm_int64comp(ASMState *as, IRIns *ir)
   }
   emit_n(as, ARMI_CMP^mhi, lefthi);
 }
+#endif
 
 /* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
 
@@ -1864,11 +1867,14 @@ static void asm_hiop(ASMState *as, IRIns *ir)
   if ((ir-1)->o <= IR_NE) {  /* 64 bit integer or FP comparisons. ORDER IR. */
     as->curins--;  /* Always skip the loword comparison. */
 #if LJ_SOFTFP
-    if (!irt_isint(ir->t))
+    if (!irt_isint(ir->t)) {
       asm_sfpcomp(as, ir-1);
-    else
+      return;
+    }
+#endif
+#if LJ_HASFFI
+    asm_int64comp(as, ir-1);
 #endif
-      asm_int64comp(as, ir-1);
     return;
 #if LJ_SOFTFP
   } else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) {
@@ -2289,7 +2295,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
 /* Ensure there are enough stack slots for call arguments. */
 static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   uint32_t i, nargs = (int)CCI_NARGS(ci);
   int nslots = 0, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR, fprodd = 0;
   asm_collectargs(as, ir, ci, args);
diff --git a/src/luajit2/src/lj_asm_mips.h b/src/luajit2/src/lj_asm_mips.h
index cd283b8831..9fe7c9c334 100644
--- a/src/luajit2/src/lj_asm_mips.h
+++ b/src/luajit2/src/lj_asm_mips.h
@@ -71,6 +71,7 @@ static void asm_sparejump_setup(ASMState *as)
     memset(mxp+2, 0, MIPS_SPAREJUMP*8);
     mxp += MIPS_SPAREJUMP*2;
     lua_assert(mxp < as->mctop);
+    lj_mcode_sync(as->mcbot, mxp);
     lj_mcode_commitbot(as->J, mxp);
     as->mcbot = mxp;
     as->mclim = as->mcbot + MCLIM_REDZONE;
@@ -282,6 +283,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
       else
 	ofs += 4;
     }
+    checkmclim(as);
   }
 }
 
@@ -335,7 +337,7 @@ static void asm_call(ASMState *as, IRIns *ir)
 
 static void asm_callx(ASMState *as, IRIns *ir)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   CCallInfo ci;
   IRRef func;
   IRIns *irf;
@@ -1892,7 +1894,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
 /* Ensure there are enough stack slots for call arguments. */
 static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   uint32_t i, nargs = (int)CCI_NARGS(ci);
   int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
   asm_collectargs(as, ir, ci, args);
diff --git a/src/luajit2/src/lj_asm_ppc.h b/src/luajit2/src/lj_asm_ppc.h
index 7637f6a6a7..651fa3187a 100644
--- a/src/luajit2/src/lj_asm_ppc.h
+++ b/src/luajit2/src/lj_asm_ppc.h
@@ -286,6 +286,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
       else
 	ofs += 4;
     }
+    checkmclim(as);
   }
   if ((ci->flags & CCI_VARARG))  /* Vararg calls need to know about FPR use. */
     emit_tab(as, fpr == REGARG_FIRSTFPR ? PPCI_CRXOR : PPCI_CREQV, 6, 6, 6);
@@ -339,7 +340,7 @@ static void asm_call(ASMState *as, IRIns *ir)
 
 static void asm_callx(ASMState *as, IRIns *ir)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   CCallInfo ci;
   IRRef func;
   IRIns *irf;
@@ -2091,7 +2092,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
 /* Ensure there are enough stack slots for call arguments. */
 static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   uint32_t i, nargs = (int)CCI_NARGS(ci);
   int nslots = 2, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
   asm_collectargs(as, ir, ci, args);
diff --git a/src/luajit2/src/lj_asm_x86.h b/src/luajit2/src/lj_asm_x86.h
index e9c53a0926..64441ccb7a 100644
--- a/src/luajit2/src/lj_asm_x86.h
+++ b/src/luajit2/src/lj_asm_x86.h
@@ -512,6 +512,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
       }
       ofs += sizeof(intptr_t);
     }
+    checkmclim(as);
   }
 #if LJ_64 && !LJ_ABI_WIN
   if (patchnfpr) *patchnfpr = fpr - REGARG_FIRSTFPR;
@@ -608,7 +609,7 @@ static void *asm_callx_func(ASMState *as, IRIns *irf, IRRef func)
 
 static void asm_callx(ASMState *as, IRIns *ir)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   CCallInfo ci;
   IRRef func;
   IRIns *irf;
@@ -2211,6 +2212,7 @@ static void asm_comp_int64(ASMState *as, IRIns *ir)
     lefthi = asm_fuseload(as, ir->op1, allow);
   } else {
     lefthi = ra_alloc1(as, ir->op1, allow);
+    rset_clear(allow, lefthi);
     righthi = asm_fuseload(as, ir->op2, allow);
     if (righthi == RID_MRM) {
       if (as->mrm.base != RID_NONE) rset_clear(allow, as->mrm.base);
@@ -2226,13 +2228,8 @@ static void asm_comp_int64(ASMState *as, IRIns *ir)
     leftlo = asm_fuseload(as, (ir-1)->op1, allow);
   } else {
     leftlo = ra_alloc1(as, (ir-1)->op1, allow);
+    rset_clear(allow, leftlo);
     rightlo = asm_fuseload(as, (ir-1)->op2, allow);
-    if (rightlo == RID_MRM) {
-      if (as->mrm.base != RID_NONE) rset_clear(allow, as->mrm.base);
-      if (as->mrm.idx != RID_NONE) rset_clear(allow, as->mrm.idx);
-    } else {
-      rset_clear(allow, rightlo);
-    }
   }
 
   /* All register allocations must be performed _before_ this point. */
@@ -2745,7 +2742,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
 /* Ensure there are enough stack slots for call arguments. */
 static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
 {
-  IRRef args[CCI_NARGS_MAX];
+  IRRef args[CCI_NARGS_MAX*2];
   int nslots;
   asm_collectargs(as, ir, ci, args);
   nslots = asm_count_call_slots(as, ci, args);
diff --git a/src/luajit2/src/lj_carith.c b/src/luajit2/src/lj_carith.c
index 18708d668a..afe7e6821d 100644
--- a/src/luajit2/src/lj_carith.c
+++ b/src/luajit2/src/lj_carith.c
@@ -238,7 +238,7 @@ static int lj_carith_meta(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
       return 1;
     }
     for (i = 0; i < 2; i++) {
-      if (ca->ct[i]) {
+      if (ca->ct[i] && tviscdata(L->base+i)) {
 	if (ctype_isenum(ca->ct[i]->info)) isenum = i;
 	repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, ca->ct[i]), NULL));
       } else {
diff --git a/src/luajit2/src/lj_ccall.c b/src/luajit2/src/lj_ccall.c
index 6196364a9a..eb73604f6e 100644
--- a/src/luajit2/src/lj_ccall.c
+++ b/src/luajit2/src/lj_ccall.c
@@ -32,6 +32,26 @@
 
 #else
 
+#if LJ_TARGET_OSX
+
+#define CCALL_HANDLE_STRUCTRET \
+  /* Return structs of size 1, 2, 4 or 8 in registers. */ \
+  cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \
+  if (cc->retref) { \
+    if (ngpr < maxgpr) \
+      cc->gpr[ngpr++] = (GPRArg)dp; \
+    else \
+      cc->stack[nsp++] = (GPRArg)dp; \
+  } else {  /* Struct with single FP field ends up in FPR. */ \
+    cc->resx87 = ccall_classify_struct(cts, ctr); \
+  }
+
+#define CCALL_HANDLE_STRUCTRET2 \
+  if (cc->resx87) sp = (uint8_t *)&cc->fpr[0]; \
+  memcpy(dp, sp, ctr->size);
+
+#else
+
 #define CCALL_HANDLE_STRUCTRET \
   cc->retref = 1;  /* Return all structs by reference (in reg or on stack). */ \
   if (ngpr < maxgpr) \
@@ -39,6 +59,8 @@
   else \
     cc->stack[nsp++] = (GPRArg)dp;
 
+#endif
+
 #define CCALL_HANDLE_COMPLEXRET \
   /* Return complex float in GPRs and complex double by reference. */ \
   cc->retref = (sz > 8); \
@@ -103,9 +125,9 @@
 /* Windows/x64 argument registers are strictly positional (use ngpr). */
 #define CCALL_HANDLE_REGARG \
   if (isfp) { \
-    if (ngpr < 4) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \
+    if (ngpr < maxgpr) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \
   } else { \
-    if (ngpr < 4) { dp = &cc->gpr[ngpr++]; goto done; } \
+    if (ngpr < maxgpr) { dp = &cc->gpr[ngpr++]; goto done; } \
   }
 
 #elif LJ_TARGET_X64
@@ -414,6 +436,42 @@
   memcpy(dp, sp, ctr->size);  /* Copy struct return value from GPRs. */
 #endif
 
+/* -- x86 OSX ABI struct classification ----------------------------------- */
+
+#if LJ_TARGET_X86 && LJ_TARGET_OSX
+
+/* Check for struct with single FP field. */
+static int ccall_classify_struct(CTState *cts, CType *ct)
+{
+  CTSize sz = ct->size;
+  if (!(sz == sizeof(float) || sz == sizeof(double))) return 0;
+  if ((ct->info & CTF_UNION)) return 0;
+  while (ct->sib) {
+    ct = ctype_get(cts, ct->sib);
+    if (ctype_isfield(ct->info)) {
+      CType *sct = ctype_rawchild(cts, ct);
+      if (ctype_isfp(sct->info)) {
+	if (sct->size == sz)
+	  return (sz >> 2);  /* Return 1 for float or 2 for double. */
+      } else if (ctype_isstruct(sct->info)) {
+	if (sct->size)
+	  return ccall_classify_struct(cts, sct);
+      } else {
+	break;
+      }
+    } else if (ctype_isbitfield(ct->info)) {
+      break;
+    } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
+      CType *sct = ctype_rawchild(cts, ct);
+      if (sct->size)
+	return ccall_classify_struct(cts, sct);
+    }
+  }
+  return 0;
+}
+
+#endif
+
 /* -- x64 struct classification ------------------------------------------- */
 
 #if LJ_TARGET_X64 && !LJ_ABI_WIN
@@ -526,22 +584,26 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct, CType *ctf)
   unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION);
   if ((ctf->info & CTF_VARARG)) goto noth;
   while (ct->sib) {
+    CType *sct;
     ct = ctype_get(cts, ct->sib);
     if (ctype_isfield(ct->info)) {
-      CType *sct = ctype_rawchild(cts, ct);
+      sct = ctype_rawchild(cts, ct);
       if (ctype_isfp(sct->info)) {
 	r |= sct->size;
 	if (!isu) n++; else if (n == 0) n = 1;
       } else if (ctype_iscomplex(sct->info)) {
 	r |= (sct->size >> 1);
 	if (!isu) n += 2; else if (n < 2) n = 2;
+      } else if (ctype_isstruct(sct->info)) {
+	goto substruct;
       } else {
 	goto noth;
       }
     } else if (ctype_isbitfield(ct->info)) {
       goto noth;
     } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
-      CType *sct = ctype_rawchild(cts, ct);
+      sct = ctype_rawchild(cts, ct);
+    substruct:
       if (sct->size > 0) {
 	unsigned int s = ccall_classify_struct(cts, sct, ctf);
 	if (s <= 1) goto noth;
diff --git a/src/luajit2/src/lj_ccallback.c b/src/luajit2/src/lj_ccallback.c
index a3a0d7985a..0010992323 100644
--- a/src/luajit2/src/lj_ccallback.c
+++ b/src/luajit2/src/lj_ccallback.c
@@ -286,9 +286,9 @@ void lj_ccallback_mcode_free(CTState *cts)
 /* Windows/x64 argument registers are strictly positional (use ngpr). */
 #define CALLBACK_HANDLE_REGARG \
   if (isfp) { \
-    if (ngpr < 4) { sp = &cts->cb.fpr[ngpr++]; nfpr = ngpr; goto done; } \
+    if (ngpr < maxgpr) { sp = &cts->cb.fpr[ngpr++]; UNUSED(nfpr); goto done; } \
   } else { \
-    if (ngpr < 4) { sp = &cts->cb.gpr[ngpr++]; goto done; } \
+    if (ngpr < maxgpr) { sp = &cts->cb.gpr[ngpr++]; goto done; } \
   }
 
 #elif LJ_TARGET_X64
diff --git a/src/luajit2/src/lj_cparse.c b/src/luajit2/src/lj_cparse.c
index 433fe87257..107c0381d4 100644
--- a/src/luajit2/src/lj_cparse.c
+++ b/src/luajit2/src/lj_cparse.c
@@ -57,7 +57,7 @@ static LJ_AINLINE int cp_iseol(CPChar c)
   return (c == '\n' || c == '\r');
 }
 
-static LJ_NOINLINE CPChar cp_get_bs(CPState *cp);
+static LJ_AINLINE CPChar cp_get(CPState *cp);
 
 /* Peek next raw character. */
 static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
@@ -65,14 +65,6 @@ static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
   return (CPChar)(uint8_t)(*cp->p);
 }
 
-/* Get next character. */
-static LJ_AINLINE CPChar cp_get(CPState *cp)
-{
-  cp->c = (CPChar)(uint8_t)(*cp->p++);
-  if (LJ_LIKELY(cp->c != '\\')) return cp->c;
-  return cp_get_bs(cp);
-}
-
 /* Transparently skip backslash-escaped line breaks. */
 static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
 {
@@ -85,6 +77,14 @@ static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
   return cp_get(cp);
 }
 
+/* Get next character. */
+static LJ_AINLINE CPChar cp_get(CPState *cp)
+{
+  cp->c = (CPChar)(uint8_t)(*cp->p++);
+  if (LJ_LIKELY(cp->c != '\\')) return cp->c;
+  return cp_get_bs(cp);
+}
+
 /* Grow save buffer. */
 static LJ_NOINLINE void cp_save_grow(CPState *cp, CPChar c)
 {
diff --git a/src/luajit2/src/lj_crecord.c b/src/luajit2/src/lj_crecord.c
index b60eb7b3c1..df98e6ec90 100644
--- a/src/luajit2/src/lj_crecord.c
+++ b/src/luajit2/src/lj_crecord.c
@@ -125,11 +125,6 @@ static IRType crec_ct2irt(CTState *cts, CType *ct)
 #define CREC_COPY_MAXLEN		128
 
 #define CREC_FILL_MAXUNROLL		16
-#if LJ_TARGET_UNALIGNED
-#define CREC_FILL_MAXLEN		(CTSIZE_PTR * CREC_FILL_MAXUNROLL)
-#else
-#define CREC_FILL_MAXLEN		CREC_FILL_MAXUNROLL
-#endif
 
 /* Number of windowed registers used for optimized memory copy. */
 #if LJ_TARGET_X86
@@ -320,9 +315,9 @@ static void crec_fill(jit_State *J, TRef trdst, TRef trlen, TRef trfill,
     MSize mlp;
     CTSize len = (CTSize)IR(tref_ref(trlen))->i;
     if (len == 0) return;  /* Shortcut. */
-    if (len > CREC_FILL_MAXLEN) goto fallback;
     if (LJ_TARGET_UNALIGNED || step >= CTSIZE_PTR)
       step = CTSIZE_PTR;
+    if (step * CREC_FILL_MAXUNROLL < len) goto fallback;
     mlp = crec_fill_unroll(ml, len, step);
     if (!mlp) goto fallback;
     if (tref_isk(trfill) || ml[0].tp != IRT_U8)
@@ -453,6 +448,10 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
     sinfo = CTINFO(CT_NUM, CTF_UNSIGNED);
     ssize = CTSIZE_PTR;
     st = IRT_UINTP;
+    if (((dsize ^ ssize) & 8) == 0) {  /* Must insert no-op type conversion. */
+      sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, IRT_PTR, 0);
+      goto xstore;
+    }
     goto conv_I_I;
 
   /* Destination is a floating-point number. */
@@ -619,7 +618,7 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
       emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE));
       sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, IRFL_UDATA_FILE);
     } else {
-      sp = emitir(IRT(IR_ADD, IRT_P32), sp, lj_ir_kint(J, sizeof(GCudata)));
+      sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata)));
     }
   } else if (tref_isstr(sp)) {
     if (ctype_isenum(d->info)) {  /* Match string against enum constant. */
@@ -637,7 +636,8 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
     } else if (ctype_isrefarray(d->info)) {  /* Copy string to array. */
       lj_trace_err(J, LJ_TRERR_BADTYPE);  /* NYI */
     } else {  /* Otherwise pass the string data as a const char[]. */
-      sp = emitir(IRT(IR_STRREF, IRT_P32), sp, lj_ir_kint(J, 0));
+      /* Don't use STRREF. It folds with SNEW, which loses the trailing NUL. */
+      sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCstr)));
       sid = CTID_A_CCHAR;
     }
   } else {  /* NYI: tref_istab(sp), tref_islightud(sp). */
@@ -1084,7 +1084,7 @@ static void crec_snap_caller(jit_State *J)
   const BCIns *pc = J->pc;
   TRef ftr = J->base[-1];
   ptrdiff_t delta;
-  if (!frame_islua(base-1))
+  if (!frame_islua(base-1) || J->framedepth <= 0)
     lj_trace_err(J, LJ_TRERR_NYICALL);
   J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]);
   L->top = base; L->base = base - delta;
diff --git a/src/luajit2/src/lj_def.h b/src/luajit2/src/lj_def.h
index 9a22e3bdb3..250729f759 100644
--- a/src/luajit2/src/lj_def.h
+++ b/src/luajit2/src/lj_def.h
@@ -101,8 +101,8 @@ typedef unsigned int uintptr_t;
 #define checkptr32(x)	((uintptr_t)(x) == (uint32_t)(uintptr_t)(x))
 
 /* Every half-decent C compiler transforms this into a rotate instruction. */
-#define lj_rol(x, n)	(((x)<<(n)) | ((x)>>(8*sizeof(x)-(n))))
-#define lj_ror(x, n)	(((x)<<(8*sizeof(x)-(n))) | ((x)>>(n)))
+#define lj_rol(x, n)	(((x)<<(n)) | ((x)>>(-(int)(n)&(8*sizeof(x)-1))))
+#define lj_ror(x, n)	(((x)<<(-(int)(n)&(8*sizeof(x)-1))) | ((x)>>(n)))
 
 /* A really naive Bloom filter. But sufficient for our needs. */
 typedef uintptr_t BloomFilter;
@@ -243,17 +243,17 @@ static LJ_AINLINE uint32_t lj_getu32(const void *p)
 #endif
 
 #ifdef _M_PPC
-#pragma intrinsic(_CountLeadingZeros)
 unsigned int _CountLeadingZeros(long);
+#pragma intrinsic(_CountLeadingZeros)
 static LJ_AINLINE uint32_t lj_fls(uint32_t x)
 {
   return _CountLeadingZeros(x) ^ 31;
 }
 #else
-#pragma intrinsic(_BitScanForward)
-#pragma intrinsic(_BitScanReverse)
 unsigned char _BitScanForward(uint32_t *, unsigned long);
 unsigned char _BitScanReverse(uint32_t *, unsigned long);
+#pragma intrinsic(_BitScanForward)
+#pragma intrinsic(_BitScanReverse)
 
 static LJ_AINLINE uint32_t lj_ffs(uint32_t x)
 {
diff --git a/src/luajit2/src/lj_err.c b/src/luajit2/src/lj_err.c
index 4a33a233db..42cd12b45e 100644
--- a/src/luajit2/src/lj_err.c
+++ b/src/luajit2/src/lj_err.c
@@ -385,12 +385,17 @@ typedef struct UndocumentedDispatcherContext {
   ULONG Fill0;
 } UndocumentedDispatcherContext;
 
-#ifdef _MSC_VER
 /* Another wild guess. */
-extern __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
+extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
+
+#ifdef MINGW_SDK_INIT
+/* Workaround for broken MinGW64 declaration. */
+VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
+#define RtlUnwindEx RtlUnwindEx_FIXED
 #endif
 
 #define LJ_MSVC_EXCODE		((DWORD)0xe06d7363)
+#define LJ_GCC_EXCODE		((DWORD)0x20474343)
 
 #define LJ_EXCODE		((DWORD)0xe24c4a00)
 #define LJ_EXCODE_MAKE(c)	(LJ_EXCODE | (DWORD)(c))
@@ -410,10 +415,9 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
   } else {
     void *cf2 = err_unwind(L, cf, 0);
     if (cf2) {  /* We catch it, so start unwinding the upper frames. */
-      if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
-#ifdef _MSC_VER
+      if (rec->ExceptionCode == LJ_MSVC_EXCODE ||
+	  rec->ExceptionCode == LJ_GCC_EXCODE) {
 	__DestructExceptionObject(rec, 1);
-#endif
 	setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
       } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {
 	/* Don't catch access violations etc. */
@@ -426,7 +430,7 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
       RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
 			       lj_vm_unwind_ff_eh :
 			       lj_vm_unwind_c_eh),
-		  rec, (void *)errcode, ctx, dispatch->HistoryTable);
+		  rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);
       /* RtlUnwindEx should never return. */
     }
   }
diff --git a/src/luajit2/src/lj_ffrecord.c b/src/luajit2/src/lj_ffrecord.c
index 4aa4f06498..35e2e88e31 100644
--- a/src/luajit2/src/lj_ffrecord.c
+++ b/src/luajit2/src/lj_ffrecord.c
@@ -272,7 +272,7 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
 {
   TRef tr = J->base[0];
   TRef base = J->base[1];
-  if (tr && base) {
+  if (tr && !tref_isnil(base)) {
     base = lj_opt_narrow_toint(J, base);
     if (!tref_isk(base) || IR(tref_ref(base))->i != 10)
       recff_nyiu(J);
@@ -657,7 +657,7 @@ static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
       end = argv2int(J, &rd->argv[2]);
     }
   } else {  /* string.byte(str, [,start [,end]]) */
-    if (J->base[1]) {
+    if (!tref_isnil(J->base[1])) {
       start = argv2int(J, &rd->argv[1]);
       trstart = lj_opt_narrow_toint(J, J->base[1]);
       trend = J->base[2];
@@ -750,7 +750,7 @@ static void LJ_FASTCALL recff_table_remove(jit_State *J, RecordFFData *rd)
   TRef tab = J->base[0];
   rd->nres = 0;
   if (tref_istab(tab)) {
-    if (!J->base[1] || tref_isnil(J->base[1])) {  /* Simple pop: t[#t] = nil */
+    if (tref_isnil(J->base[1])) {  /* Simple pop: t[#t] = nil */
       TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, tab);
       GCtab *t = tabV(&rd->argv[0]);
       MSize len = lj_tab_len(t);
diff --git a/src/luajit2/src/lj_mcode.c b/src/luajit2/src/lj_mcode.c
index 5f7582c483..cb79e8cdd7 100644
--- a/src/luajit2/src/lj_mcode.c
+++ b/src/luajit2/src/lj_mcode.c
@@ -206,6 +206,7 @@ static void *mcode_alloc(jit_State *J, size_t sz)
 {
   /* Target an address in the static assembler code (64K aligned).
   ** Try addresses within a distance of target-range/2+1MB..target+range/2-1MB.
+  ** Use half the jump range so every address in the range can reach any other.
   */
 #if LJ_TARGET_MIPS
   /* Use the middle of the 256MB-aligned region. */
@@ -214,7 +215,7 @@ static void *mcode_alloc(jit_State *J, size_t sz)
 #else
   uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff;
 #endif
-  const uintptr_t range = (1u << LJ_TARGET_JUMPRANGE) - (1u << 21);
+  const uintptr_t range = (1u << (LJ_TARGET_JUMPRANGE-1)) - (1u << 21);
   /* First try a contiguous area below the last one. */
   uintptr_t hint = J->mcarea ? (uintptr_t)J->mcarea - sz : 0;
   int i;
diff --git a/src/luajit2/src/lj_opt_fold.c b/src/luajit2/src/lj_opt_fold.c
index be50bf9784..fe37b98a88 100644
--- a/src/luajit2/src/lj_opt_fold.c
+++ b/src/luajit2/src/lj_opt_fold.c
@@ -1819,6 +1819,7 @@ LJFOLDF(merge_eqne_snew_kgc)
 #define FOLD_SNEW_TYPE8		IRT_U8  /* Prefer unsigned loads. */
 #endif
 
+  PHIBARRIER(fleft);
   if (len <= FOLD_SNEW_MAX_LEN) {
     IROp op = (IROp)fins->o;
     IRRef strref = fleft->op1;
@@ -2179,14 +2180,16 @@ TRef LJ_FASTCALL lj_opt_fold(jit_State *J)
     if (!(J->flags & JIT_F_OPT_FOLD) && irm_kind(lj_ir_mode[fins->o]) == IRM_N)
       return lj_opt_cse(J);
 
-    /* Forwarding or CSE disabled? Emit raw IR for loads, except for SLOAD. */
-    if ((J->flags & (JIT_F_OPT_FWD|JIT_F_OPT_CSE)) !=
-		    (JIT_F_OPT_FWD|JIT_F_OPT_CSE) &&
+    /* No FOLD, forwarding or CSE? Emit raw IR for loads, except for SLOAD. */
+    if ((J->flags & (JIT_F_OPT_FOLD|JIT_F_OPT_FWD|JIT_F_OPT_CSE)) !=
+		    (JIT_F_OPT_FOLD|JIT_F_OPT_FWD|JIT_F_OPT_CSE) &&
 	irm_kind(lj_ir_mode[fins->o]) == IRM_L && fins->o != IR_SLOAD)
       return lj_ir_emit(J);
 
-    /* DSE disabled? Emit raw IR for stores. */
-    if (!(J->flags & JIT_F_OPT_DSE) && irm_kind(lj_ir_mode[fins->o]) == IRM_S)
+    /* No FOLD or DSE? Emit raw IR for stores. */
+    if ((J->flags & (JIT_F_OPT_FOLD|JIT_F_OPT_DSE)) !=
+		    (JIT_F_OPT_FOLD|JIT_F_OPT_DSE) &&
+	irm_kind(lj_ir_mode[fins->o]) == IRM_S)
       return lj_ir_emit(J);
   }
 
diff --git a/src/luajit2/src/lj_opt_mem.c b/src/luajit2/src/lj_opt_mem.c
index bf77666b1b..98974ce33c 100644
--- a/src/luajit2/src/lj_opt_mem.c
+++ b/src/luajit2/src/lj_opt_mem.c
@@ -347,7 +347,7 @@ TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J)
 	IRIns *ir;
 	/* Check for any intervening guards (includes conflicting loads). */
 	for (ir = IR(J->cur.nins-1); ir > store; ir--)
-	  if (irt_isguard(ir->t))
+	  if (irt_isguard(ir->t) || ir->o == IR_CALLL)
 	    goto doemit;  /* No elimination possible. */
 	/* Remove redundant store from chain and replace with NOP. */
 	*refp = store->prev;
diff --git a/src/luajit2/src/lj_opt_split.c b/src/luajit2/src/lj_opt_split.c
index 303af03c68..5a8c33b949 100644
--- a/src/luajit2/src/lj_opt_split.c
+++ b/src/luajit2/src/lj_opt_split.c
@@ -195,6 +195,19 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref)
   return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs));
 }
 
+/* Substitute references of a snapshot. */
+static void split_subst_snap(jit_State *J, SnapShot *snap, IRIns *oir)
+{
+  SnapEntry *map = &J->cur.snapmap[snap->mapofs];
+  MSize n, nent = snap->nent;
+  for (n = 0; n < nent; n++) {
+    SnapEntry sn = map[n];
+    IRIns *ir = &oir[snap_ref(sn)];
+    if (!(LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && irref_isk(snap_ref(sn))))
+      map[n] = ((sn & 0xffff0000) | ir->prev);
+  }
+}
+
 /* Transform the old IR to the new IR. */
 static void split_ir(jit_State *J)
 {
@@ -203,7 +216,8 @@ static void split_ir(jit_State *J)
   MSize need = (irlen+1)*(sizeof(IRIns) + sizeof(IRRef1));
   IRIns *oir = (IRIns *)lj_str_needbuf(J->L, &G(J->L)->tmpbuf, need);
   IRRef1 *hisubst;
-  IRRef ref;
+  IRRef ref, snref;
+  SnapShot *snap;
 
   /* Copy old IR to buffer. */
   memcpy(oir, IR(nk), irlen*sizeof(IRIns));
@@ -230,12 +244,20 @@ static void split_ir(jit_State *J)
   }
 
   /* Process old IR instructions. */
+  snap = J->cur.snap;
+  snref = snap->ref;
   for (ref = REF_FIRST; ref < nins; ref++) {
     IRIns *ir = &oir[ref];
     IRRef nref = lj_ir_nextins(J);
     IRIns *nir = IR(nref);
     IRRef hi = 0;
 
+    if (ref >= snref) {
+      snap->ref = nref;
+      split_subst_snap(J, snap++, oir);
+      snref = snap < &J->cur.snap[J->cur.nsnap] ? snap->ref : ~(IRRef)0;
+    }
+
     /* Copy-substitute old instruction to new instruction. */
     nir->op1 = ir->op1 < nk ? ir->op1 : oir[ir->op1].prev;
     nir->op2 = ir->op2 < nk ? ir->op2 : oir[ir->op2].prev;
@@ -635,6 +657,10 @@ static void split_ir(jit_State *J)
     }
     hisubst[ref] = hi;  /* Store hiword substitution. */
   }
+  if (snref == nins) {  /* Substitution for last snapshot. */
+    snap->ref = J->cur.nins;
+    split_subst_snap(J, snap, oir);
+  }
 
   /* Add PHI marks. */
   for (ref = J->cur.nins-1; ref >= REF_FIRST; ref--) {
@@ -643,24 +669,6 @@ static void split_ir(jit_State *J)
     if (!irref_isk(ir->op1)) irt_setphi(IR(ir->op1)->t);
     if (ir->op2 > J->loopref) irt_setphi(IR(ir->op2)->t);
   }
-
-  /* Substitute snapshot maps. */
-  oir[nins].prev = J->cur.nins;  /* Substitution for last snapshot. */
-  {
-    SnapNo i, nsnap = J->cur.nsnap;
-    for (i = 0; i < nsnap; i++) {
-      SnapShot *snap = &J->cur.snap[i];
-      SnapEntry *map = &J->cur.snapmap[snap->mapofs];
-      MSize n, nent = snap->nent;
-      snap->ref = snap->ref == REF_FIRST ? REF_FIRST : oir[snap->ref].prev;
-      for (n = 0; n < nent; n++) {
-	SnapEntry sn = map[n];
-	IRIns *ir = &oir[snap_ref(sn)];
-	if (!(LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && irref_isk(snap_ref(sn))))
-	  map[n] = ((sn & 0xffff0000) | ir->prev);
-      }
-    }
-  }
 }
 
 /* Protected callback for split pass. */
diff --git a/src/luajit2/src/lj_record.c b/src/luajit2/src/lj_record.c
index 7336e0ac14..01a8eee832 100644
--- a/src/luajit2/src/lj_record.c
+++ b/src/luajit2/src/lj_record.c
@@ -696,17 +696,6 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
     J->base[--rbase] = TREF_TRUE;  /* Prepend true to results. */
     frame = frame_prevd(frame);
   }
-  /* Return to lower frame via interpreter for unhandled cases. */
-  if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) &&
-       (!frame_islua(frame) ||
-	(J->parent == 0 && !bc_isret(bc_op(J->cur.startins))))) {
-    /* NYI: specialize to frame type and return directly, not via RET*. */
-    for (i = -1; i < (ptrdiff_t)rbase; i++)
-      J->base[i] = 0;  /* Purge dead slots. */
-    J->maxslot = rbase + (BCReg)gotresults;
-    rec_stop(J, LJ_TRLINK_RETURN, 0);  /* Return to interpreter. */
-    return;
-  }
   if (frame_isvarg(frame)) {
     BCReg cbase = (BCReg)frame_delta(frame);
     if (--J->framedepth < 0)  /* NYI: return of vararg func to lower frame. */
@@ -1379,7 +1368,7 @@ noconstify:
 /* -- Record calls to Lua functions --------------------------------------- */
 
 /* Check unroll limits for calls. */
-static void check_call_unroll(jit_State *J, TraceNo lnk)
+static void check_call_unroll(jit_State *J)
 {
   cTValue *frame = J->L->base - 1;
   void *pc = mref(frame_func(frame)->l.pc, void);
@@ -1400,14 +1389,8 @@ static void check_call_unroll(jit_State *J, TraceNo lnk)
 	rec_stop(J, LJ_TRLINK_UPREC, J->cur.traceno);  /* Up-recursion. */
     }
   } else {
-    if (count > J->param[JIT_P_callunroll]) {
-      if (lnk) {  /* Possible tail- or up-recursion. */
-	lj_trace_flush(J, lnk);  /* Flush trace that only returns. */
-	/* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */
-	hotcount_set(J2GG(J), J->pc+1, LJ_PRNG_BITS(J, 4));
-      }
+    if (count > J->param[JIT_P_callunroll])
       lj_trace_err(J, LJ_TRERR_CUNROLL);
-    }
   }
 }
 
@@ -1452,23 +1435,13 @@ static void rec_func_vararg(jit_State *J)
 static void rec_func_lua(jit_State *J)
 {
   rec_func_setup(J);
-  check_call_unroll(J, 0);
+  check_call_unroll(J);
 }
 
 /* Record entry to an already compiled function. */
 static void rec_func_jit(jit_State *J, TraceNo lnk)
 {
-  GCtrace *T;
   rec_func_setup(J);
-  T = traceref(J, lnk);
-  if (T->linktype == LJ_TRLINK_RETURN) {  /* Trace returns to interpreter? */
-    check_call_unroll(J, lnk);
-    /* Temporarily unpatch JFUNC* to continue recording across function. */
-    J->patchins = *J->pc;
-    J->patchpc = (BCIns *)J->pc;
-    *J->patchpc = T->startins;
-    return;
-  }
   J->instunroll = 0;  /* Cannot continue across a compiled function. */
   if (J->pc == J->startpc && J->framedepth + J->retdepth == 0)
     rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno);  /* Extra tail-recursion. */
diff --git a/src/luajit2/src/lj_snap.c b/src/luajit2/src/lj_snap.c
index aea6102c4c..30ff915289 100644
--- a/src/luajit2/src/lj_snap.c
+++ b/src/luajit2/src/lj_snap.c
@@ -564,6 +564,8 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
 		continue;
 	      }
 	      tmp = emitir(irs->ot, tmp, val);
+	    } else if (LJ_HASFFI && irs->o == IR_XBAR && ir->o == IR_CNEW) {
+	      emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
 	    }
 	}
       }
diff --git a/src/luajit2/src/lj_str.c b/src/luajit2/src/lj_str.c
index e63d86282c..6548ee4d38 100644
--- a/src/luajit2/src/lj_str.c
+++ b/src/luajit2/src/lj_str.c
@@ -48,7 +48,7 @@ static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
 {
   MSize i = 0;
   lua_assert(len > 0);
-  lua_assert((((uintptr_t)a + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4);
+  lua_assert((((uintptr_t)a+len-1) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4);
   do {  /* Note: innocuous access up to end of string + 3. */
     uint32_t v = lj_getu32(a+i) ^ *(const uint32_t *)(b+i);
     if (v) {
@@ -121,7 +121,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
   h ^= b; h -= lj_rol(b, 16);
   /* Check if the string has already been interned. */
   o = gcref(g->strhash[h & g->strmask]);
-  if (LJ_LIKELY((((uintptr_t)str + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4)) {
+  if (LJ_LIKELY((((uintptr_t)str+len-1) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4)) {
     while (o != NULL) {
       GCstr *sx = gco2str(o);
       if (sx->len == len && str_fastcmp(str, strdata(sx), len) == 0) {
diff --git a/src/luajit2/src/lj_strscan.c b/src/luajit2/src/lj_strscan.c
index 8d41a3e20c..a71b86a283 100644
--- a/src/luajit2/src/lj_strscan.c
+++ b/src/luajit2/src/lj_strscan.c
@@ -187,7 +187,7 @@ static StrScanFmt strscan_dec(const uint8_t *p, TValue *o,
   if (dig) {
     uint32_t i = dig;
     if (i > STRSCAN_MAXDIG) {
-      ex10 -= (int32_t)(i - STRSCAN_MAXDIG);
+      ex10 += (int32_t)(i - STRSCAN_MAXDIG);
       i = STRSCAN_MAXDIG;
     }
     /* Scan unaligned leading digit. */
@@ -280,9 +280,10 @@ static StrScanFmt strscan_dec(const uint8_t *p, TValue *o,
 	if (d == 0 && i == DPREV(lo)) lo = i;
       }
       if (cy) {
+	hi = DPREV(hi);
 	if (xi[DPREV(lo)] == 0) lo = DPREV(lo);
 	else if (hi == lo) { lo = DPREV(lo); xi[DPREV(lo)] |= xi[lo]; }
-	hi = DPREV(hi); xi[hi] = (uint8_t)cy; idig++;
+	xi[hi] = (uint8_t)cy; idig++;
       }
     }
 
diff --git a/src/luajit2/src/luaconf.h b/src/luajit2/src/luaconf.h
index 58919676fd..d55caab1d0 100644
--- a/src/luajit2/src/luaconf.h
+++ b/src/luajit2/src/luaconf.h
@@ -30,12 +30,12 @@
 #define LUA_LDIR	LUA_ROOT "share/lua/5.1/"
 #define LUA_CDIR	LUA_ROOT "lib/lua/5.1/"
 #ifdef LUA_XROOT
-#define LUA_JDIR	LUA_XROOT "share/luajit-2.0.1/"
+#define LUA_JDIR	LUA_XROOT "share/luajit-2.0.2/"
 #define LUA_XPATH \
   ";" LUA_XROOT "share/lua/5.1/?.lua;" LUA_XROOT "share/lua/5.1/?/init.lua"
 #define LUA_XCPATH	LUA_XROOT "lib/lua/5.1/?.so;"
 #else
-#define LUA_JDIR	LUA_ROOT "share/luajit-2.0.1/"
+#define LUA_JDIR	LUA_ROOT "share/luajit-2.0.2/"
 #define LUA_XPATH
 #define LUA_XCPATH
 #endif
@@ -51,7 +51,11 @@
 #define LUA_INIT	"LUA_INIT"
 
 /* Special file system characters. */
+#if defined(_WIN32)
+#define LUA_DIRSEP	"\\"
+#else
 #define LUA_DIRSEP	"/"
+#endif
 #define LUA_PATHSEP	";"
 #define LUA_PATH_MARK	"?"
 #define LUA_EXECDIR	"!"
diff --git a/src/luajit2/src/luajit.c b/src/luajit2/src/luajit.c
index 37b0deb3cf..e0eacc423a 100644
--- a/src/luajit2/src/luajit.c
+++ b/src/luajit2/src/luajit.c
@@ -499,15 +499,15 @@ static int handle_luainit(lua_State *L)
     return dostring(L, init, "=" LUA_INIT);
 }
 
-struct Smain {
+static struct Smain {
   char **argv;
   int argc;
   int status;
-};
+} smain;
 
 static int pmain(lua_State *L)
 {
-  struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
+  struct Smain *s = &smain;
   char **argv = s->argv;
   int script;
   int flags = 0;
@@ -556,17 +556,16 @@ static int pmain(lua_State *L)
 int main(int argc, char **argv)
 {
   int status;
-  struct Smain s;
   lua_State *L = lua_open();  /* create state */
   if (L == NULL) {
     l_message(argv[0], "cannot create state: not enough memory");
     return EXIT_FAILURE;
   }
-  s.argc = argc;
-  s.argv = argv;
-  status = lua_cpcall(L, pmain, &s);
+  smain.argc = argc;
+  smain.argv = argv;
+  status = lua_cpcall(L, pmain, NULL);
   report(L, status);
   lua_close(L);
-  return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
+  return (status || smain.status) ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
diff --git a/src/luajit2/src/luajit.h b/src/luajit2/src/luajit.h
index ed39d014d5..f33b64c566 100644
--- a/src/luajit2/src/luajit.h
+++ b/src/luajit2/src/luajit.h
@@ -30,9 +30,9 @@
 
 #include "lua.h"
 
-#define LUAJIT_VERSION		"LuaJIT 2.0.1"
-#define LUAJIT_VERSION_NUM	20001  /* Version 2.0.1 = 02.00.01. */
-#define LUAJIT_VERSION_SYM	luaJIT_version_2_0_1
+#define LUAJIT_VERSION		"LuaJIT 2.0.2"
+#define LUAJIT_VERSION_NUM	20002  /* Version 2.0.2 = 02.00.02. */
+#define LUAJIT_VERSION_SYM	luaJIT_version_2_0_2
 #define LUAJIT_COPYRIGHT	"Copyright (C) 2005-2013 Mike Pall"
 #define LUAJIT_URL		"http://luajit.org/"
 
diff --git a/src/luajit2/src/vm_ppc.dasc b/src/luajit2/src/vm_ppc.dasc
index 685ea5180b..f253081100 100644
--- a/src/luajit2/src/vm_ppc.dasc
+++ b/src/luajit2/src/vm_ppc.dasc
@@ -49,7 +49,7 @@
 |// Convenience macros for TOC handling.
 |.if TOC
 |// Linker needs a TOC patch area for every external call relocation.
-|.macro blex, target; bl extern target; nop; .endmacro
+|.macro blex, target; bl extern target@plt; nop; .endmacro
 |.macro .toc, a, b; a, b; .endmacro
 |.if P64
 |.define TOC_OFS,	 8
@@ -59,7 +59,7 @@
 |.define ENV_OFS,	8
 |.endif
 |.else  // No TOC.
-|.macro blex, target; bl extern target; .endmacro
+|.macro blex, target; bl extern target@plt; .endmacro
 |.macro .toc, a, b; .endmacro
 |.endif
 |.macro .tocenv, a, b; .if TOCENV; a, b; .endif; .endmacro
diff --git a/src/luajit2/src/vm_ppcspe.dasc b/src/luajit2/src/vm_ppcspe.dasc
index 4fabc02f10..293e391913 100644
--- a/src/luajit2/src/vm_ppcspe.dasc
+++ b/src/luajit2/src/vm_ppcspe.dasc
@@ -1390,7 +1390,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checknum CARG2
   |   evmergehi CARG1, CARG2, CARG2
   |  checkfail ->fff_fallback
-  |  bl extern func
+  |  bl extern func@plt
   |  evmergelo CRET1, CRET1, CRET2
   |  b ->fff_restv
   |.endmacro
@@ -1405,7 +1405,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checknum CARG1
   |   evmergehi CARG3, CARG4, CARG4
   |  checkanyfail ->fff_fallback
-  |  bl extern func
+  |  bl extern func@plt
   |  evmergelo CRET1, CRET1, CRET2
   |  b ->fff_restv
   |.endmacro
@@ -1437,7 +1437,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checknum CARG2
   |   evmergehi CARG1, CARG2, CARG2
   |  checkfail ->fff_fallback
-  |  bl extern log
+  |  bl extern log@plt
   |  evmergelo CRET1, CRET1, CRET2
   |  b ->fff_restv
   |
@@ -1471,7 +1471,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checknum CARG1
   |  checkanyfail ->fff_fallback
   |  efdctsi CARG3, CARG4
-  |  bl extern ldexp
+  |  bl extern ldexp@plt
   |  evmergelo CRET1, CRET1, CRET2
   |  b ->fff_restv
   |
@@ -1484,7 +1484,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checkfail ->fff_fallback
   |  la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
   |   lwz PC, FRAME_PC(BASE)
-  |  bl extern frexp
+  |  bl extern frexp@plt
   |   lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH)
   |  evmergelo CRET1, CRET1, CRET2
   |   efdcfsi CRET2, TMP1
@@ -1503,7 +1503,7 @@ static void build_subroutines(BuildCtx *ctx)
   |  checkfail ->fff_fallback
   |  la CARG3, -8(BASE)
   |   lwz PC, FRAME_PC(BASE)
-  |  bl extern modf
+  |  bl extern modf@plt
   |  evmergelo CRET1, CRET1, CRET2
   |   la RA, -8(BASE)
   |  evstdd CRET1, 0(BASE)
@@ -2399,7 +2399,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  checknum CARG1
     |   evmergehi CARG3, CARG4, CARG4
     |  checkanyfail ->vmeta_arith_vv
-    |  bl extern pow
+    |  bl extern pow@plt
     |  evmergelo CRET2, CRET1, CRET2
     |  evstddx CRET2, BASE, RA
     |  ins_next
diff --git a/src/luajit2/src/vm_x86.dasc b/src/luajit2/src/vm_x86.dasc
index b4674e2ba5..f25dfd302b 100644
--- a/src/luajit2/src/vm_x86.dasc
+++ b/src/luajit2/src/vm_x86.dasc
@@ -6152,7 +6152,11 @@ static void emit_asm_debug(BuildCtx *ctx)
 	".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
 #endif
 #if (defined(__sun__) && defined(__svr4__))
+#if LJ_64
+    fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@unwind\n");
+#else
     fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n");
+#endif
 #else
     fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
 #endif
-- 
GitLab