Skip to content

Commit

Permalink
[JIT] Improve stack walker to use top-of-stack
Browse files Browse the repository at this point in the history
It is impractical to know how many frames we can walk back safely, and
we want to fail safely for the case that we are wrong (i.e. jit code
frame is not on stack),

Force -fno-omit-frame-pointer if the JIT is active. GNU make
automatically uses on the correct invocation of 'as', so that helps, but
I'm not sure how I'm going to configure MSVC just yet (uses ml64).
  • Loading branch information
bdw committed Apr 27, 2018
1 parent 5ae2b27 commit 451d6e4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 24 deletions.
16 changes: 14 additions & 2 deletions Configure.pl
Expand Up @@ -17,6 +17,11 @@
sub defined_or($$) {
defined $_[0] ? $_[0] : $_[1]
}
# This allows us to run on broken perls
sub uniq {
my %s; grep { !$s{$_}++ } @_;
}


my $NAME = 'moar';
my $GENLIST = 'build/gen.list';
Expand Down Expand Up @@ -160,6 +165,8 @@ ($$)
$config{lddebugflags} = $config{ccdebugflags} unless defined $config{lddebugflags};
$config{ldinstflags} = $config{ccinstflags} unless defined $config{ldinstflags};

$config{as} = $config{cc} unless defined $config{as};

# Probe the compiler.
build::probe::compiler_usability(\%config, \%defaults);

Expand Down Expand Up @@ -361,7 +368,12 @@ ($$)
? '-Rpass=loop-vectorize'
: $config{cc} eq 'gcc'
? '-fopt-info-vec-optimized'
: die if $args{'show-autovect'};
: die if $args{'show-autovect'};
# TODO - we need to do -fno-omit-frame-pointer anyway if we run the JIT
push @cflags, $config{cc} eq 'cl' ? '/Oy' :
($config{cc} eq 'gcc' || $config{cc} eq 'clang') ? '-fno-omit-frame-pointer' : ()
if $args{jit};

if (exists $args{'show-autovect-failed'}) {
push @cflags, '-Rpass-missed=loop-vectorize' if $config{cc} eq 'clang';
push @cflags, ("-ftree-vectorizer-verbose=" . ($args{'show-autovect-failed'} || 1), "-fopt-info-vec-missed")
Expand All @@ -381,7 +393,7 @@ ($$)
push @cflags, '-DWORDS_BIGENDIAN' if $config{be}; # 3rdparty/sha1 needs it and it isnt set on mips;
push @cflags, $ENV{CFLAGS} if $ENV{CFLAGS};
push @cflags, $ENV{CPPFLAGS} if $ENV{CPPFLAGS};
$config{cflags} = join ' ', @cflags;
$config{cflags} = join ' ', uniq(@cflags);

# generate LDFLAGS
my @ldflags = ($config{ldmiscflags});
Expand Down
4 changes: 3 additions & 1 deletion src/jit/interface.c
@@ -1,7 +1,9 @@
#include "moar.h"
#include "internal.h"

void * stack_find_return_address(void *base, void *end, MVMint64 depth);
/* Walk stack to find the current return address in a code frame */
void * stack_find_return_address_posix(void *base, size_t size, void *top);
void * stack_find_return_address_win64(void *base, size_t size, void *top);

/* Enter the JIT code segment. The label is a continuation point where control
* is resumed after the frame is properly setup. */
Expand Down
44 changes: 23 additions & 21 deletions src/jit/x64/stack_walk.s
@@ -1,26 +1,28 @@
.intel_syntax noprefix
.text
.globl stack_find_return_address_in_frame_posix
.globl _stack_find_return_address_in_frame_posix
.intel_syntax noprefix
.text
.globl stack_find_return_address_in_frame_posix
.globl _stack_find_return_address_in_frame_posix
stack_find_return_address_in_frame_posix:
_stack_find_return_address_in_frame_posix:
mov rcx, rdi /* base pointer */
mov r8, rdx /* maximum number of steps */
mov rdx, rsi /* end pointer */
mov rcx, rdi /* arg0 = start-of-code region */
mov r8, rdx /* arg2 = stack base-pointer */
mov rdx, rsi /* arg1 = size-of-code */
_stack_find_return_address_in_frame_win64:
/* rdi = base pointer, rsi = end pointer */
push rbp
mov r9, rsp
push rbp
mov r9, rsp
add rdx, rcx /* compute end-of-code region */
/* rcx = start, rdx = end, r8 = stack base,
* r9 = next stack frame, ax = return address */
loop:
dec r8 /* counter */
jz done
mov rax, qword ptr [r9+0x8]
mov r9, qword ptr [r9]
cmp rax, rcx
jl loop
cmp rax, rdx
jg loop
cmp r8, r9 /* have we gone past our start-of-stack pointer? */
jle done /* stack grows downwards */
mov rax, qword ptr [r9+0x8]
mov r9, qword ptr [r9]
cmp rax, rcx
jl loop
cmp rax, rdx
jg loop
done:
/* rax is now within range by definition, or, we're to deep */
pop rbp
ret
/* rax is now within range by definition, or, we're to deep */
pop rbp
ret

0 comments on commit 451d6e4

Please sign in to comment.