Blame SOURCES/luajit-openresty-features.patch

006bc1
From a6879cb3982f02744dd77b6663ae6bc14162e652 Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <agentzh@gmail.com>
006bc1
Date: Sat, 19 Dec 2015 10:43:32 -0800
006bc1
Subject: [PATCH 02/13] Makefile: ensure we always install the symlink for
006bc1
 "luajit".
006bc1
006bc1
---
006bc1
 Makefile | 7 +------
006bc1
 1 file changed, 1 insertion(+), 6 deletions(-)
006bc1
006bc1
diff --git a/Makefile b/Makefile
006bc1
index 923bf72b..f4b84081 100644
006bc1
--- a/Makefile
006bc1
+++ b/Makefile
006bc1
@@ -130,13 +130,8 @@ install: $(LUAJIT_BIN)
006bc1
 	  $(RM) $(FILE_PC).tmp
006bc1
 	cd src && $(INSTALL_F) $(FILES_INC) $(INSTALL_INC)
006bc1
 	cd src/jit && $(INSTALL_F) $(FILES_JITLIB) $(INSTALL_JITLIB)
006bc1
+	$(SYMLINK) $(INSTALL_TNAME) $(INSTALL_TSYM)
006bc1
 	@echo "==== Successfully installed LuaJIT $(VERSION) to $(PREFIX) ===="
006bc1
-	@echo ""
006bc1
-	@echo "Note: the development releases deliberately do NOT install a symlink for luajit"
006bc1
-	@echo "You can do this now by running this command (with sudo):"
006bc1
-	@echo ""
006bc1
-	@echo "  $(SYMLINK) $(INSTALL_TNAME) $(INSTALL_TSYM)"
006bc1
-	@echo ""
006bc1
 
006bc1
 
006bc1
 uninstall:
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From e29e78dd64573947777e8ca7741d46d1c0ba2f7b Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <agentzh@gmail.com>
006bc1
Date: Tue, 14 Mar 2017 14:26:48 -0700
006bc1
Subject: [PATCH 03/13] optimize: lj_str_new: tests the full hash value before
006bc1
 doing the full string comparison on hash collisions. thanks Shuxin Yang for
006bc1
 the patch.
006bc1
006bc1
---
006bc1
 src/lj_str.c | 4 ++--
006bc1
 1 file changed, 2 insertions(+), 2 deletions(-)
006bc1
006bc1
diff --git a/src/lj_str.c b/src/lj_str.c
006bc1
index 264dedc1..f1b5fb5d 100644
006bc1
--- a/src/lj_str.c
006bc1
+++ b/src/lj_str.c
006bc1
@@ -152,7 +152,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
006bc1
   if (LJ_LIKELY((((uintptr_t)str+len-1) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4)) {
006bc1
     while (o != NULL) {
006bc1
       GCstr *sx = gco2str(o);
006bc1
-      if (sx->len == len && str_fastcmp(str, strdata(sx), len) == 0) {
006bc1
+      if (sx->len == len && sx->hash == h && str_fastcmp(str, strdata(sx), len) == 0) {
006bc1
 	/* Resurrect if dead. Can only happen with fixstring() (keywords). */
006bc1
 	if (isdead(g, o)) flipwhite(o);
006bc1
 	return sx;  /* Return existing string. */
006bc1
@@ -162,7 +162,7 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
006bc1
   } else {  /* Slow path: end of string is too close to a page boundary. */
006bc1
     while (o != NULL) {
006bc1
       GCstr *sx = gco2str(o);
006bc1
-      if (sx->len == len && memcmp(str, strdata(sx), len) == 0) {
006bc1
+      if (sx->len == len && sx->hash == h && memcmp(str, strdata(sx), len) == 0) {
006bc1
 	/* Resurrect if dead. Can only happen with fixstring() (keywords). */
006bc1
 	if (isdead(g, o)) flipwhite(o);
006bc1
 	return sx;  /* Return existing string. */
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From 555ee4e814f799937ca505423fc05c0b0402f81c Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <yichun@openresty.com>
006bc1
Date: Tue, 15 Jan 2019 12:17:50 -0800
006bc1
Subject: [PATCH 04/13] bugfix: fixed assertion failure "lj_record.c:92:
006bc1
 rec_check_slots: Assertion `nslots <= 250' failed" found by stressing our
006bc1
 edgelang compiler.
006bc1
006bc1
---
006bc1
 src/lj_record.c | 2 ++
006bc1
 1 file changed, 2 insertions(+)
006bc1
006bc1
diff --git a/src/lj_record.c b/src/lj_record.c
006bc1
index 7f37d6c6..4a50de1b 100644
006bc1
--- a/src/lj_record.c
006bc1
+++ b/src/lj_record.c
006bc1
@@ -1860,6 +1860,8 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
006bc1
       lj_trace_err_info(J, LJ_TRERR_NYIBC);
006bc1
     }
006bc1
   }
006bc1
+  if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS)
006bc1
+    lj_trace_err(J, LJ_TRERR_STACKOV);
006bc1
 }
006bc1
 
006bc1
 /* -- Record allocations -------------------------------------------------- */
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From 58e9941b6268202f7953a5534e0c662ad90b2510 Mon Sep 17 00:00:00 2001
006bc1
From: doujiang24 <doujiang24@gmail.com>
006bc1
Date: Sun, 12 Mar 2017 21:04:50 +0800
006bc1
Subject: [PATCH 05/13] feature: added the bytecode option `L` to display lua
006bc1
 source line numbers.
006bc1
006bc1
Signed-off-by: Yichun Zhang (agentzh) <agentzh@gmail.com>
006bc1
---
006bc1
 src/jit/bc.lua     | 20 +++++++++++++-------
006bc1
 src/jit/bcsave.lua | 11 ++++++++---
006bc1
 src/lib_jit.c      |  6 ++++++
006bc1
 3 files changed, 27 insertions(+), 10 deletions(-)
006bc1
006bc1
diff --git a/src/jit/bc.lua b/src/jit/bc.lua
006bc1
index 193cf01f..80f92689 100644
006bc1
--- a/src/jit/bc.lua
006bc1
+++ b/src/jit/bc.lua
006bc1
@@ -63,15 +63,21 @@ local function ctlsub(c)
006bc1
 end
006bc1
 
006bc1
 -- Return one bytecode line.
006bc1
-local function bcline(func, pc, prefix)
006bc1
-  local ins, m = funcbc(func, pc)
006bc1
+local function bcline(func, pc, prefix, lineinfo)
006bc1
+  local ins, m, l = funcbc(func, pc, lineinfo and 1 or 0)
006bc1
   if not ins then return end
006bc1
   local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128)
006bc1
   local a = band(shr(ins, 8), 0xff)
006bc1
   local oidx = 6*band(ins, 0xff)
006bc1
   local op = sub(bcnames, oidx+1, oidx+6)
006bc1
-  local s = format("%04d %s %-6s %3s ",
006bc1
-    pc, prefix or "  ", op, ma == 0 and "" or a)
006bc1
+  local s
006bc1
+  if lineinfo then
006bc1
+    s = format("%04d %7s %s %-6s %3s ",
006bc1
+      pc, "["..l.."]", prefix or "  ", op, ma == 0 and "" or a)
006bc1
+  else
006bc1
+    s = format("%04d %s %-6s %3s ",
006bc1
+      pc, prefix or "  ", op, ma == 0 and "" or a)
006bc1
+  end
006bc1
   local d = shr(ins, 16)
006bc1
   if mc == 13*128 then -- BCMjump
006bc1
     return format("%s=> %04d\n", s, pc+d-0x7fff)
006bc1
@@ -124,20 +130,20 @@ local function bctargets(func)
006bc1
 end
006bc1
 
006bc1
 -- Dump bytecode instructions of a function.
006bc1
-local function bcdump(func, out, all)
006bc1
+local function bcdump(func, out, all, lineinfo)
006bc1
   if not out then out = stdout end
006bc1
   local fi = funcinfo(func)
006bc1
   if all and fi.children then
006bc1
     for n=-1,-1000000000,-1 do
006bc1
       local k = funck(func, n)
006bc1
       if not k then break end
006bc1
-      if type(k) == "proto" then bcdump(k, out, true) end
006bc1
+      if type(k) == "proto" then bcdump(k, out, true, lineinfo) end
006bc1
     end
006bc1
   end
006bc1
   out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined))
006bc1
   local target = bctargets(func)
006bc1
   for pc=1,1000000000 do
006bc1
-    local s = bcline(func, pc, target[pc] and "=>")
006bc1
+    local s = bcline(func, pc, target[pc] and "=>", lineinfo)
006bc1
     if not s then break end
006bc1
     out:write(s)
006bc1
   end
006bc1
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua
006bc1
index 2553d97e..9c6146c2 100644
006bc1
--- a/src/jit/bcsave.lua
006bc1
+++ b/src/jit/bcsave.lua
006bc1
@@ -23,6 +23,7 @@ local function usage()
006bc1
   io.stderr:write[[
006bc1
 Save LuaJIT bytecode: luajit -b[options] input output
006bc1
   -l        Only list bytecode.
006bc1
+  -L        Only list bytecode with lineinfo.
006bc1
   -s        Strip debug info (default).
006bc1
   -g        Keep debug info.
006bc1
   -n name   Set module name (default: auto-detect from input name).
006bc1
@@ -575,9 +576,9 @@ end
006bc1
 
006bc1
 ------------------------------------------------------------------------------
006bc1
 
006bc1
-local function bclist(input, output)
006bc1
+local function bclist(input, output, lineinfo)
006bc1
   local f = readfile(input)
006bc1
-  require("jit.bc").dump(f, savefile(output, "w"), true)
006bc1
+  require("jit.bc").dump(f, savefile(output, "w"), true, lineinfo)
006bc1
 end
006bc1
 
006bc1
 local function bcsave(ctx, input, output)
006bc1
@@ -604,6 +605,7 @@ local function docmd(...)
006bc1
   local arg = {...}
006bc1
   local n = 1
006bc1
   local list = false
006bc1
+  local lineinfo = false
006bc1
   local ctx = {
006bc1
     strip = true, arch = jit.arch, os = string.lower(jit.os),
006bc1
     type = false, modname = false,
006bc1
@@ -617,6 +619,9 @@ local function docmd(...)
006bc1
 	local opt = string.sub(a, m, m)
006bc1
 	if opt == "l" then
006bc1
 	  list = true
006bc1
+	elseif opt == "L" then
006bc1
+	  list = true
006bc1
+	  lineinfo = true
006bc1
 	elseif opt == "s" then
006bc1
 	  ctx.strip = true
006bc1
 	elseif opt == "g" then
006bc1
@@ -645,7 +650,7 @@ local function docmd(...)
006bc1
   end
006bc1
   if list then
006bc1
     if #arg == 0 or #arg > 2 then usage() end
006bc1
-    bclist(arg[1], arg[2] or "-")
006bc1
+    bclist(arg[1], arg[2] or "-", lineinfo)
006bc1
   else
006bc1
     if #arg ~= 2 then usage() end
006bc1
     bcsave(ctx, arg[1], arg[2])
006bc1
diff --git a/src/lib_jit.c b/src/lib_jit.c
006bc1
index 6e265fdb..6972550b 100644
006bc1
--- a/src/lib_jit.c
006bc1
+++ b/src/lib_jit.c
006bc1
@@ -224,6 +224,7 @@ LJLIB_CF(jit_util_funcbc)
006bc1
 {
006bc1
   GCproto *pt = check_Lproto(L, 0);
006bc1
   BCPos pc = (BCPos)lj_lib_checkint(L, 2);
006bc1
+  int lineinfo = lj_lib_optint(L, 3, 0);
006bc1
   if (pc < pt->sizebc) {
006bc1
     BCIns ins = proto_bc(pt)[pc];
006bc1
     BCOp op = bc_op(ins);
006bc1
@@ -231,6 +232,11 @@ LJLIB_CF(jit_util_funcbc)
006bc1
     setintV(L->top, ins);
006bc1
     setintV(L->top+1, lj_bc_mode[op]);
006bc1
     L->top += 2;
006bc1
+    if (lineinfo) {
006bc1
+      setintV(L->top, lj_debug_line(pt, pc));
006bc1
+      L->top += 1;
006bc1
+      return 3;
006bc1
+    }
006bc1
     return 2;
006bc1
   }
006bc1
   return 0;
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From a61c93d0784c532db4ec0797475a0e0ad93dda4c Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <yichun@openresty.com>
006bc1
Date: Wed, 27 Feb 2019 17:20:19 -0800
006bc1
Subject: [PATCH 06/13] bugfix: ffi.C.FUNC(): it lacked a write barrier which
006bc1
 might lead to use-after-free issues and memory corruptions.
006bc1
006bc1
Fix #42.
006bc1
---
006bc1
 src/lj_clib.c | 1 +
006bc1
 1 file changed, 1 insertion(+)
006bc1
006bc1
diff --git a/src/lj_clib.c b/src/lj_clib.c
006bc1
index f016b06b..a8672052 100644
006bc1
--- a/src/lj_clib.c
006bc1
+++ b/src/lj_clib.c
006bc1
@@ -384,6 +384,7 @@ TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name)
006bc1
       cd = lj_cdata_new(cts, id, CTSIZE_PTR);
006bc1
       *(void **)cdataptr(cd) = p;
006bc1
       setcdataV(L, tv, cd);
006bc1
+      lj_gc_anybarriert(L, cl->cache);
006bc1
     }
006bc1
   }
006bc1
   return tv;
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From 3086b483e76ad12ae0a0dfab60960c1175b69dab Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <agentzh@gmail.com>
006bc1
Date: Thu, 15 May 2014 16:03:29 -0700
006bc1
Subject: [PATCH 07/13] feature: added internal memory-buffer-based trace
006bc1
 entry/exit/start-recording event logging, mainly for debugging bugs in the
006bc1
 JIT compiler. it requires -DLUA_USE_TRACE_LOGS when building.
006bc1
006bc1
---
006bc1
 src/lj_debug.c  | 125 ++++++++++++++++++++++++++++++++++++++++++++++++
006bc1
 src/lj_debug.h  |  11 +++++
006bc1
 src/lj_trace.c  |   9 ++++
006bc1
 src/vm_x86.dasc |  24 ++++++++++
006bc1
 4 files changed, 169 insertions(+)
006bc1
006bc1
diff --git a/src/lj_debug.c b/src/lj_debug.c
006bc1
index 959dc289..7f4f793a 100644
006bc1
--- a/src/lj_debug.c
006bc1
+++ b/src/lj_debug.c
006bc1
@@ -697,3 +697,128 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
006bc1
   lua_concat(L, (int)(L->top - L->base) - top);
006bc1
 }
006bc1
 
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+
006bc1
+#include "lj_dispatch.h"
006bc1
+
006bc1
+#define MAX_TRACE_EVENTS  64
006bc1
+
006bc1
+enum {
006bc1
+    LJ_TRACE_EVENT_ENTER,
006bc1
+    LJ_TRACE_EVENT_EXIT,
006bc1
+    LJ_TRACE_EVENT_START
006bc1
+};
006bc1
+
006bc1
+typedef struct {
006bc1
+    int              event;
006bc1
+    unsigned         traceno;
006bc1
+    unsigned         exitno;
006bc1
+    int              directexit;
006bc1
+    const BCIns     *ins;
006bc1
+    lua_State       *thread;
006bc1
+    GCfunc          *fn;
006bc1
+} lj_trace_event_record_t;
006bc1
+
006bc1
+static lj_trace_event_record_t lj_trace_events[MAX_TRACE_EVENTS];
006bc1
+
006bc1
+static int  rb_start = 0;
006bc1
+static int  rb_end = 0;
006bc1
+static int  rb_full = 0;
006bc1
+
006bc1
+static void
006bc1
+lj_trace_log_event(lj_trace_event_record_t *rec)
006bc1
+{
006bc1
+  lj_trace_events[rb_end] = *rec;
006bc1
+
006bc1
+  if (rb_full) {
006bc1
+    rb_end++;
006bc1
+    if (rb_end == MAX_TRACE_EVENTS) {
006bc1
+      rb_end = 0;
006bc1
+    }
006bc1
+    rb_start = rb_end;
006bc1
+
006bc1
+  } else {
006bc1
+    rb_end++;
006bc1
+    if (rb_end == MAX_TRACE_EVENTS) {
006bc1
+      rb_end = 0;
006bc1
+      rb_full = MAX_TRACE_EVENTS;
006bc1
+    }
006bc1
+  }
006bc1
+}
006bc1
+
006bc1
+static GCfunc*
006bc1
+lj_debug_top_frame_fn(lua_State *L, const BCIns *pc)
006bc1
+{
006bc1
+  int size;
006bc1
+  cTValue *frame;
006bc1
+
006bc1
+  frame = lj_debug_frame(L, 0, &size);
006bc1
+  if (frame == NULL) {
006bc1
+    return NULL;
006bc1
+  }
006bc1
+
006bc1
+  return frame_func(frame);
006bc1
+}
006bc1
+
006bc1
+void
006bc1
+lj_log_trace_start_record(lua_State *L, unsigned traceno, const BCIns *pc,
006bc1
+  GCfunc *fn)
006bc1
+{
006bc1
+  lj_trace_event_record_t  r;
006bc1
+
006bc1
+  r.event = LJ_TRACE_EVENT_START;
006bc1
+  r.thread = L;
006bc1
+  r.ins = pc;
006bc1
+  r.traceno = traceno;
006bc1
+  r.fn = fn;
006bc1
+
006bc1
+  lj_trace_log_event(&r);
006bc1
+}
006bc1
+
006bc1
+void
006bc1
+lj_log_trace_entry(lua_State *L, unsigned traceno, const BCIns *pc)
006bc1
+{
006bc1
+  lj_trace_event_record_t  r;
006bc1
+
006bc1
+  r.event = LJ_TRACE_EVENT_ENTER;
006bc1
+  r.thread = L;
006bc1
+  r.ins = pc;
006bc1
+  r.traceno = traceno;
006bc1
+  r.fn = lj_debug_top_frame_fn(L, pc);
006bc1
+
006bc1
+  lj_trace_log_event(&r);
006bc1
+}
006bc1
+
006bc1
+static void
006bc1
+lj_log_trace_exit_helper(lua_State *L, int vmstate, const BCIns *pc, int direct)
006bc1
+{
006bc1
+  if (vmstate >= 0) {
006bc1
+    lj_trace_event_record_t  r;
006bc1
+
006bc1
+    jit_State *J = L2J(L);
006bc1
+
006bc1
+    r.event = LJ_TRACE_EVENT_EXIT;
006bc1
+    r.thread = L;
006bc1
+    r.ins = pc;
006bc1
+    r.traceno = vmstate;
006bc1
+    r.exitno = J->exitno;
006bc1
+    r.directexit = direct;
006bc1
+    r.fn = lj_debug_top_frame_fn(L, pc);
006bc1
+
006bc1
+    lj_trace_log_event(&r);
006bc1
+  }
006bc1
+}
006bc1
+
006bc1
+void
006bc1
+lj_log_trace_normal_exit(lua_State *L, int vmstate, const BCIns *pc)
006bc1
+{
006bc1
+  lj_log_trace_exit_helper(L, vmstate, pc, 0);
006bc1
+}
006bc1
+
006bc1
+void
006bc1
+lj_log_trace_direct_exit(lua_State *L, int vmstate, const BCIns *pc)
006bc1
+{
006bc1
+  lj_log_trace_exit_helper(L, vmstate, pc, 1);
006bc1
+}
006bc1
+
006bc1
+#endif  /* LUA_USE_TRACE_LOGS */
006bc1
diff --git a/src/lj_debug.h b/src/lj_debug.h
006bc1
index 5917c00b..82f53bda 100644
006bc1
--- a/src/lj_debug.h
006bc1
+++ b/src/lj_debug.h
006bc1
@@ -62,4 +62,15 @@ enum {
006bc1
   VARNAME__MAX
006bc1
 };
006bc1
 
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+LJ_FUNC void LJ_FASTCALL lj_log_trace_direct_exit(lua_State *L,
006bc1
+  int vmstate, const BCIns *pc);
006bc1
+LJ_FUNC void LJ_FASTCALL lj_log_trace_normal_exit(lua_State *L,
006bc1
+  int vmstate, const BCIns *pc);
006bc1
+LJ_FUNC void LJ_FASTCALL lj_log_trace_entry(lua_State *L,
006bc1
+  unsigned traceno, const BCIns *pc);
006bc1
+LJ_FUNC void LJ_FASTCALL lj_log_trace_start_record(lua_State *L, unsigned traceno,
006bc1
+  const BCIns *pc, GCfunc *fn);
006bc1
+#endif
006bc1
+
006bc1
 #endif
006bc1
diff --git a/src/lj_trace.c b/src/lj_trace.c
006bc1
index d85b47f8..c2f0d8cf 100644
006bc1
--- a/src/lj_trace.c
006bc1
+++ b/src/lj_trace.c
006bc1
@@ -404,6 +404,9 @@ static void trace_start(jit_State *J)
006bc1
 {
006bc1
   lua_State *L;
006bc1
   TraceNo traceno;
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+  const BCIns *pc = J->pc;
006bc1
+#endif
006bc1
 
006bc1
   if ((J->pt->flags & PROTO_NOJIT)) {  /* JIT disabled for this proto? */
006bc1
     if (J->parent == 0 && J->exitno == 0) {
006bc1
@@ -462,6 +465,9 @@ static void trace_start(jit_State *J)
006bc1
     }
006bc1
   );
006bc1
   lj_record_setup(J);
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+  lj_log_trace_start_record(L, (unsigned) J->cur.traceno, pc, J->fn);
006bc1
+#endif
006bc1
 }
006bc1
 
006bc1
 /* Stop tracing. */
006bc1
@@ -890,6 +896,9 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
006bc1
       }
006bc1
     }
006bc1
   }
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+  lj_log_trace_normal_exit(L, (int) T->traceno, pc);
006bc1
+#endif
006bc1
   /* Return MULTRES or 0. */
006bc1
   ERRNO_RESTORE
006bc1
   switch (bc_op(*pc)) {
006bc1
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc
006bc1
index 211ae7b9..66377cd5 100644
006bc1
--- a/src/vm_x86.dasc
006bc1
+++ b/src/vm_x86.dasc
006bc1
@@ -2919,6 +2919,19 @@ static void build_subroutines(BuildCtx *ctx)
006bc1
   |  mov r13, TMPa
006bc1
   |  mov r12, TMPQ
006bc1
   |.endif
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+  |  mov FCARG1, SAVE_L
006bc1
+  |  mov L:FCARG1->base, BASE
006bc1
+  |  mov RB, RD     // Save RD
006bc1
+  |  mov TMP1, PC  // Save PC
006bc1
+  |  mov CARG3d, PC   // CARG3d == BASE
006bc1
+  |  mov FCARG2, dword [DISPATCH+DISPATCH_GL(vmstate)]
006bc1
+  |  call extern lj_log_trace_direct_exit@8
006bc1
+  |  mov PC, TMP1
006bc1
+  |  mov RD, RB
006bc1
+  |  mov RB, SAVE_L
006bc1
+  |  mov BASE, L:RB->base
006bc1
+#endif
006bc1
   |  test RD, RD; js >9			// Check for error from exit.
006bc1
   |  mov L:RB, SAVE_L
006bc1
   |  mov MULTRES, RD
006bc1
@@ -5260,6 +5273,17 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
006bc1
   case BC_JLOOP:
006bc1
     |.if JIT
006bc1
     |  ins_AD	// RA = base (ignored), RD = traceno
006bc1
+#ifdef LUA_USE_TRACE_LOGS
006bc1
+    |  mov L:RB, SAVE_L
006bc1
+    |  mov L:RB->base, BASE  // Save BASE
006bc1
+    |  mov TMP1, RD     // Save RD
006bc1
+    |  mov CARG3d, PC  // CARG3d == BASE
006bc1
+    |  mov FCARG2, RD
006bc1
+    |  mov FCARG1, RB
006bc1
+    |  call extern lj_log_trace_entry@8
006bc1
+    |  mov RD, TMP1
006bc1
+    |  mov BASE, L:RB->base
006bc1
+#endif
006bc1
     |  mov RA, [DISPATCH+DISPATCH_J(trace)]
006bc1
     |  mov TRACE:RD, [RA+RD*4]
006bc1
     |  mov RDa, TRACE:RD->mcode
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From 00a5957d632f1715fdc88c1a3fe7cc355f5a13cb Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <agentzh@gmail.com>
006bc1
Date: Wed, 21 May 2014 16:05:13 -0700
006bc1
Subject: [PATCH 08/13] bugfix: fixed build regression on i386 introduced by
006bc1
 the LUA_USE_TRACE_LOGS feature.
006bc1
006bc1
---
006bc1
 src/vm_x86.dasc | 4 ++++
006bc1
 1 file changed, 4 insertions(+)
006bc1
006bc1
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc
006bc1
index 66377cd5..50210010 100644
006bc1
--- a/src/vm_x86.dasc
006bc1
+++ b/src/vm_x86.dasc
006bc1
@@ -2920,6 +2920,7 @@ static void build_subroutines(BuildCtx *ctx)
006bc1
   |  mov r12, TMPQ
006bc1
   |.endif
006bc1
 #ifdef LUA_USE_TRACE_LOGS
006bc1
+  |.if X64
006bc1
   |  mov FCARG1, SAVE_L
006bc1
   |  mov L:FCARG1->base, BASE
006bc1
   |  mov RB, RD     // Save RD
006bc1
@@ -2931,6 +2932,7 @@ static void build_subroutines(BuildCtx *ctx)
006bc1
   |  mov RD, RB
006bc1
   |  mov RB, SAVE_L
006bc1
   |  mov BASE, L:RB->base
006bc1
+  |.endif
006bc1
 #endif
006bc1
   |  test RD, RD; js >9			// Check for error from exit.
006bc1
   |  mov L:RB, SAVE_L
006bc1
@@ -5274,6 +5276,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
006bc1
     |.if JIT
006bc1
     |  ins_AD	// RA = base (ignored), RD = traceno
006bc1
 #ifdef LUA_USE_TRACE_LOGS
006bc1
+    |.if X64
006bc1
     |  mov L:RB, SAVE_L
006bc1
     |  mov L:RB->base, BASE  // Save BASE
006bc1
     |  mov TMP1, RD     // Save RD
006bc1
@@ -5283,6 +5286,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
006bc1
     |  call extern lj_log_trace_entry@8
006bc1
     |  mov RD, TMP1
006bc1
     |  mov BASE, L:RB->base
006bc1
+    |.endif
006bc1
 #endif
006bc1
     |  mov RA, [DISPATCH+DISPATCH_J(trace)]
006bc1
     |  mov TRACE:RD, [RA+RD*4]
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From 7950afe36eadad8b529f4aa90b303861619a2322 Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <agentzh@gmail.com>
006bc1
Date: Sat, 7 Jun 2014 13:41:24 -0700
006bc1
Subject: [PATCH 09/13] fixed compilation errors on Solaris when
006bc1
 -DLUA_USE_TRACE_LOGS is enabled.
006bc1
006bc1
---
006bc1
 src/lj_debug.c | 8 ++++----
006bc1
 1 file changed, 4 insertions(+), 4 deletions(-)
006bc1
006bc1
diff --git a/src/lj_debug.c b/src/lj_debug.c
006bc1
index 7f4f793a..b93b69d3 100644
006bc1
--- a/src/lj_debug.c
006bc1
+++ b/src/lj_debug.c
006bc1
@@ -760,7 +760,7 @@ lj_debug_top_frame_fn(lua_State *L, const BCIns *pc)
006bc1
   return frame_func(frame);
006bc1
 }
006bc1
 
006bc1
-void
006bc1
+LJ_FUNC void LJ_FASTCALL
006bc1
 lj_log_trace_start_record(lua_State *L, unsigned traceno, const BCIns *pc,
006bc1
   GCfunc *fn)
006bc1
 {
006bc1
@@ -775,7 +775,7 @@ lj_log_trace_start_record(lua_State *L, unsigned traceno, const BCIns *pc,
006bc1
   lj_trace_log_event(&r);
006bc1
 }
006bc1
 
006bc1
-void
006bc1
+LJ_FUNC void LJ_FASTCALL
006bc1
 lj_log_trace_entry(lua_State *L, unsigned traceno, const BCIns *pc)
006bc1
 {
006bc1
   lj_trace_event_record_t  r;
006bc1
@@ -809,13 +809,13 @@ lj_log_trace_exit_helper(lua_State *L, int vmstate, const BCIns *pc, int direct)
006bc1
   }
006bc1
 }
006bc1
 
006bc1
-void
006bc1
+LJ_FUNC void LJ_FASTCALL
006bc1
 lj_log_trace_normal_exit(lua_State *L, int vmstate, const BCIns *pc)
006bc1
 {
006bc1
   lj_log_trace_exit_helper(L, vmstate, pc, 0);
006bc1
 }
006bc1
 
006bc1
-void
006bc1
+LJ_FUNC void LJ_FASTCALL
006bc1
 lj_log_trace_direct_exit(lua_State *L, int vmstate, const BCIns *pc)
006bc1
 {
006bc1
   lj_log_trace_exit_helper(L, vmstate, pc, 1);
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From bd304a366be2ffb10eec6aeba390595232958320 Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <agentzh@gmail.com>
006bc1
Date: Tue, 27 May 2014 12:37:13 -0700
006bc1
Subject: [PATCH 10/13] feature: jit.dump: output Lua source location after
006bc1
 every BC.
006bc1
006bc1
---
006bc1
 src/jit/dump.lua | 3 +++
006bc1
 1 file changed, 3 insertions(+)
006bc1
006bc1
diff --git a/src/jit/dump.lua b/src/jit/dump.lua
006bc1
index 2bea652b..ef0dca61 100644
006bc1
--- a/src/jit/dump.lua
006bc1
+++ b/src/jit/dump.lua
006bc1
@@ -591,6 +591,9 @@ local function dump_record(tr, func, pc, depth, callee)
006bc1
   if pc >= 0 then
006bc1
     line = bcline(func, pc, recprefix)
006bc1
     if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
006bc1
+    if pc > 0 then
006bc1
+      line = sub(line, 1, -2) .. "       (" .. fmtfunc(func, pc) .. ")\n"
006bc1
+    end
006bc1
   else
006bc1
     line = "0000 "..recprefix.." FUNCC      \n"
006bc1
     callee = func
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From cce112ca4fdde7d1ca5963c50d0621fb2e526524 Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <yichun@openresty.com>
006bc1
Date: Fri, 5 Apr 2019 12:38:40 -0700
006bc1
Subject: [PATCH 11/13] feature: luajit -bl: dump the constant tables (KGC and
006bc1
 KN) for each lua proto object as well.
006bc1
006bc1
---
006bc1
 src/jit/bc.lua | 32 ++++++++++++++++++++++++++++++++
006bc1
 1 file changed, 32 insertions(+)
006bc1
006bc1
diff --git a/src/jit/bc.lua b/src/jit/bc.lua
006bc1
index 80f92689..9fee4cda 100644
006bc1
--- a/src/jit/bc.lua
006bc1
+++ b/src/jit/bc.lua
006bc1
@@ -141,6 +141,38 @@ local function bcdump(func, out, all, lineinfo)
006bc1
     end
006bc1
   end
006bc1
   out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined))
006bc1
+
006bc1
+  for n=-1,-1000000000,-1 do
006bc1
+    local kc = funck(func, n)
006bc1
+    if not kc then break end
006bc1
+
006bc1
+    local typ = type(kc)
006bc1
+    if typ == "string" then
006bc1
+      kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub))
006bc1
+      out:write(format("KGC    %d    %s\n", -(n + 1), kc))
006bc1
+    elseif typ == "proto" then
006bc1
+      local fi = funcinfo(kc)
006bc1
+      if fi.ffid then
006bc1
+	kc = vmdef.ffnames[fi.ffid]
006bc1
+      else
006bc1
+	kc = fi.loc
006bc1
+      end
006bc1
+      out:write(format("KGC    %d    %s\n", -(n + 1), kc))
006bc1
+    elseif typ == "table" then
006bc1
+      out:write(format("KGC    %d    table\n", -(n + 1)))
006bc1
+    else
006bc1
+      -- error("unknown KGC type: " .. typ)
006bc1
+    end
006bc1
+  end
006bc1
+
006bc1
+  for n=1,1000000000 do
006bc1
+    local kc = funck(func, n)
006bc1
+    if not kc then break end
006bc1
+    if type(kc) == "number" then
006bc1
+      out:write(format("KN    %d    %s\n", n, kc))
006bc1
+    end
006bc1
+  end
006bc1
+
006bc1
   local target = bctargets(func)
006bc1
   for pc=1,1000000000 do
006bc1
     local s = bcline(func, pc, target[pc] and "=>", lineinfo)
006bc1
-- 
006bc1
2.21.0
006bc1
006bc1
006bc1
From 7d5f5be581ed392059601168a95068e026765aa0 Mon Sep 17 00:00:00 2001
006bc1
From: "Yichun Zhang (agentzh)" <yichun@openresty.com>
006bc1
Date: Fri, 17 May 2019 14:49:48 -0700
006bc1
Subject: [PATCH 13/13] bugfix: thanks Julien Desgats for the report and Peter
006bc1
 Cawley for the patch.
006bc1
006bc1
The test covering this bug was submitted to the openresty/luajit2-test-suite
006bc1
repo as commit ce2c916d55.
006bc1
---
006bc1
 src/lj_tab.c | 81 ++++++++++++++++++++++++++++++++++------------------
006bc1
 1 file changed, 53 insertions(+), 28 deletions(-)
006bc1
006bc1
diff --git a/src/lj_tab.c b/src/lj_tab.c
006bc1
index c51666d3..ff216f3c 100644
006bc1
--- a/src/lj_tab.c
006bc1
+++ b/src/lj_tab.c
006bc1
@@ -474,6 +474,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
006bc1
     lua_assert(freenode != &G(L)->nilnode);
006bc1
     collide = hashkey(t, &n->key);
006bc1
     if (collide != n) {  /* Colliding node not the main node? */
006bc1
+      Node *nn;
006bc1
       while (noderef(collide->next) != n)  /* Find predecessor. */
006bc1
 	collide = nextnode(collide);
006bc1
       setmref(collide->next, freenode);  /* Relink chain. */
006bc1
@@ -483,39 +484,63 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
006bc1
       freenode->next = n->next;
006bc1
       setmref(n->next, NULL);
006bc1
       setnilV(&n->val);
006bc1
-      /* Rechain pseudo-resurrected string keys with colliding hashes. */
006bc1
-      while (nextnode(freenode)) {
006bc1
-	Node *nn = nextnode(freenode);
006bc1
-	if (tvisstr(&nn->key) && !tvisnil(&nn->val) &&
006bc1
-	    hashstr(t, strV(&nn->key)) == n) {
006bc1
-	  freenode->next = nn->next;
006bc1
-	  nn->next = n->next;
006bc1
-	  setmref(n->next, nn);
006bc1
-	  /*
006bc1
-	  ** Rechaining a resurrected string key creates a new dilemma:
006bc1
-	  ** Another string key may have originally been resurrected via
006bc1
-	  ** _any_ of the previous nodes as a chain anchor. Including
006bc1
-	  ** a node that had to be moved, which makes them unreachable.
006bc1
-	  ** It's not feasible to check for all previous nodes, so rechain
006bc1
-	  ** any string key that's currently in a non-main positions.
006bc1
-	  */
006bc1
-	  while ((nn = nextnode(freenode))) {
006bc1
-	    if (tvisstr(&nn->key) && !tvisnil(&nn->val)) {
006bc1
-	      Node *mn = hashstr(t, strV(&nn->key));
006bc1
-	      if (mn != freenode) {
006bc1
-		freenode->next = nn->next;
006bc1
-		nn->next = mn->next;
006bc1
-		setmref(mn->next, nn);
006bc1
+      /*
006bc1
+      ** Nodes after n might have n as their main node, and need rechaining
006bc1
+      ** back onto n. We make use of the following property of tables: for all
006bc1
+      ** nodes m, at least one of the following four statements is true:
006bc1
+      **  1. tvisnil(&m->key)  NB: tvisnil(&m->val) is a stronger statement
006bc1
+      **  2. tvisstr(&m->key)
006bc1
+      **  3. tvisstr(&main(m)->key)
006bc1
+      **  4. main(m) == main(main(m))
006bc1
+      ** Initially, we need to rechain any nn which has main(nn) == n. As
006bc1
+      ** main(n) != n (because collide != n earlier), main(nn) == n requires
006bc1
+      ** either statement 2 or statement 3 to be true about nn.
006bc1
+      */
006bc1
+      if (!tvisstr(&n->key)) {
006bc1
+	/* Statement 3 is not true, so only need to consider string keys. */
006bc1
+	while ((nn = nextnode(freenode))) {
006bc1
+	  if (tvisstr(&nn->key) && !tvisnil(&nn->val) &&
006bc1
+	      hashstr(t, strV(&nn->key)) == n) {
006bc1
+	    goto rechain;
006bc1
+	  }
006bc1
+	  freenode = nn;
006bc1
+	}
006bc1
+      } else {
006bc1
+	/* Statement 3 is true, so need to consider all types of key. */
006bc1
+	while ((nn = nextnode(freenode))) {
006bc1
+	  if (!tvisnil(&nn->val) && hashkey(t, &nn->key) == n) {
006bc1
+	  rechain:
006bc1
+	    freenode->next = nn->next;
006bc1
+	    nn->next = n->next;
006bc1
+	    setmref(n->next, nn);
006bc1
+	    /*
006bc1
+	    ** Rechaining one node onto n creates a new dilemma: we now need
006bc1
+	    ** to rechain any nn which has main(nn) == n OR has main(nn) equal
006bc1
+	    ** to any node which has already been rechained. Furthermore, at
006bc1
+	    ** least one of n and n->next will have a string key, so all types
006bc1
+	    ** of nn key need to be considered. Rather than testing whether
006bc1
+	    ** main(nn) definitely _is_ in the new chain, we test whether it
006bc1
+	    ** might _not_ be in the old chain, and if so re-link it into
006bc1
+	    ** the correct chain.
006bc1
+	    */
006bc1
+	    while ((nn = nextnode(freenode))) {
006bc1
+	      if (!tvisnil(&nn->val)) {
006bc1
+		Node *mn = hashkey(t, &nn->key);
006bc1
+		if (mn != freenode && mn != nn) {
006bc1
+		  freenode->next = nn->next;
006bc1
+		  nn->next = mn->next;
006bc1
+		  setmref(mn->next, nn);
006bc1
+		} else {
006bc1
+		  freenode = nn;
006bc1
+		}
006bc1
 	      } else {
006bc1
 		freenode = nn;
006bc1
 	      }
006bc1
-	    } else {
006bc1
-	      freenode = nn;
006bc1
 	    }
006bc1
+	    break;
006bc1
+	  } else {
006bc1
+	    freenode = nn;
006bc1
 	  }
006bc1
-	  break;
006bc1
-	} else {
006bc1
-	  freenode = nn;
006bc1
 	}
006bc1
       }
006bc1
     } else {  /* Otherwise use free node. */
006bc1
-- 
006bc1
2.21.0
006bc1