Compare commits

...

17 Commits

Author SHA1 Message Date
Aditya Bisht
fc8cfacf14
Merge bb784b48a6 into e3c70a7d81 2025-03-10 09:46:04 +08:00
Mike Pall
e3c70a7d81 macOS: Fix support for Apple hardened runtime.
Reported by Christian Clason. #1334
2025-03-10 00:05:08 +01:00
Mike Pall
7db2d1b12a Fix handling of nil value markers in template tables.
Thanks to Peter Cawley. #1348 #1155
2025-03-09 23:11:05 +01:00
Mike Pall
e0551670c9 Merge branch 'master' into v2.1 2025-03-09 23:09:02 +01:00
Mike Pall
85c3f2fb6f Avoid unpatching bytecode twice after a trace flush.
Reported by Sergey Kaplun. #1345
2025-03-09 23:04:23 +01:00
Mike Pall
eee16efa77 Fix state restore when recording __concat metamethod.
Reported by Sergey Kaplun. #1338 #1298
2025-03-09 21:28:17 +01:00
Mike Pall
4219efae43 Windows: Allow mixed builds with msvcbuild.bat.
Suggested by alex4814. #1341
2025-03-09 21:05:06 +01:00
Mike Pall
0254770582 macOS: Add suport for Apple hardened runtime.
Thanks to Peter Cawley. #1334
2025-03-09 20:45:22 +01:00
Mike Pall
f14556234c Merge branch 'master' into v2.1 2025-03-09 16:25:34 +01:00
Mike Pall
d508715ab6 Add compatibility string coercion for fp:seek() argument.
Reported by Magnus Wibeck. #1343
2025-03-09 16:21:29 +01:00
Mike Pall
e27ee68817 Windows: Clarify installation directory layout.
Suggested by eabase. #1346
2025-03-09 16:10:22 +01:00
Mike Pall
55a42da36e Remove Cygwin from docs, since it's not a supported target. 2025-03-09 16:09:36 +01:00
Mike Pall
423ac2144b Improve CLI signal handling on POSIX. 2025-03-09 15:50:01 +01:00
Mike Pall
54dc2fa5d7 FFI: Add pre-declared int128_t, uint128_t, __int128 types.
Note: Only declaration and copy (interpreted only) are implemented.
2025-03-09 15:37:35 +01:00
Mike Pall
b1179ea5f7 Use dylib extension for iOS installs, too.
Reported by Andrey Filipenkov. #1336
2025-03-09 15:00:15 +01:00
Mike Pall
5eb9509468 Change handling of nil value markers in template tables.
Reported by Bernhard M. Wiedemann. #1348 #1155
2025-03-09 14:44:57 +01:00
Aditya Bisht
bb784b48a6
Adding s390x support for DynASM 2022-06-23 14:05:10 +05:30
20 changed files with 2304 additions and 65 deletions

View File

@ -110,7 +110,7 @@ else
endif endif
TARGET_SYS?= $(HOST_SYS) TARGET_SYS?= $(HOST_SYS)
ifeq (Darwin,$(TARGET_SYS)) ifneq (,$(filter $(TARGET_SYS),Darwin iOS))
INSTALL_SONAME= $(INSTALL_DYLIBNAME) INSTALL_SONAME= $(INSTALL_DYLIBNAME)
INSTALL_SOSHORT1= $(INSTALL_DYLIBSHORT1) INSTALL_SOSHORT1= $(INSTALL_DYLIBSHORT1)
INSTALL_SOSHORT2= $(INSTALL_DYLIBSHORT2) INSTALL_SOSHORT2= $(INSTALL_DYLIBSHORT2)

View File

@ -117,7 +117,7 @@ hold all user-configurable settings:
<li><tt>Makefile</tt> has settings for <b>installing</b> LuaJIT (POSIX <li><tt>Makefile</tt> has settings for <b>installing</b> LuaJIT (POSIX
only).</li> only).</li>
<li><tt>src/Makefile</tt> has settings for <b>compiling</b> LuaJIT <li><tt>src/Makefile</tt> has settings for <b>compiling</b> LuaJIT
under POSIX, MinGW or Cygwin.</li> under POSIX or MinGW.</li>
<li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with <li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with
MSVC (Visual Studio).</li> MSVC (Visual Studio).</li>
</ul> </ul>
@ -195,10 +195,8 @@ Obviously the prefixes given during build and installation need to be the same.
<h2 id="windows">Windows Systems</h2> <h2 id="windows">Windows Systems</h2>
<h3>Prerequisites</h3> <h3>Prerequisites</h3>
<p> <p>
Either install one of the open source SDKs Either install the open source SDK <a href="http://mingw.org/"><span class="ext">&raquo;</span>&nbsp;MinGW</a>,
(<a href="http://mingw.org/"><span class="ext">&raquo;</span>&nbsp;MinGW</a> or which comes with a modified GCC plus the required development headers.
<a href="https://www.cygwin.com/"><span class="ext">&raquo;</span>&nbsp;Cygwin</a>), which come with a modified
GCC plus the required development headers.
Or install Microsoft's Visual Studio (MSVC). Or install Microsoft's Visual Studio (MSVC).
</p> </p>
<h3>Building with MSVC</h3> <h3>Building with MSVC</h3>
@ -217,9 +215,9 @@ Then follow the installation instructions below.
<p> <p>
For an x64 to ARM64 cross-build run this first: <tt>vcvarsall.bat x64_arm64</tt> For an x64 to ARM64 cross-build run this first: <tt>vcvarsall.bat x64_arm64</tt>
</p> </p>
<h3>Building with MinGW or Cygwin</h3> <h3>Building with MinGW</h3>
<p> <p>
Open a command prompt window and make sure the MinGW or Cygwin programs Open a command prompt window and make sure the MinGW programs
are in your path. Then <tt>cd</tt> to the directory of the git repository. are in your path. Then <tt>cd</tt> to the directory of the git repository.
Then run this command for MinGW: Then run this command for MinGW:
</p> </p>
@ -227,12 +225,6 @@ Then run this command for MinGW:
mingw32-make mingw32-make
</pre> </pre>
<p> <p>
Or this command for Cygwin:
</p>
<pre class="code">
make
</pre>
<p>
Then follow the installation instructions below. Then follow the installation instructions below.
</p> </p>
<h3>Installing LuaJIT</h3> <h3>Installing LuaJIT</h3>
@ -249,6 +241,19 @@ absolute path names &mdash; all modules are loaded relative to the
directory where <tt>luajit.exe</tt> is installed directory where <tt>luajit.exe</tt> is installed
(see <tt>src/luaconf.h</tt>). (see <tt>src/luaconf.h</tt>).
</p> </p>
<p>
The final directory layout should look like this:
</p>
<pre class="code">
├── luajit.exe
├── lua51.dll
├── <- put your own classic Lua/C API modules (*.dll) here
└── lua
├── <- put your own Lua modules (*.lua) here
└── jit
├── bc.lua
└── (etc …)
</pre>
<h2 id="cross">Cross-compiling LuaJIT</h2> <h2 id="cross">Cross-compiling LuaJIT</h2>
<p> <p>

546
dynasm/dasm_s390x.h Normal file
View File

@ -0,0 +1,546 @@
/*
** DynASM s390x encoding engine.
** Copyright (C) 2005-2022 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "s390x"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC,
DASM_DISP12, DASM_DISP20,
DASM_IMM8, DASM_IMM16, DASM_IMM32,
DASM_LEN8R,DASM_LEN4HR,DASM_LEN4LR,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned short *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels)
DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels)
DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10 + maxgl) * sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc * sizeof(int));
memset((void *)(((unsigned char *)D->pclabels) + osz), 0, D->pcsize - osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList) actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels)
memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2 * DASM_MAXSECPOS * sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos =
(int)sec->bsize / sizeof(int) - DASM_MAXSECPOS + DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned short ins = *p++;
unsigned short action = ins;
if (action >= DASM__MAX) {
ofs += 2;
continue;
}
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP:
goto stop;
case DASM_SECTION:
n = *p++ & 255;
CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n];
goto stop;
case DASM_ESC:
p++;
ofs += 2;
break;
case DASM_REL_EXT:
p++;
ofs += 4;
break;
case DASM_ALIGN:
ofs += *p++;
b[pos++] = ofs;
break;
case DASM_REL_LG:
if (p[-2] >> 12 == 0xc) { /* RIL instruction needs 32-bit immediate. */
ofs += 2;
}
n = *p++ - 10;
pl = D->lglabels + n;
/* 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;
case DASM_REL_PC:
if (p[-2] >> 12 == 0xc) { /* RIL instruction needs 32-bit immediate. */
ofs += 2;
}
pl = D->pclabels + n;
CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
ofs += 2;
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + *p++ - 10;
CKPL(lg, LG);
goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n;
CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) {
int *pb = DASM_POS2PTR(D, n);
n = *pb;
*pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM8:
b[pos++] = n;
break;
case DASM_IMM16:
CK(((short)n) == n || ((unsigned short)n) == n, RANGE_I); /* TODO: is this the right way to handle unsigned immediates? */
ofs += 2;
b[pos++] = n;
break;
case DASM_IMM32:
ofs += 4;
b[pos++] = n;
break;
case DASM_DISP20:
CK(-(1 << 19) <= n && n < (1 << 19), RANGE_I);
b[pos++] = n;
break;
case DASM_DISP12:
CK((n >> 12) == 0, RANGE_I);
b[pos++] = n;
break;
case DASM_LEN8R:
CK(n >= 1 && n <= 256, RANGE_I);
b[pos++] = n;
break;
case DASM_LEN4HR:
case DASM_LEN4LR:
CK(n >= 1 && n <= 128, RANGE_I);
b[pos++] = n;
break;
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t * szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK)
return D->status;
{
int pc;
for (pc = 0; pc * sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0)
return DASM_S_UNDEF_PC | pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx * sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) {
int *pb = DASM_POS2PTR(D, n);
n = *pb;
*pb = -idx;
}
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned short ins = *p++;
unsigned short action = ins;
switch (action) {
case DASM_STOP:
case DASM_SECTION:
goto stop;
case DASM_ESC:
p++;
break;
case DASM_REL_EXT:
p++;
break;
case DASM_ALIGN:
ofs -= (b[pos++] + ofs) & *p++;
break;
case DASM_REL_LG:
case DASM_REL_PC:
p++;
pos++;
break;
case DASM_LABEL_LG:
case DASM_LABEL_PC:
p++;
b[pos++] += ofs;
break;
case DASM_IMM8:
case DASM_IMM16:
case DASM_IMM32:
case DASM_DISP20:
case DASM_DISP12:
case DASM_LEN8R:
case DASM_LEN4HR:
case DASM_LEN4LR:
pos++;
break;
}
}
stop:(void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned short *cp = (unsigned short *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned short ins = *p++;
unsigned short action = ins;
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP:
case DASM_SECTION:
goto stop;
case DASM_ESC:
*cp++ = *p++;
break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, *p++, 1) - 4;
goto patchrel;
case DASM_ALIGN:
ins = *p++;
/* TODO: emit 4-byte noprs instead of 2-byte nops where possible. */
while ((((char *)cp - base) & ins))
*cp++ = 0x0700; /* nop */
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
p++; /* skip argument */
patchrel:
/* Offsets are halfword aligned (so need to be halved). */
n += 2; /* Offset is relative to start of instruction. */
if (cp[-1] >> 12 == 0xc) {
*cp++ = n >> 17;
} else {
CK(-(1 << 16) <= n && n < (1 << 16) && (n & 1) == 0, RANGE_LG);
}
*cp++ = n >> 1;
break;
case DASM_LABEL_LG:
ins = *p++;
if (ins >= 20)
D->globals[ins - 10] = (void *)(base + n);
break;
case DASM_LABEL_PC:
break;
case DASM_IMM8:
cp[-1] |= n & 0xff;
break;
case DASM_IMM16:
*cp++ = n;
break;
case DASM_IMM32:
*cp++ = n >> 16;
*cp++ = n;
break;
case DASM_DISP20:
cp[-2] |= n & 0xfff;
cp[-1] |= (n >> 4) & 0xff00;
break;
case DASM_DISP12:
cp[-1] |= n & 0xfff;
break;
case DASM_LEN8R:
cp[-1] |= (n - 1) & 0xff;
break;
case DASM_LEN4HR:
cp[-1] |= ((n - 1) << 4) & 0xf0;
break;
case DASM_LEN4LR:
cp[-1] |= (n - 1) & 0x0f;
break;
default:
*cp++ = ins;
break;
}
}
stop:(void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc * sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0)
return *DASM_POS2PTR(D, -pos);
if (pos > 0)
return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) {
D->status = DASM_S_UNDEF_LG | i;
break;
}
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC | (D->section - D->sections);
return D->status;
}
#endif

1632
dynasm/dasm_s390x.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h \
lj_strfmt.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h lj_strfmt.h lj_ff.h lj_ffdef.h lj_lib.h lj_strscan.h lj_libdef.h
lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \
lj_state.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ lj_state.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \

View File

@ -25,6 +25,7 @@
#include "lj_strfmt.h" #include "lj_strfmt.h"
#include "lj_ff.h" #include "lj_ff.h"
#include "lj_lib.h" #include "lj_lib.h"
#include "lj_strscan.h"
/* Userdata payload for I/O file. */ /* Userdata payload for I/O file. */
typedef struct IOFileUD { typedef struct IOFileUD {
@ -323,13 +324,14 @@ LJLIB_CF(io_method_seek)
FILE *fp = io_tofile(L)->fp; FILE *fp = io_tofile(L)->fp;
int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end"); int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
int64_t ofs = 0; int64_t ofs = 0;
cTValue *o; TValue *o;
int res; int res;
if (opt == 0) opt = SEEK_SET; if (opt == 0) opt = SEEK_SET;
else if (opt == 1) opt = SEEK_CUR; else if (opt == 1) opt = SEEK_CUR;
else if (opt == 2) opt = SEEK_END; else if (opt == 2) opt = SEEK_END;
o = L->base+2; o = L->base+2;
if (o < L->top) { if (o < L->top) {
if (tvisstr(o)) lj_strscan_num(strV(o), o);
if (tvisint(o)) if (tvisint(o))
ofs = (int64_t)intV(o); ofs = (int64_t)intV(o);
else if (tvisnum(o)) else if (tvisnum(o))

View File

@ -179,7 +179,7 @@ static const void *bcread_varinfo(GCproto *pt)
} }
/* Read a single constant key/value of a template table. */ /* Read a single constant key/value of a template table. */
static void bcread_ktabk(LexState *ls, TValue *o) static void bcread_ktabk(LexState *ls, TValue *o, GCtab *t)
{ {
MSize tp = bcread_uleb128(ls); MSize tp = bcread_uleb128(ls);
if (tp >= BCDUMP_KTAB_STR) { if (tp >= BCDUMP_KTAB_STR) {
@ -191,6 +191,8 @@ static void bcread_ktabk(LexState *ls, TValue *o)
} else if (tp == BCDUMP_KTAB_NUM) { } else if (tp == BCDUMP_KTAB_NUM) {
o->u32.lo = bcread_uleb128(ls); o->u32.lo = bcread_uleb128(ls);
o->u32.hi = bcread_uleb128(ls); o->u32.hi = bcread_uleb128(ls);
} else if (tp == BCDUMP_KTAB_NIL) { /* Restore nil value marker. */
settabV(ls->L, o, t);
} else { } else {
lj_assertLS(tp <= BCDUMP_KTAB_TRUE, "bad constant type %d", tp); lj_assertLS(tp <= BCDUMP_KTAB_TRUE, "bad constant type %d", tp);
setpriV(o, ~tp); setpriV(o, ~tp);
@ -207,15 +209,15 @@ static GCtab *bcread_ktab(LexState *ls)
MSize i; MSize i;
TValue *o = tvref(t->array); TValue *o = tvref(t->array);
for (i = 0; i < narray; i++, o++) for (i = 0; i < narray; i++, o++)
bcread_ktabk(ls, o); bcread_ktabk(ls, o, t);
} }
if (nhash) { /* Read hash entries. */ if (nhash) { /* Read hash entries. */
MSize i; MSize i;
for (i = 0; i < nhash; i++) { for (i = 0; i < nhash; i++) {
TValue key; TValue key;
bcread_ktabk(ls, &key); bcread_ktabk(ls, &key, t);
lj_assertLS(!tvisnil(&key), "nil key"); lj_assertLS(!tvisnil(&key), "nil key");
bcread_ktabk(ls, lj_tab_set(ls->L, t, &key)); bcread_ktabk(ls, lj_tab_set(ls->L, t, &key), t);
} }
} }
return t; return t;

View File

@ -71,6 +71,8 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
*p++ = BCDUMP_KTAB_NUM; *p++ = BCDUMP_KTAB_NUM;
p = lj_strfmt_wuleb128(p, o->u32.lo); p = lj_strfmt_wuleb128(p, o->u32.lo);
p = lj_strfmt_wuleb128(p, o->u32.hi); p = lj_strfmt_wuleb128(p, o->u32.hi);
} else if (tvistab(o)) { /* Write the nil value marker as a nil. */
*p++ = BCDUMP_KTAB_NIL;
} else { } else {
lj_assertBCW(tvispri(o), "unhandled type %d", itype(o)); lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
*p++ = BCDUMP_KTAB_NIL+~itype(o); *p++ = BCDUMP_KTAB_NIL+~itype(o);
@ -133,7 +135,7 @@ static void bcwrite_ktab_sorted_hash(BCWriteCtx *ctx, Node *node, MSize nhash)
TValue **heap = ctx->heap; TValue **heap = ctx->heap;
MSize i = nhash; MSize i = nhash;
for (;; node--) { /* Build heap. */ for (;; node--) { /* Build heap. */
if (!tvisnil(&node->key)) { if (!tvisnil(&node->val)) {
bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key); bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key);
if (i == 0) break; if (i == 0) break;
} }
@ -163,7 +165,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
MSize i, hmask = t->hmask; MSize i, hmask = t->hmask;
Node *node = noderef(t->node); Node *node = noderef(t->node);
for (i = 0; i <= hmask; i++) for (i = 0; i <= hmask; i++)
nhash += !tvisnil(&node[i].key); nhash += !tvisnil(&node[i].val);
} }
/* Write number of array slots and hash slots. */ /* Write number of array slots and hash slots. */
p = lj_strfmt_wuleb128(p, narray); p = lj_strfmt_wuleb128(p, narray);
@ -184,7 +186,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
} else { } else {
MSize i = nhash; MSize i = nhash;
for (;; node--) for (;; node--)
if (!tvisnil(&node->key)) { if (!tvisnil(&node->val)) {
bcwrite_ktabk(ctx, &node->key, 0); bcwrite_ktabk(ctx, &node->key, 0);
bcwrite_ktabk(ctx, &node->val, 1); bcwrite_ktabk(ctx, &node->val, 1);
if (--i == 0) break; if (--i == 0) break;

View File

@ -262,6 +262,14 @@ static void *callback_mcode_init(global_State *g, uint32_t *page)
#define CCPROT_CREATE 0 #define CCPROT_CREATE 0
#endif #endif
/* Check for macOS hardened runtime. */
#if LUAJIT_SECURITY_MCODE != 0 && defined(MAP_JIT) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000
#include <pthread.h>
#define CCMAP_CREATE MAP_JIT
#else
#define CCMAP_CREATE 0
#endif
#endif #endif
/* Allocate and initialize area for callback function pointers. */ /* Allocate and initialize area for callback function pointers. */
@ -276,10 +284,13 @@ static void callback_mcode_new(CTState *cts)
if (!p) if (!p)
lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV); lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
#elif LJ_TARGET_POSIX #elif LJ_TARGET_POSIX
p = mmap(NULL, sz, (PROT_READ|PROT_WRITE|CCPROT_CREATE), MAP_PRIVATE|MAP_ANONYMOUS, p = mmap(NULL, sz, PROT_READ|PROT_WRITE|CCPROT_CREATE,
-1, 0); MAP_PRIVATE|MAP_ANONYMOUS|CCMAP_CREATE, -1, 0);
if (p == MAP_FAILED) if (p == MAP_FAILED)
lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV); lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
#if CCMAP_CREATE
pthread_jit_write_protect_np(0);
#endif
#else #else
/* Fallback allocator. Fails if memory is not executable by default. */ /* Fallback allocator. Fails if memory is not executable by default. */
p = lj_mem_new(cts->L, sz); p = lj_mem_new(cts->L, sz);
@ -296,8 +307,12 @@ static void callback_mcode_new(CTState *cts)
LJ_WIN_VPROTECT(p, sz, PAGE_EXECUTE_READ, &oprot); LJ_WIN_VPROTECT(p, sz, PAGE_EXECUTE_READ, &oprot);
} }
#elif LJ_TARGET_POSIX #elif LJ_TARGET_POSIX
#if CCMAP_CREATE
pthread_jit_write_protect_np(1);
#else
mprotect(p, sz, (PROT_READ|PROT_EXEC)); mprotect(p, sz, (PROT_READ|PROT_EXEC));
#endif #endif
#endif
} }
/* Free area for callback function pointers. */ /* Free area for callback function pointers. */

View File

@ -33,10 +33,12 @@
_("int16_t", INT16) \ _("int16_t", INT16) \
_("int32_t", INT32) \ _("int32_t", INT32) \
_("int64_t", INT64) \ _("int64_t", INT64) \
_("int128_t", INT128) \
_("uint8_t", UINT8) \ _("uint8_t", UINT8) \
_("uint16_t", UINT16) \ _("uint16_t", UINT16) \
_("uint32_t", UINT32) \ _("uint32_t", UINT32) \
_("uint64_t", UINT64) \ _("uint64_t", UINT64) \
_("uint128_t", UINT128) \
_("intptr_t", INT_PSZ) \ _("intptr_t", INT_PSZ) \
_("uintptr_t", UINT_PSZ) \ _("uintptr_t", UINT_PSZ) \
/* From POSIX. */ \ /* From POSIX. */ \
@ -55,6 +57,7 @@
_("__int16", 2, CTOK_INT) \ _("__int16", 2, CTOK_INT) \
_("__int32", 4, CTOK_INT) \ _("__int32", 4, CTOK_INT) \
_("__int64", 8, CTOK_INT) \ _("__int64", 8, CTOK_INT) \
_("__int128", 16, CTOK_INT) \
_("float", 4, CTOK_FP) \ _("float", 4, CTOK_FP) \
_("double", 8, CTOK_FP) \ _("double", 8, CTOK_FP) \
_("long", 0, CTOK_LONG) \ _("long", 0, CTOK_LONG) \

View File

@ -292,6 +292,8 @@ typedef struct CTState {
_(UINT32, 4, CT_NUM, CTF_UNSIGNED|CTALIGN(2)) \ _(UINT32, 4, CT_NUM, CTF_UNSIGNED|CTALIGN(2)) \
_(INT64, 8, CT_NUM, CTF_LONG_IF8|CTALIGN(3)) \ _(INT64, 8, CT_NUM, CTF_LONG_IF8|CTALIGN(3)) \
_(UINT64, 8, CT_NUM, CTF_UNSIGNED|CTF_LONG_IF8|CTALIGN(3)) \ _(UINT64, 8, CT_NUM, CTF_UNSIGNED|CTF_LONG_IF8|CTALIGN(3)) \
_(INT128, 16, CT_NUM, CTALIGN(4)) \
_(UINT128, 16, CT_NUM, CTF_UNSIGNED|CTALIGN(4)) \
_(FLOAT, 4, CT_NUM, CTF_FP|CTALIGN(2)) \ _(FLOAT, 4, CT_NUM, CTF_FP|CTALIGN(2)) \
_(DOUBLE, 8, CT_NUM, CTF_FP|CTALIGN(3)) \ _(DOUBLE, 8, CT_NUM, CTF_FP|CTALIGN(3)) \
_(COMPLEX_FLOAT, 8, CT_ARRAY, CTF_COMPLEX|CTALIGN(2)|CTID_FLOAT) \ _(COMPLEX_FLOAT, 8, CT_ARRAY, CTF_COMPLEX|CTALIGN(2)|CTID_FLOAT) \

View File

@ -98,6 +98,14 @@ static int mcode_setprot(void *p, size_t sz, DWORD prot)
#define MAP_ANONYMOUS MAP_ANON #define MAP_ANONYMOUS MAP_ANON
#endif #endif
/* Check for macOS hardened runtime. */
#if LUAJIT_SECURITY_MCODE != 0 && defined(MAP_JIT) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000
#include <pthread.h>
#define MCMAP_CREATE MAP_JIT
#else
#define MCMAP_CREATE 0
#endif
#define MCPROT_RW (PROT_READ|PROT_WRITE) #define MCPROT_RW (PROT_READ|PROT_WRITE)
#define MCPROT_RX (PROT_READ|PROT_EXEC) #define MCPROT_RX (PROT_READ|PROT_EXEC)
#define MCPROT_RWX (PROT_READ|PROT_WRITE|PROT_EXEC) #define MCPROT_RWX (PROT_READ|PROT_WRITE|PROT_EXEC)
@ -109,10 +117,14 @@ static int mcode_setprot(void *p, size_t sz, DWORD prot)
static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot) static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot)
{ {
void *p = mmap((void *)hint, sz, prot|MCPROT_CREATE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); void *p = mmap((void *)hint, sz, prot|MCPROT_CREATE, MAP_PRIVATE|MAP_ANONYMOUS|MCMAP_CREATE, -1, 0);
if (p == MAP_FAILED) { if (p == MAP_FAILED) {
if (!hint) lj_trace_err(J, LJ_TRERR_MCODEAL); if (!hint) lj_trace_err(J, LJ_TRERR_MCODEAL);
p = NULL; p = NULL;
#if MCMAP_CREATE
} else {
pthread_jit_write_protect_np(0);
#endif
} }
return p; return p;
} }
@ -125,7 +137,12 @@ static void mcode_free(jit_State *J, void *p, size_t sz)
static int mcode_setprot(void *p, size_t sz, int prot) static int mcode_setprot(void *p, size_t sz, int prot)
{ {
#if MCMAP_CREATE
pthread_jit_write_protect_np((prot & PROT_EXEC));
return 0;
#else
return mprotect(p, sz, prot); return mprotect(p, sz, prot);
#endif
} }
#else #else

View File

@ -2217,9 +2217,11 @@ LJFOLD(HREF TDUP KNUM)
LJFOLDF(fwd_href_tdup) LJFOLDF(fwd_href_tdup)
{ {
TValue keyv; TValue keyv;
cTValue *val;
lj_ir_kvalue(J->L, &keyv, fright); lj_ir_kvalue(J->L, &keyv, fright);
if (lj_tab_get(J->L, ir_ktab(IR(fleft->op1)), &keyv) == niltvg(J2G(J)) && val = lj_tab_get(J->L, ir_ktab(IR(fleft->op1)), &keyv);
lj_opt_fwd_href_nokey(J)) /* Check for either nil or the nil value marker in the template table. */
if ((tvisnil(val) || tvistab(val)) && lj_opt_fwd_href_nokey(J))
return lj_ir_kkptr(J, niltvg(J2G(J))); return lj_ir_kkptr(J, niltvg(J2G(J)));
return NEXTFOLD; return NEXTFOLD;
} }

View File

@ -233,7 +233,9 @@ static TRef fwd_ahload(jit_State *J, IRRef xref)
return lj_ir_knum_u64(J, tv->u64); return lj_ir_knum_u64(J, tv->u64);
else if (tvisint(tv)) else if (tvisint(tv))
return lj_ir_kint(J, intV(tv)); return lj_ir_kint(J, intV(tv));
else if (tvisgcv(tv)) else if (tvistab(tv)) /* Template table nil value marker. */
return TREF_NIL;
else if (tvisstr(tv))
return lj_ir_kstr(J, strV(tv)); return lj_ir_kstr(J, strV(tv));
} }
/* Othwerwise: don't intern as a constant. */ /* Othwerwise: don't intern as a constant. */

View File

@ -1725,7 +1725,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
BCLine line = ls->linenumber; BCLine line = ls->linenumber;
GCtab *t = NULL; GCtab *t = NULL;
int vcall = 0, needarr = 0, fixt = 0; int vcall = 0, needarr = 0;
uint32_t narr = 1; /* First array index. */ uint32_t narr = 1; /* First array index. */
uint32_t nhash = 0; /* Number of hash entries. */ uint32_t nhash = 0; /* Number of hash entries. */
BCReg freg = fs->freereg; BCReg freg = fs->freereg;
@ -1769,9 +1769,10 @@ static void expr_table(LexState *ls, ExpDesc *e)
lj_gc_anybarriert(fs->L, t); lj_gc_anybarriert(fs->L, t);
if (expr_isk_nojump(&val)) { /* Add const key/value to template table. */ if (expr_isk_nojump(&val)) { /* Add const key/value to template table. */
expr_kvalue(fs, v, &val); expr_kvalue(fs, v, &val);
} else { /* Otherwise create dummy string key (avoids lj_tab_newkey). */ /* Mark nil value with table value itself to preserve the key. */
settabV(fs->L, v, t); /* Preserve key with table itself as value. */ if (key.k == VKSTR && tvisnil(v)) settabV(fs->L, v, t);
fixt = 1; /* Fix this later, after all resizes. */ } else { /* Preserve the key for the following non-const store. */
settabV(fs->L, v, t);
goto nonconst; goto nonconst;
} }
} else { } else {
@ -1813,17 +1814,6 @@ static void expr_table(LexState *ls, ExpDesc *e)
} else { } else {
if (needarr && t->asize < narr) if (needarr && t->asize < narr)
lj_tab_reasize(fs->L, t, narr-1); lj_tab_reasize(fs->L, t, narr-1);
if (fixt) { /* Fix value for dummy keys in template table. */
Node *node = noderef(t->node);
uint32_t i, hmask = t->hmask;
for (i = 0; i <= hmask; i++) {
Node *n = &node[i];
if (tvistab(&n->val)) {
lj_assertFS(tabV(&n->val) == t, "bad dummy key in template table");
setnilV(&n->val); /* Turn value into nil. */
}
}
}
lj_gc_check(fs->L); lj_gc_check(fs->L);
} }
} }

View File

@ -2079,6 +2079,7 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
/* -- Concatenation ------------------------------------------------------- */ /* -- Concatenation ------------------------------------------------------- */
typedef struct RecCatDataCP { typedef struct RecCatDataCP {
TValue savetv[5+LJ_FR2];
jit_State *J; jit_State *J;
BCReg baseslot, topslot; BCReg baseslot, topslot;
TRef tr; TRef tr;
@ -2119,7 +2120,9 @@ static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud)
return NULL; return NULL;
} }
/* Pass partial result. */ /* Pass partial result. */
topslot = J->maxslot--; rcd->topslot = topslot = J->maxslot--;
/* Save updated range of slots. */
memcpy(rcd->savetv, &L->base[topslot-1], sizeof(rcd->savetv));
*xbase = tr; *xbase = tr;
top = xbase; top = xbase;
setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */ setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */
@ -2139,16 +2142,18 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
{ {
lua_State *L = J->L; lua_State *L = J->L;
ptrdiff_t delta = L->top - L->base; ptrdiff_t delta = L->top - L->base;
TValue savetv[5+LJ_FR2], errobj; TValue errobj;
RecCatDataCP rcd; RecCatDataCP rcd;
int errcode; int errcode;
rcd.J = J; rcd.J = J;
rcd.baseslot = baseslot; rcd.baseslot = baseslot;
rcd.topslot = topslot; rcd.topslot = topslot;
memcpy(savetv, &L->base[topslot-1], sizeof(savetv)); /* Save slots. */ /* Save slots. */
memcpy(rcd.savetv, &L->base[topslot-1], sizeof(rcd.savetv));
errcode = lj_vm_cpcall(L, NULL, &rcd, rec_mm_concat_cp); errcode = lj_vm_cpcall(L, NULL, &rcd, rec_mm_concat_cp);
if (errcode) copyTV(L, &errobj, L->top-1); if (errcode) copyTV(L, &errobj, L->top-1);
memcpy(&L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ /* Restore slots. */
memcpy(&L->base[rcd.topslot-1], rcd.savetv, sizeof(rcd.savetv));
if (errcode) { if (errcode) {
L->top = L->base + delta; L->top = L->base + delta;
copyTV(L, L->top++, &errobj); copyTV(L, L->top++, &errobj);

View File

@ -194,6 +194,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
Node *next = nextnode(kn); Node *next = nextnode(kn);
/* Don't use copyTV here, since it asserts on a copy of a dead key. */ /* Don't use copyTV here, since it asserts on a copy of a dead key. */
n->val = kn->val; n->key = kn->key; n->val = kn->val; n->key = kn->key;
if (tvistab(&n->val)) setnilV(&n->val); /* Replace nil value marker. */
setmref(n->next, next == NULL? next : (Node *)((char *)next + d)); setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
} }
} }

View File

@ -222,14 +222,6 @@ static void trace_unpatch(jit_State *J, GCtrace *T)
bc_isret(op), "bad original bytecode %d", op); bc_isret(op), "bad original bytecode %d", op);
*pc = T->startins; *pc = T->startins;
break; break;
case BC_JMP:
lj_assertJ(op == BC_ITERL, "bad original bytecode %d", op);
pc += bc_j(*pc)+2;
if (bc_op(*pc) == BC_JITERL) {
lj_assertJ(traceref(J, bc_d(*pc)) == T, "JITERL references other trace");
*pc = T->startins;
}
break;
case BC_JFUNCF: case BC_JFUNCF:
lj_assertJ(op == BC_FUNCF, "bad original bytecode %d", op); lj_assertJ(op == BC_FUNCF, "bad original bytecode %d", op);
*pc = T->startins; *pc = T->startins;
@ -245,18 +237,19 @@ static void trace_flushroot(jit_State *J, GCtrace *T)
GCproto *pt = &gcref(T->startpt)->pt; GCproto *pt = &gcref(T->startpt)->pt;
lj_assertJ(T->root == 0, "not a root trace"); lj_assertJ(T->root == 0, "not a root trace");
lj_assertJ(pt != NULL, "trace has no prototype"); lj_assertJ(pt != NULL, "trace has no prototype");
/* First unpatch any modified bytecode. */
trace_unpatch(J, T);
/* Unlink root trace from chain anchored in prototype. */ /* Unlink root trace from chain anchored in prototype. */
if (pt->trace == T->traceno) { /* Trace is first in chain. Easy. */ if (pt->trace == T->traceno) { /* Trace is first in chain. Easy. */
pt->trace = T->nextroot; pt->trace = T->nextroot;
unpatch:
/* Unpatch modified bytecode only if the trace has not been flushed. */
trace_unpatch(J, T);
} else if (pt->trace) { /* Otherwise search in chain of root traces. */ } else if (pt->trace) { /* Otherwise search in chain of root traces. */
GCtrace *T2 = traceref(J, pt->trace); GCtrace *T2 = traceref(J, pt->trace);
if (T2) { if (T2) {
for (; T2->nextroot; T2 = traceref(J, T2->nextroot)) for (; T2->nextroot; T2 = traceref(J, T2->nextroot))
if (T2->nextroot == T->traceno) { if (T2->nextroot == T->traceno) {
T2->nextroot = T->nextroot; /* Unlink from chain. */ T2->nextroot = T->nextroot; /* Unlink from chain. */
break; goto unpatch;
} }
} }
} }

View File

@ -35,6 +35,21 @@
#if !LJ_TARGET_CONSOLE #if !LJ_TARGET_CONSOLE
#include <signal.h> #include <signal.h>
#if LJ_TARGET_POSIX
/* Improve signal handling on POSIX. Try CTRL-C on: luajit -e 'io.read()' */
static void signal_set(int sig, void (*h)(int))
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = h;
sigemptyset(&sa.sa_mask);
sigaction(sig, &sa, NULL);
}
#else
#define signal_set signal
#endif
#endif #endif
static lua_State *globalL = NULL; static lua_State *globalL = NULL;
@ -54,8 +69,8 @@ static void lstop(lua_State *L, lua_Debug *ar)
static void laction(int i) static void laction(int i)
{ {
signal(i, SIG_DFL); /* if another SIGINT happens before lstop, /* Terminate process if another SIGINT happens (double CTRL-C). */
terminate process (default action) */ signal_set(i, SIG_DFL);
lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
} }
#endif #endif
@ -117,11 +132,11 @@ static int docall(lua_State *L, int narg, int clear)
lua_pushcfunction(L, traceback); /* push traceback function */ lua_pushcfunction(L, traceback); /* push traceback function */
lua_insert(L, base); /* put it under chunk and args */ lua_insert(L, base); /* put it under chunk and args */
#if !LJ_TARGET_CONSOLE #if !LJ_TARGET_CONSOLE
signal(SIGINT, laction); signal_set(SIGINT, laction);
#endif #endif
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
#if !LJ_TARGET_CONSOLE #if !LJ_TARGET_CONSOLE
signal(SIGINT, SIG_DFL); signal_set(SIGINT, SIG_DFL);
#endif #endif
lua_remove(L, base); /* remove traceback function */ lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection in case of errors */ /* force a complete garbage collection in case of errors */

View File

@ -8,7 +8,8 @@
@rem nogc64 disable LJ_GC64 mode for x64 @rem nogc64 disable LJ_GC64 mode for x64
@rem debug emit debug symbols @rem debug emit debug symbols
@rem amalg amalgamated build @rem amalg amalgamated build
@rem static static linkage @rem static create static lib to statically link into your project
@rem mixed create static lib to build a DLL in your project
@if not defined INCLUDE goto :FAIL @if not defined INCLUDE goto :FAIL
@ -106,12 +107,14 @@ buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
@if "%1"=="static" goto :STATIC @if "%1"=="static" goto :STATIC
%LJCOMPILE% %LJDYNBUILD% lj_*.c lib_*.c %LJCOMPILE% %LJDYNBUILD% lj_*.c lib_*.c
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
@if "%1"=="mixed" goto :STATICLIB
%LJLINK% /DLL /OUT:%LJDLLNAME% lj_*.obj lib_*.obj %LJLINK% /DLL /OUT:%LJDLLNAME% lj_*.obj lib_*.obj
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
@goto :MTDLL @goto :MTDLL
:STATIC :STATIC
%LJCOMPILE% lj_*.c lib_*.c %LJCOMPILE% lj_*.c lib_*.c
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
:STATICLIB
%LJLIB% /OUT:%LJLIBNAME% lj_*.obj lib_*.obj %LJLIB% /OUT:%LJLIBNAME% lj_*.obj lib_*.obj
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
@goto :MTDLL @goto :MTDLL
@ -119,13 +122,15 @@ buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
@if "%2"=="static" goto :AMALGSTATIC @if "%2"=="static" goto :AMALGSTATIC
%LJCOMPILE% %LJDYNBUILD% ljamalg.c %LJCOMPILE% %LJDYNBUILD% ljamalg.c
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
@if "%2"=="mixed" goto :AMALGSTATICLIB
%LJLINK% /DLL /OUT:%LJDLLNAME% ljamalg.obj lj_vm.obj %LJLINK% /DLL /OUT:%LJDLLNAME% ljamalg.obj lj_vm.obj
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
@goto :MTDLL @goto :MTDLL
:AMALGSTATIC :AMALGSTATIC
%LJCOMPILE% ljamalg.c %LJCOMPILE% ljamalg.c
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
%LJLINK% /OUT:%LJDLLNAME% ljamalg.obj lj_vm.obj :AMALGSTATICLIB
%LJLIB% /OUT:%LJLIBNAME% ljamalg.obj lj_vm.obj
@if errorlevel 1 goto :BAD @if errorlevel 1 goto :BAD
:MTDLL :MTDLL
if exist %LJDLLNAME%.manifest^ if exist %LJDLLNAME%.manifest^