aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_alloc.c52
-rw-r--r--src/lj_dispatch.c4
-rw-r--r--src/lj_dispatch.h17
-rw-r--r--src/lj_trace.c4
4 files changed, 72 insertions, 5 deletions
diff --git a/src/lj_alloc.c b/src/lj_alloc.c
index 2f3fb473..8d4edb5e 100644
--- a/src/lj_alloc.c
+++ b/src/lj_alloc.c
@@ -23,7 +23,7 @@
23#define lj_alloc_c 23#define lj_alloc_c
24#define LUA_CORE 24#define LUA_CORE
25 25
26/* To get the mremap prototype. Must be defind before any system includes. */ 26/* To get the mremap prototype. Must be defined before any system includes. */
27#if defined(__linux__) && !defined(_GNU_SOURCE) 27#if defined(__linux__) && !defined(_GNU_SOURCE)
28#define _GNU_SOURCE 28#define _GNU_SOURCE
29#endif 29#endif
@@ -98,18 +98,22 @@ static void INIT_MMAP(void)
98/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ 98/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
99static LJ_AINLINE void *CALL_MMAP(size_t size) 99static LJ_AINLINE void *CALL_MMAP(size_t size)
100{ 100{
101 DWORD olderr = GetLastError();
101 void *ptr = NULL; 102 void *ptr = NULL;
102 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, 103 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size,
103 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 104 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
105 SetLastError(olderr);
104 return st == 0 ? ptr : MFAIL; 106 return st == 0 ? ptr : MFAIL;
105} 107}
106 108
107/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ 109/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
108static LJ_AINLINE void *DIRECT_MMAP(size_t size) 110static LJ_AINLINE void *DIRECT_MMAP(size_t size)
109{ 111{
112 DWORD olderr = GetLastError();
110 void *ptr = NULL; 113 void *ptr = NULL;
111 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, 114 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size,
112 MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); 115 MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE);
116 SetLastError(olderr);
113 return st == 0 ? ptr : MFAIL; 117 return st == 0 ? ptr : MFAIL;
114} 118}
115 119
@@ -120,15 +124,19 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
120/* Win32 MMAP via VirtualAlloc */ 124/* Win32 MMAP via VirtualAlloc */
121static LJ_AINLINE void *CALL_MMAP(size_t size) 125static LJ_AINLINE void *CALL_MMAP(size_t size)
122{ 126{
127 DWORD olderr = GetLastError();
123 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 128 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
129 SetLastError(olderr);
124 return ptr ? ptr : MFAIL; 130 return ptr ? ptr : MFAIL;
125} 131}
126 132
127/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ 133/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
128static LJ_AINLINE void *DIRECT_MMAP(size_t size) 134static LJ_AINLINE void *DIRECT_MMAP(size_t size)
129{ 135{
136 DWORD olderr = GetLastError();
130 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, 137 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
131 PAGE_READWRITE); 138 PAGE_READWRITE);
139 SetLastError(olderr);
132 return ptr ? ptr : MFAIL; 140 return ptr ? ptr : MFAIL;
133} 141}
134 142
@@ -137,6 +145,7 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
137/* This function supports releasing coalesed segments */ 145/* This function supports releasing coalesed segments */
138static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) 146static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
139{ 147{
148 DWORD olderr = GetLastError();
140 MEMORY_BASIC_INFORMATION minfo; 149 MEMORY_BASIC_INFORMATION minfo;
141 char *cptr = (char *)ptr; 150 char *cptr = (char *)ptr;
142 while (size) { 151 while (size) {
@@ -150,11 +159,13 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
150 cptr += minfo.RegionSize; 159 cptr += minfo.RegionSize;
151 size -= minfo.RegionSize; 160 size -= minfo.RegionSize;
152 } 161 }
162 SetLastError(olderr);
153 return 0; 163 return 0;
154} 164}
155 165
156#else 166#else
157 167
168#include <errno.h>
158#include <sys/mman.h> 169#include <sys/mman.h>
159 170
160#define MMAP_PROT (PROT_READ|PROT_WRITE) 171#define MMAP_PROT (PROT_READ|PROT_WRITE)
@@ -169,7 +180,13 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
169#if LJ_TARGET_LINUX 180#if LJ_TARGET_LINUX
170 181
171/* Actually this only gives us max. 1GB in current Linux kernels. */ 182/* Actually this only gives us max. 1GB in current Linux kernels. */
172#define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0) 183static LJ_AINLINE void *CALL_MMAP(size_t size)
184{
185 int olderr = errno;
186 void *ptr = mmap(NULL, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
187 errno = olderr;
188 return ptr;
189}
173 190
174#elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 191#elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
175 192
@@ -188,6 +205,7 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
188 205
189static LJ_AINLINE void *CALL_MMAP(size_t size) 206static LJ_AINLINE void *CALL_MMAP(size_t size)
190{ 207{
208 int olderr = errno;
191 /* Hint for next allocation. Doesn't need to be thread-safe. */ 209 /* Hint for next allocation. Doesn't need to be thread-safe. */
192 static uintptr_t alloc_hint = MMAP_REGION_START; 210 static uintptr_t alloc_hint = MMAP_REGION_START;
193 int retry = 0; 211 int retry = 0;
@@ -205,6 +223,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
205 if ((uintptr_t)p >= MMAP_REGION_START && 223 if ((uintptr_t)p >= MMAP_REGION_START &&
206 (uintptr_t)p + size < MMAP_REGION_END) { 224 (uintptr_t)p + size < MMAP_REGION_END) {
207 alloc_hint = (uintptr_t)p + size; 225 alloc_hint = (uintptr_t)p + size;
226 errno = olderr;
208 return p; 227 return p;
209 } 228 }
210 if (p != CMFAIL) munmap(p, size); 229 if (p != CMFAIL) munmap(p, size);
@@ -212,6 +231,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
212 retry = 1; 231 retry = 1;
213 alloc_hint = MMAP_REGION_START; 232 alloc_hint = MMAP_REGION_START;
214 } 233 }
234 errno = olderr;
215 return CMFAIL; 235 return CMFAIL;
216} 236}
217 237
@@ -224,17 +244,39 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
224#else 244#else
225 245
226/* 32 bit mode is easy. */ 246/* 32 bit mode is easy. */
227#define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) 247static LJ_AINLINE void *CALL_MMAP(size_t size)
248{
249 int olderr = errno;
250 void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
251 errno = olderr;
252 return ptr;
253}
228 254
229#endif 255#endif
230 256
231#define INIT_MMAP() ((void)0) 257#define INIT_MMAP() ((void)0)
232#define DIRECT_MMAP(s) CALL_MMAP(s) 258#define DIRECT_MMAP(s) CALL_MMAP(s)
233#define CALL_MUNMAP(a, s) munmap((a), (s)) 259
260static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
261{
262 int olderr = errno;
263 int ret = munmap(ptr, size);
264 errno = olderr;
265 return ret;
266}
234 267
235#if LJ_TARGET_LINUX 268#if LJ_TARGET_LINUX
236/* Need to define _GNU_SOURCE to get the mremap prototype. */ 269/* Need to define _GNU_SOURCE to get the mremap prototype. */
237#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) 270static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
271 int flags)
272{
273 int olderr = errno;
274 ptr = mremap(ptr, osz, nsz, flags);
275 errno = olderr;
276 return ptr;
277}
278
279#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
238#define CALL_MREMAP_NOMOVE 0 280#define CALL_MREMAP_NOMOVE 0
239#define CALL_MREMAP_MAYMOVE 1 281#define CALL_MREMAP_MAYMOVE 1
240#if LJ_64 282#if LJ_64
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index 0b14e21c..42027e7d 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -348,6 +348,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres)
348/* Instruction dispatch. Used by instr/line/return hooks or when recording. */ 348/* Instruction dispatch. Used by instr/line/return hooks or when recording. */
349void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) 349void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
350{ 350{
351 ERRNO_SAVE
351 GCfunc *fn = curr_func(L); 352 GCfunc *fn = curr_func(L);
352 GCproto *pt = funcproto(fn); 353 GCproto *pt = funcproto(fn);
353 void *cf = cframe_raw(L->cframe); 354 void *cf = cframe_raw(L->cframe);
@@ -382,6 +383,7 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc)
382 } 383 }
383 if ((g->hookmask & LUA_MASKRET) && bc_isret(bc_op(pc[-1]))) 384 if ((g->hookmask & LUA_MASKRET) && bc_isret(bc_op(pc[-1])))
384 callhook(L, LUA_HOOKRET, -1); 385 callhook(L, LUA_HOOKRET, -1);
386 ERRNO_RESTORE
385} 387}
386 388
387/* Initialize call. Ensure stack space and return # of missing parameters. */ 389/* Initialize call. Ensure stack space and return # of missing parameters. */
@@ -405,6 +407,7 @@ static int call_init(lua_State *L, GCfunc *fn)
405/* Call dispatch. Used by call hooks, hot calls or when recording. */ 407/* Call dispatch. Used by call hooks, hot calls or when recording. */
406ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc) 408ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc)
407{ 409{
410 ERRNO_SAVE
408 GCfunc *fn = curr_func(L); 411 GCfunc *fn = curr_func(L);
409 BCOp op; 412 BCOp op;
410 global_State *g = G(L); 413 global_State *g = G(L);
@@ -443,6 +446,7 @@ out:
443 (op == BC_FUNCF || op == BC_FUNCV)) 446 (op == BC_FUNCF || op == BC_FUNCV))
444 op = (BCOp)((int)op+(int)BC_IFUNCF-(int)BC_FUNCF); 447 op = (BCOp)((int)op+(int)BC_IFUNCF-(int)BC_FUNCF);
445#endif 448#endif
449 ERRNO_RESTORE
446 return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ 450 return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */
447} 451}
448 452
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h
index 3ba983a8..dd4f68fe 100644
--- a/src/lj_dispatch.h
+++ b/src/lj_dispatch.h
@@ -69,4 +69,21 @@ LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc);
69LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc); 69LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc);
70LJ_FUNCA void LJ_FASTCALL lj_dispatch_return(lua_State *L, const BCIns *pc); 70LJ_FUNCA void LJ_FASTCALL lj_dispatch_return(lua_State *L, const BCIns *pc);
71 71
72#if LJ_HASFFI && !defined(_BUILDVM_H)
73/* Save/restore errno and GetLastError() around hooks, exits and recording. */
74#include <errno.h>
75#if LJ_TARGET_WINDOWS
76#define WIN32_LEAN_AND_MEAN
77#include <windows.h>
78#define ERRNO_SAVE int olderr = errno; DWORD oldwerr = GetLastError();
79#define ERRNO_RESTORE errno = olderr; SetLastError(oldwerr);
80#else
81#define ERRNO_SAVE int olderr = errno;
82#define ERRNO_RESTORE errno = olderr;
83#endif
84#else
85#define ERRNO_SAVE
86#define ERRNO_RESTORE
87#endif
88
72#endif 89#endif
diff --git a/src/lj_trace.c b/src/lj_trace.c
index 69124542..ab75c9d2 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -638,6 +638,7 @@ void lj_trace_ins(jit_State *J, const BCIns *pc)
638/* A hotcount triggered. Start recording a root trace. */ 638/* A hotcount triggered. Start recording a root trace. */
639void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc) 639void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc)
640{ 640{
641 ERRNO_SAVE
641 /* Note: pc is the interpreter bytecode PC here. It's offset by 1. */ 642 /* Note: pc is the interpreter bytecode PC here. It's offset by 1. */
642 hotcount_set(J2GG(J), pc, J->param[JIT_P_hotloop]+1); /* Reset hotcount. */ 643 hotcount_set(J2GG(J), pc, J->param[JIT_P_hotloop]+1); /* Reset hotcount. */
643 /* Only start a new trace if not recording or inside __gc call or vmevent. */ 644 /* Only start a new trace if not recording or inside __gc call or vmevent. */
@@ -648,6 +649,7 @@ void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc)
648 J->state = LJ_TRACE_START; 649 J->state = LJ_TRACE_START;
649 lj_trace_ins(J, pc-1); 650 lj_trace_ins(J, pc-1);
650 } 651 }
652 ERRNO_RESTORE
651} 653}
652 654
653/* Check for a hot side exit. If yes, start recording a side trace. */ 655/* Check for a hot side exit. If yes, start recording a side trace. */
@@ -684,6 +686,7 @@ static TValue *trace_exit_cp(lua_State *L, lua_CFunction dummy, void *ud)
684/* A trace exited. Restore interpreter state. */ 686/* A trace exited. Restore interpreter state. */
685int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) 687int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
686{ 688{
689 ERRNO_SAVE
687 lua_State *L = J->L; 690 lua_State *L = J->L;
688 ExitDataCP exd; 691 ExitDataCP exd;
689 int errcode; 692 int errcode;
@@ -738,6 +741,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
738 } 741 }
739 } 742 }
740 /* Return MULTRES or 0. */ 743 /* Return MULTRES or 0. */
744 ERRNO_RESTORE
741 switch (bc_op(*pc)) { 745 switch (bc_op(*pc)) {
742 case BC_CALLM: case BC_CALLMT: 746 case BC_CALLM: case BC_CALLMT:
743 return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); 747 return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc));