Skip to content

Commit

Permalink
[JIT] Extract JIT interface module
Browse files Browse the repository at this point in the history
Several aspects of the JIT leak out to the rest of the VM, such as:
- finding the correct deopt idx
- finding the active frame handlers
- finding the active set of inlines

I want to contain them in the JIT and so provide a somewhat cleaner
interface, primarily to change that interface to use the new stack
walker.
  • Loading branch information
bdw committed Apr 28, 2018
1 parent d320a43 commit 005b967
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 63 deletions.
4 changes: 3 additions & 1 deletion build/Makefile.in
Expand Up @@ -69,7 +69,8 @@ JIT_OBJECTS = src/jit/graph@obj@ \
src/jit/log@obj@ \
src/jit/expr@obj@ \
src/jit/tile@obj@ \
src/jit/linear_scan@obj@
src/jit/linear_scan@obj@ \
src/jit/interface@obj@


# JIT intermediate files which clean should remove
Expand Down Expand Up @@ -399,6 +400,7 @@ HEADERS = src/moar.h \
src/jit/compile.h \
src/jit/tile.h \
src/jit/register.h \
src/jit/interface.h \
src/jit/log.h \
src/instrument/crossthreadwrite.h \
src/instrument/line_coverage.h \
Expand Down
2 changes: 1 addition & 1 deletion src/6model/reprs/NativeCall.c
Expand Up @@ -90,7 +90,7 @@ static void gc_cleanup(MVMThreadContext *tc, MVMSTable *st, void *data) {
if (body->arg_info)
MVM_free(body->arg_info);
if (body->jitcode)
MVM_jit_destroy_code(tc, body->jitcode);
MVM_jit_code_destroy(tc, body->jitcode);
}

static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/interp.c
Expand Up @@ -5781,7 +5781,7 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
}
/* trampoline back to this opcode */
cur_op -= 2;
MVM_jit_enter_code(tc, cu, tc->cur_frame->spesh_cand->jitcode);
MVM_jit_code_enter(tc, cu, tc->cur_frame->spesh_cand->jitcode);
if (!tc->cur_frame) {
/* somehow unwound our top frame */
goto return_label;
Expand Down
16 changes: 1 addition & 15 deletions src/jit/compile.c
Expand Up @@ -188,7 +188,7 @@ MVMJitCode * MVM_jit_compiler_assemble(MVMThreadContext *tc, MVMJitCompiler *cl,
return code;
}

void MVM_jit_destroy_code(MVMThreadContext *tc, MVMJitCode *code) {
void MVM_jit_code_destroy(MVMThreadContext *tc, MVMJitCode *code) {
MVM_platform_free_pages(code->func_ptr, code->size);
MVM_free(code->labels);
MVM_free(code->deopts);
Expand Down Expand Up @@ -320,17 +320,3 @@ void MVM_jit_spill_memory_release(MVMThreadContext *tc, MVMJitCompiler *compiler
compiler->spills[idx].next = compiler->spills_free[bucket];
compiler->spills_free[bucket] = idx;
}

/* Enter the JIT code segment. The label is a continuation point where control
* is resumed after the frame is properly setup. */
void MVM_jit_enter_code(MVMThreadContext *tc, MVMCompUnit *cu,
MVMJitCode *code) {
void *label = tc->cur_frame->jit_entry_label;
MVMint32 ofs = (char*)label - (char*)code->func_ptr;
if (ofs < 0 || ofs >= code->size)
MVM_oops(tc, "JIT entry label out of range for code!\n"
"(label %p, func_ptr %p, code size %lui, offset %li, frame_nr %i, seq nr %i)",
label, code->func_ptr, code->size, ((char*)label) - ((char*)code->func_ptr),
tc->cur_frame->sequence_nr, code->seq_nr);
code->func_ptr(tc, cu, label);
}
14 changes: 1 addition & 13 deletions src/jit/compile.h
@@ -1,4 +1,3 @@

struct MVMJitCode {
void (*func_ptr)(MVMThreadContext *tc, MVMCompUnit *cu, void * label);
size_t size;
Expand Down Expand Up @@ -29,9 +28,7 @@ struct MVMJitCode {

MVMJitCode* MVM_jit_compile_graph(MVMThreadContext *tc, MVMJitGraph *graph);

void MVM_jit_destroy_code(MVMThreadContext *tc, MVMJitCode *code);
void MVM_jit_enter_code(MVMThreadContext *tc, MVMCompUnit *cu,
MVMJitCode * code);
void MVM_jit_code_destroy(MVMThreadContext *tc, MVMJitCode *code);

/* Peseudotile compile functions */
void MVM_jit_compile_label(MVMThreadContext *tc, MVMJitCompiler *compiler,
Expand All @@ -50,12 +47,3 @@ void MVM_jit_compile_memory_copy(MVMThreadContext *tc, MVMJitCompiler *compiler,
MVMJitTile *tile, MVMJitExprTree *tree);
void MVM_jit_compile_guard(MVMThreadContext *tc, MVMJitCompiler *compiler,
MVMJitTile *tile, MVMJitExprTree *tree);

/* Function for getting effective (JIT/specialized/original) bytecode. */
MVM_STATIC_INLINE MVMuint8 * MVM_frame_effective_bytecode(MVMFrame *f) {
MVMSpeshCandidate *spesh_cand = f->spesh_cand;
if (spesh_cand)
return spesh_cand->jitcode ? spesh_cand->jitcode->bytecode : spesh_cand->bytecode;
return f->static_info->body.bytecode;
}

48 changes: 48 additions & 0 deletions src/jit/interface.c
@@ -0,0 +1,48 @@
#include "moar.h"
#include "internal.h"

void * stack_find_return_address(void *base, void *end, MVMint64 depth);

/* Enter the JIT code segment. The label is a continuation point where control
* is resumed after the frame is properly setup. */
void MVM_jit_code_enter(MVMThreadContext *tc, MVMCompUnit *cu,
MVMJitCode *code) {
void *label = tc->cur_frame->jit_entry_label;
MVMint32 ofs = (char*)label - (char*)code->func_ptr;
if (ofs < 0 || ofs >= code->size)
MVM_oops(tc, "JIT entry label out of range for code!\n"
"(label %p, func_ptr %p, code size %lui, offset %li, frame_nr %i, seq nr %i)",
label, code->func_ptr, code->size, ((char*)label) - ((char*)code->func_ptr),
tc->cur_frame->sequence_nr, code->seq_nr);
code->func_ptr(tc, cu, label);
}

MVMint32 MVM_jit_code_get_active_handlers(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, MVMint32 *handlers_out) {
MVMint32 i;
MVMint32 j = 0;
void *current_position = frame->jit_entry_label;
fprintf(stderr, "Get active deopt idx: %" PRIx64 "\n", current_position);
for (i = 0; i < code->num_handlers; i++) {
void *start_label = code->labels[code->handlers[i].start_label];
void *end_label = code->labels[code->handlers[i].end_label];
if (start_label <= current_position && end_label >= current_position) {
handlers_out[j++] = i;
}
}
return j;
}

MVMint32 MVM_jit_code_get_active_deopt_idx(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame) {
MVMint32 i;
void *current_position = frame->jit_entry_label;
for (i = 0; i < code->num_deopts; i++) {
if (code->labels[code->deopts[i].label] == current_position) {
break;
}
}
return i;
}

MVMint32 MVM_jit_code_get_active_inlines(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, MVMint32 *inlines) {
return 0;
}
12 changes: 12 additions & 0 deletions src/jit/interface.h
@@ -0,0 +1,12 @@
/* Function for getting effective (JIT/specialized/original) bytecode. */
MVM_STATIC_INLINE MVMuint8 * MVM_frame_effective_bytecode(MVMFrame *f) {
MVMSpeshCandidate *spesh_cand = f->spesh_cand;
if (spesh_cand)
return spesh_cand->jitcode ? spesh_cand->jitcode->bytecode : spesh_cand->bytecode;
return f->static_info->body.bytecode;
}

void MVM_jit_code_enter(MVMThreadContext *tc, MVMCompUnit *cu, MVMJitCode * code);
MVMint32 MVM_jit_code_get_active_handlers(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, MVMint32 *handlers);
MVMint32 MVM_jit_code_get_active_deopt_idx(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame);
MVMint32 MVM_jit_code_get_active_inlines(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, MVMint32 *inlines);
16 changes: 14 additions & 2 deletions src/jit/stub.c
Expand Up @@ -17,10 +17,22 @@ void MVM_jit_graph_destroy(MVMThreadContext *tc, MVMJitGraph *graph) {
return;
}

void MVM_jit_destroy_code(MVMThreadContext *tc, MVMJitCode *code) {
void MVM_jit_code_destroy(MVMThreadContext *tc, MVMJitCode *code) {
return;
}

void MVM_jit_enter_code(MVMThreadContext *tc, MVMCompUnit *cu, MVMJitCode *code) {
void MVM_jit_code_enter(MVMThreadContext *tc, MVMCompUnit *cu, MVMJitCode *code) {
return;
}

MVMint32 MVM_jit_code_get_active_handlers(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, MVMint32 *handlers) {
return 0;
}

MVMint32 MVM_jit_code_get_active_inlines(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, MVMint32 *inlines) {
return 0;
}

MVMint32 MVM_jit_code_get_active_deopt_idx(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame) {
return 0;
}
1 change: 1 addition & 0 deletions src/moar.h
Expand Up @@ -198,6 +198,7 @@ MVM_PUBLIC const MVMint32 MVM_jit_support(void);
#include "jit/tile.h"
#include "jit/compile.h"
#include "jit/log.h"
#include "jit/interface.h"
#include "profiler/instrument.h"
#include "profiler/log.h"
#include "profiler/profile.h"
Expand Down
2 changes: 1 addition & 1 deletion src/spesh/candidate.c
Expand Up @@ -179,5 +179,5 @@ void MVM_spesh_candidate_destroy(MVMThreadContext *tc, MVMSpeshCandidate *candid
MVM_free(candidate->local_types);
MVM_free(candidate->lexical_types);
if (candidate->jitcode)
MVM_jit_destroy_code(tc, candidate->jitcode);
MVM_jit_code_destroy(tc, candidate->jitcode);
}
54 changes: 25 additions & 29 deletions src/spesh/deopt.c
Expand Up @@ -260,40 +260,36 @@ void MVM_spesh_deopt_all(MVMThreadContext *tc) {
if (f->spesh_cand) {
/* Found one. Is it JITted code? */
if (f->spesh_cand->jitcode && f->jit_entry_label) {
MVMint32 num_deopts = f->spesh_cand->jitcode->num_deopts;
MVMJitDeopt *deopts = f->spesh_cand->jitcode->deopts;
void **labels = f->spesh_cand->jitcode->labels;
MVMint32 i;
for (i = 0; i < num_deopts; i++) {
if (labels[deopts[i].label] == f->jit_entry_label) {
/* Resolve offset and target. */
MVMint32 deopt_idx = deopts[i].idx;
MVMint32 deopt_offset = f->spesh_cand->deopts[2 * deopt_idx + 1];
MVMint32 deopt_target = f->spesh_cand->deopts[2 * deopt_idx];
MVMJitCode *jitcode = f->spesh_cand->jitcode;
MVMint32 idx = MVM_jit_code_get_active_deopt_idx(tc, jitcode, f);
if (idx < jitcode->num_deopts) {
/* Resolve offset and target. */
MVMint32 deopt_idx = jitcode->deopts[idx].idx;
MVMint32 deopt_offset = f->spesh_cand->deopts[2 * deopt_idx + 1];
MVMint32 deopt_target = f->spesh_cand->deopts[2 * deopt_idx];
#if MVM_LOG_DEOPTS
fprintf(stderr, "Found deopt label for JIT (%d) (label %d idx %d)\n", i,
deopts[i].label, deopts[i].idx);
fprintf(stderr, "Found deopt label for JIT (%d) (label %d idx %d)\n", i,
deopts[i].label, deopts[i].idx);
#endif

/* Re-create any frames needed if we're in an inline; if not,
* just update return address. */
if (f->spesh_cand->inlines) {
MVMROOT2(tc, f, l, {
uninline(tc, f, f->spesh_cand, deopt_offset, deopt_target, l);
});
}
else {
f->return_address = f->static_info->body.bytecode + deopt_target;
}
/* Re-create any frames needed if we're in an inline; if not,
* just update return address. */
if (f->spesh_cand->inlines) {
MVMROOT2(tc, f, l, {
uninline(tc, f, f->spesh_cand, deopt_offset, deopt_target, l);
});
}
else {
f->return_address = f->static_info->body.bytecode + deopt_target;
}

/* No spesh cand/slots needed now. */
deopt_named_args_used(tc, f);
f->effective_spesh_slots = NULL;
f->spesh_cand = NULL;
f->jit_entry_label = NULL;
/* No spesh cand/slots needed now. */
deopt_named_args_used(tc, f);
f->effective_spesh_slots = NULL;
f->spesh_cand = NULL;
f->jit_entry_label = NULL;

break;
}
break;
}
#if MVM_LOG_DEOPTS
if (i == num_deopts)
Expand Down

0 comments on commit 005b967

Please sign in to comment.