From a35c6fdc42bb31f5e8bf743c94366341ad700595 Mon Sep 17 00:00:00 2001 From: Nickolas Lloyd Date: Fri, 23 Dec 2016 16:21:19 -0500 Subject: [PATCH] ; Fix a possible bug with JIT-compiled functions in the call stack * src/bytecode-jit.c (jit_byte_code__, jit_exec): Insert entry into `byte_stack_list' from `jit_exec' instead of `jit_byte_code__'. It seems like this would be needed for proper stack unwinding in `unwind_to_catch'. * src/bytecode.c (relocate_byte_stack) [HAVE_LIBJIT]: Skip entries in `byte_stack_list' with no associated bytecode stack. --- src/bytecode-jit.c | 40 +++++++++++++++++++--------------------- src/bytecode.c | 4 ++++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/bytecode-jit.c b/src/bytecode-jit.c index 6faa972b686..28269fe87f1 100644 --- a/src/bytecode-jit.c +++ b/src/bytecode-jit.c @@ -32,11 +32,7 @@ along with GNU Emacs. If not, see . */ /* Fetch the next byte from the bytecode stream. */ -#if BYTE_CODE_SAFE -#define FETCH (eassert (stack.byte_string_start == SDATA (stack.byte_string)), *stack.pc++) -#else -#define FETCH *stack.pc++ -#endif +#define FETCH *pc++ /* Fetch two bytes from the bytecode stream and make a 16-bit number out of them. */ @@ -660,7 +656,15 @@ jit_exec (Lisp_Object byte_code, Lisp_Object args_template, ptrdiff_t nargs, Lis { Lisp_Object (*func)(Lisp_Object *) = (Lisp_Object (*)(Lisp_Object *))AREF (byte_code, COMPILED_JIT_ID); - return func (top); + /* We don't actually need to use this structure to keep track of a + stack, since our stack isn't GCed. We just need to use it as a + placeholder in `byte_stack_list' to facilitate proper unwinding. */ + struct byte_stack stack = {}; + stack.next = byte_stack_list; + byte_stack_list = &stack; + Lisp_Object ret = func (top); + byte_stack_list = byte_stack_list->next; + return ret; } } @@ -675,13 +679,14 @@ jit_byte_code__ (Lisp_Object byte_code) Lisp_Object *stacke; #endif ptrdiff_t bytestr_length; - struct byte_stack stack; Lisp_Object bytestr; Lisp_Object vector; Lisp_Object maxdepth; Lisp_Object *top; enum handlertype type; + unsigned char *byte_string_start, *pc; + /* jit-specific variables */ jit_function_t this_func; jit_type_t params[1]; @@ -725,15 +730,9 @@ jit_byte_code__ (Lisp_Object byte_code) bytestr_length = SBYTES (bytestr); vectorp = XVECTOR (vector)->contents; - stack.byte_string = bytestr; - stack.pc = stack.byte_string_start = SDATA (bytestr); + pc = byte_string_start = SDATA (bytestr); if (MAX_ALLOCA / word_size <= XFASTINT (maxdepth)) memory_full (SIZE_MAX); -#if BYTE_MAINTAIN_TOP - stack.top = NULL; -#endif - stack.next = byte_stack_list; - byte_stack_list = &stack; /* prepare for jit */ jit_context_build_start (jit_context); @@ -752,7 +751,7 @@ jit_byte_code__ (Lisp_Object byte_code) labels[i] = jit_label_undefined; } - while (stack.pc < stack.byte_string_start + bytestr_length) + while (pc < byte_string_start + bytestr_length) { #ifndef BYTE_CODE_THREADED op = FETCH; @@ -773,7 +772,7 @@ jit_byte_code__ (Lisp_Object byte_code) plain break. */ #define NEXT \ do { \ - if (stack.pc >= stack.byte_string_start + bytestr_length) \ + if (pc >= byte_string_start + bytestr_length) \ goto exit; \ else \ { \ @@ -837,7 +836,7 @@ jit_byte_code__ (Lisp_Object byte_code) #endif -#define JIT_PC (stack.pc - stack.byte_string_start) +#define JIT_PC (pc - byte_string_start) #define JIT_NEED_STACK jit_value_ref (this_func, stackv) #define JIT_NEXT \ do { \ @@ -1175,7 +1174,7 @@ jit_byte_code__ (Lisp_Object byte_code) else { op = FETCH - 128; - op += (stack.pc - stack.byte_string_start); + op += (pc - byte_string_start); } CHECK_RANGE (op); JIT_NEED_STACK; @@ -1202,7 +1201,7 @@ jit_byte_code__ (Lisp_Object byte_code) CASE (BRgoto): { op = FETCH - 128; - const int dest = (stack.pc - stack.byte_string_start) + op; + const int dest = (pc - byte_string_start) + op; JIT_CALL (byte_code_quit, NULL, 0); jit_insn_branch ( this_func, @@ -1997,7 +1996,7 @@ jit_byte_code__ (Lisp_Object byte_code) call3 (Qerror, build_string ("Invalid byte opcode: op=%s, ptr=%d"), make_number (op), - make_number ((stack.pc - 1) - stack.byte_string_start)); + make_number (pc - 1 - byte_string_start)); /* Handy byte-codes for lexical binding. */ CASE (Bstack_ref1): @@ -2079,7 +2078,6 @@ jit_byte_code__ (Lisp_Object byte_code) } exit: - byte_stack_list = byte_stack_list->next; { int err = !jit_function_compile (this_func); diff --git a/src/bytecode.c b/src/bytecode.c index 6567039765d..26860daec10 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -66,6 +66,10 @@ relocate_byte_stack (struct byte_stack *stack) { for (; stack; stack = stack->next) { +#ifdef HAVE_LIBJIT + if (!stack->byte_string_start) + continue; +#endif if (stack->byte_string_start != SDATA (stack->byte_string)) { ptrdiff_t offset = stack->pc - stack->byte_string_start; -- 2.39.5