Skip to content

Commit

Permalink
Teach frame walker to understand inlines
Browse files Browse the repository at this point in the history
Thus fixing MVM_frame_find_lexical_by_name_rel_caller in the case that
inlining has taken place.
  • Loading branch information
jnthn committed Jul 17, 2018
1 parent 6ae63d2 commit 198f5e4
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 12 deletions.
97 changes: 85 additions & 12 deletions src/spesh/frame_walker.c
Expand Up @@ -21,12 +21,51 @@ void MVM_spesh_frame_walker_init(MVMThreadContext *tc, MVMSpeshFrameWalker *fw,
MVM_gc_root_temp_push(tc, (MVMCollectable **)&(fw->cur_outer_frame));
}

/* Sentinel value to indicate there's no inline to explore. */
#define NO_INLINE -2

/* Go to the next inline, if any. */
static void go_to_next_inline(MVMThreadContext *tc, MVMSpeshFrameWalker *fw) {
MVMFrame *f = fw->cur_caller_frame;
MVMSpeshCandidate *cand = f->spesh_cand;
MVMint32 i;
if (fw->inline_idx == NO_INLINE)
return;
for (i = fw->inline_idx + 1; i < cand->num_inlines; i++) {
if (fw->deopt_offset > cand->inlines[i].start && fw->deopt_offset <= cand->inlines[i].end) {
/* Found an applicable inline. */
fw->inline_idx = i;
return;
}
}

/* No inline available. */
fw->inline_idx = NO_INLINE;
}

/* See if the current frame is specialized, and if so if we are in an inline.
* If so, go to the innermost inline. */
static void go_to_first_inline(MVMThreadContext *tc, MVMSpeshFrameWalker *fw) {
MVMFrame *f = fw->cur_caller_frame;
if (f->spesh_cand && f->spesh_cand->inlines) {
MVMint32 deopt_idx = MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, f);
if (deopt_idx >= 0) {
fw->deopt_offset = f->spesh_cand->deopts[2 * deopt_idx + 1];
fw->inline_idx = -1;
go_to_next_inline(tc, fw);
return;
}
}
fw->inline_idx = NO_INLINE;
}

/* Moves to the next frame to visit. Returns non-zero if there was a next
* frame to move to, and zero if there is not (and as such the iteration is
* over). */
MVMuint32 MVM_spesh_frame_walker_next(MVMThreadContext *tc, MVMSpeshFrameWalker *fw) {
if (!fw->started) {
fw->started = 1;
go_to_first_inline(tc, fw);
return fw->cur_caller_frame ? 1 : 0;
}
else {
Expand All @@ -50,7 +89,15 @@ MVMuint32 MVM_spesh_frame_walker_next(MVMThreadContext *tc, MVMSpeshFrameWalker
/* Otherwise, we're currently visiting a caller, and it's time to try
* visiting its outers if we're meant to do that. */
else if (fw->visit_outers) {
MVMFrame *outer = fw->cur_caller_frame->outer;
MVMFrame *outer;
if (fw->inline_idx == NO_INLINE) {
outer = fw->cur_caller_frame->outer;
}
else {
MVMSpeshInline *i = &(fw->cur_caller_frame->spesh_cand->inlines[fw->inline_idx]);
MVMCode *code = (MVMCode *)fw->cur_caller_frame->work[i->code_ref_reg].o;
outer = code ? code->body.outer : NULL;
}
if (outer) {
fw->cur_outer_frame = outer;
fw->visiting_outers = 1;
Expand All @@ -59,10 +106,21 @@ MVMuint32 MVM_spesh_frame_walker_next(MVMThreadContext *tc, MVMSpeshFrameWalker
}

/* If we get here, we're looking for the next caller, if there is
* one. */
* one. Is there an inline to try and visit? If there is one, then
* we will be placed on it. If there is not one, we will be placed
* on the base frame containing inlines. Either way, we must have
* something to go to. */
if (fw->inline_idx != NO_INLINE) {
go_to_next_inline(tc, fw);
return 1;
}

/* Otherwise, really need to go out one frame, and then maybe go
* to its first inline. */
caller = fw->cur_caller_frame->caller;
if (caller) {
fw->cur_caller_frame = caller;
go_to_first_inline(tc, fw);
return 1;
}

Expand All @@ -71,31 +129,46 @@ MVMuint32 MVM_spesh_frame_walker_next(MVMThreadContext *tc, MVMSpeshFrameWalker
}
}

/* Gets the current frame. */
MVMFrame * get_current_frame(MVMThreadContext *tc, MVMSpeshFrameWalker *fw) {
return fw->visiting_outers ? fw->cur_outer_frame : fw->cur_caller_frame;
}

/* Gets the lexical in the current frame we're visiting, if it declares one.
* Returns zero if there is no such lexical in that current frame. If there is
* one, returns non-zero and populates found_out and found_kind_out. Will also
* trigger vivification of the lexical if needed. */
MVMuint32 MVM_spesh_frame_walker_get_lex(MVMThreadContext *tc, MVMSpeshFrameWalker *fw,
MVMString *name, MVMRegister **found_out,
MVMuint16 *found_kind_out) {
MVMFrame *cur_frame = get_current_frame(tc, fw);
MVMLexicalRegistry *lexical_names = cur_frame->static_info->body.lexical_names;
MVMFrame *cur_frame;
MVMStaticFrame *sf;
MVMuint32 base_index;
MVMLexicalRegistry *lexical_names;
if (fw->visiting_outers) {
cur_frame = fw->cur_outer_frame;
sf = cur_frame->static_info;
base_index = 0;
}
else {
cur_frame = fw->cur_caller_frame;
if (fw->inline_idx == NO_INLINE) {
sf = cur_frame->static_info;
base_index = 0;
}
else {
sf = cur_frame->spesh_cand->inlines[fw->inline_idx].sf;
base_index = cur_frame->spesh_cand->inlines[fw->inline_idx].lexicals_start;
}
}
lexical_names = sf->body.lexical_names;
if (lexical_names) {
/* Indexes were formerly stored off-by-one to avoid semi-predicate issue. */
MVMLexicalRegistry *entry;
MVM_HASH_GET(tc, lexical_names, name, entry)
if (entry) {
MVMRegister *result = &cur_frame->env[entry->value];
MVMuint16 kind = cur_frame->static_info->body.lexical_types[entry->value];
MVMint32 index = base_index + entry->value;
MVMRegister *result = &cur_frame->env[index];
MVMuint16 kind = sf->body.lexical_types[entry->value];
*found_out = result;
*found_kind_out = kind;
if (kind == MVM_reg_obj && !result->o)
MVM_frame_vivify_lexical(tc, cur_frame, entry->value);
MVM_frame_vivify_lexical(tc, cur_frame, index);
return 1;
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/spesh/frame_walker.h
Expand Up @@ -3,6 +3,12 @@ struct MVMSpeshFrameWalker {
/* The current real MVMFrame that we are considering. */
MVMFrame *cur_caller_frame;

/* If we're currently looking through applicable inlines, the deopt offset
* to look for them based on, together with the current inline we are
* looking at. */
MVMint32 deopt_offset;
MVMint32 inline_idx;

/* If we're doing a walk of outer frames too, the current outer frame that
* we are considering starting from the caller frame. */
MVMFrame *cur_outer_frame;
Expand Down

0 comments on commit 198f5e4

Please sign in to comment.