Skip to content

Commit

Permalink
Store deopt one target directly in bytecode.
Browse files Browse the repository at this point in the history
Rather than needing to use the offsets to resolve them each deopt.
This brings the interpreted approach in line with what the JIT does,
but further to that it means that we can have a sequence of guards
that will deopt to the same place, which will be used for upcoming
improvements to invocation specialization.
  • Loading branch information
jnthn committed Aug 2, 2017
1 parent 99332f2 commit 0585b8d
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 64 deletions.
55 changes: 29 additions & 26 deletions lib/MAST/Ops.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -770,25 +770,24 @@ BEGIN {
1914,
1918,
1921,
1923,
1925,
1924,
1927,
1929,
1931,
1933,
1935,
1937,
1939,
1941,
1943,
1945,
1930,
1932,
1934,
1936,
1938,
1940,
1942,
1944,
1946,
1948,
1951,
1954,
1957,
1958,
1960,
1964,
1961,
1963,
1967,
1970,
1973,
Expand All @@ -805,8 +804,8 @@ BEGIN {
2006,
2009,
2012,
2016,
2020,
2015,
2019,
2023,
2026,
2029,
Expand All @@ -818,17 +817,18 @@ BEGIN {
2047,
2050,
2053,
2054,
2056,
2058,
2060,
2060,
2060,
2057,
2059,
2061,
2062,
2062,
2063,
2065);
2063,
2063,
2064,
2065,
2065,
2066,
2068);
MAST::Ops.WHO<@counts> := nqp::list_i(0,
2,
2,
Expand Down Expand Up @@ -1595,9 +1595,9 @@ BEGIN {
4,
4,
3,
2,
2,
2,
3,
3,
3,
2,
2,
2,
Expand Down Expand Up @@ -3578,10 +3578,13 @@ BEGIN {
33,
65,
128,
152,
65,
128,
152,
65,
128,
152,
66,
65,
66,
Expand Down
12 changes: 6 additions & 6 deletions src/core/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5165,27 +5165,27 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
MVMObject *check = GET_REG(cur_op, 0).o;
MVMSTable *want = (MVMSTable *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 4;
cur_op += 8;
if (!check || STABLE(check) != want)
MVM_spesh_deopt_one(tc);
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardconc): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMSTable *want = (MVMSTable *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 4;
cur_op += 8;
if (!check || !IS_CONCRETE(check) || STABLE(check) != want)
MVM_spesh_deopt_one(tc);
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardtype): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMSTable *want = (MVMSTable *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 4;
cur_op += 8;
if (!check || IS_CONCRETE(check) || STABLE(check) != want)
MVM_spesh_deopt_one(tc);
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_decont): {
Expand Down
6 changes: 3 additions & 3 deletions src/core/oplist
Original file line number Diff line number Diff line change
Expand Up @@ -821,9 +821,9 @@ decodertakecharseof w(str) r(obj) r(int64)
# guard = guard on type only; index is spesh slot with type
# guardconc = guard on type + concrete; index is spesh slot with type
# guardtype = guard on type + type object; index is spesh slot with type
sp_guard .s r(obj) sslot
sp_guardconc .s r(obj) sslot
sp_guardtype .s r(obj) sslot
sp_guard .s r(obj) sslot uint32
sp_guardconc .s r(obj) sslot uint32
sp_guardtype .s r(obj) sslot uint32

# These are variants of the normal interpreted ops that do not log. Used for
# the case where we can't JIT-compile, but don't want to keep on logging.
Expand Down
12 changes: 6 additions & 6 deletions src/core/ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -9189,37 +9189,37 @@ static const MVMOpInfo MVM_op_infos[] = {
MVM_OP_sp_guard,
"sp_guard",
".s",
2,
3,
0,
0,
0,
0,
0,
{ MVM_operand_read_reg | MVM_operand_obj, MVM_operand_spesh_slot }
{ MVM_operand_read_reg | MVM_operand_obj, MVM_operand_spesh_slot, MVM_operand_uint32 }
},
{
MVM_OP_sp_guardconc,
"sp_guardconc",
".s",
2,
3,
0,
0,
0,
0,
0,
{ MVM_operand_read_reg | MVM_operand_obj, MVM_operand_spesh_slot }
{ MVM_operand_read_reg | MVM_operand_obj, MVM_operand_spesh_slot, MVM_operand_uint32 }
},
{
MVM_OP_sp_guardtype,
"sp_guardtype",
".s",
2,
3,
0,
0,
0,
0,
0,
{ MVM_operand_read_reg | MVM_operand_obj, MVM_operand_spesh_slot }
{ MVM_operand_read_reg | MVM_operand_obj, MVM_operand_spesh_slot, MVM_operand_uint32 }
},
{
MVM_OP_sp_decont,
Expand Down
3 changes: 3 additions & 0 deletions src/spesh/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ static void write_instructions(MVMThreadContext *tc, MVMSpeshGraph *g, SpeshWrit
case MVM_operand_int32:
write_int32(ws, ins->operands[i].lit_i32);
break;
case MVM_operand_uint32:
write_int32(ws, ins->operands[i].lit_ui32);
break;
case MVM_operand_int64:
write_int64(ws, ins->operands[i].lit_i64);
break;
Expand Down
25 changes: 6 additions & 19 deletions src/spesh/deopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,6 @@ static void uninline(MVMThreadContext *tc, MVMFrame *f, MVMSpeshCandidate *cand,
}
}

static MVMint32 find_deopt_target(MVMThreadContext *tc, MVMFrame *f, MVMint32 deopt_offset) {
MVMint32 i;
for (i = 0; i < f->spesh_cand->num_deopts * 2; i += 2) {
if (f->spesh_cand->deopts[i + 1] == deopt_offset) {
return f->spesh_cand->deopts[i];
}
}
MVM_oops(tc, "find_deopt_target failed for %s (%s)",
MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid));
}

static void deopt_frame(MVMThreadContext *tc, MVMFrame *f, MVMint32 deopt_offset, MVMint32 deopt_target) {
/* Found it; are we in an inline? */
MVMSpeshInline *inlines = f->spesh_cand->inlines;
Expand Down Expand Up @@ -201,7 +189,7 @@ static void deopt_frame(MVMThreadContext *tc, MVMFrame *f, MVMint32 deopt_offset

/* De-optimizes the currently executing frame, provided it is specialized and
* at a valid de-optimization point. Typically used when a guard fails. */
void MVM_spesh_deopt_one(MVMThreadContext *tc) {
void MVM_spesh_deopt_one(MVMThreadContext *tc, MVMuint32 deopt_target) {
MVMFrame *f = tc->cur_frame;
if (tc->instance->profiling)
MVM_profiler_log_deopt_one(tc);
Expand All @@ -212,10 +200,9 @@ void MVM_spesh_deopt_one(MVMThreadContext *tc) {
#endif
clear_dynlex_cache(tc, f);
if (f->spesh_cand) {
MVMint32 deopt_offset = *(tc->interp_cur_op) - f->spesh_cand->bytecode;
MVMint32 deopt_target = find_deopt_target(tc, f, deopt_offset);
MVMuint32 deopt_offset = *(tc->interp_cur_op) - f->spesh_cand->bytecode;
#if MVM_LOG_DEOPTS
fprintf(stderr, "Will deopt %d -> %d\n", deopt_offset, deopt_target);
fprintf(stderr, "Will deopt %u -> %u\n", deopt_offset, deopt_target);
#endif
deopt_frame(tc, tc->cur_frame, deopt_offset, deopt_target);
}
Expand All @@ -227,11 +214,11 @@ void MVM_spesh_deopt_one(MVMThreadContext *tc) {
}

/* De-optimizes the current frame by directly specifying the addresses */
void MVM_spesh_deopt_one_direct(MVMThreadContext *tc, MVMint32 deopt_offset,
MVMint32 deopt_target) {
void MVM_spesh_deopt_one_direct(MVMThreadContext *tc, MVMuint32 deopt_offset,
MVMuint32 deopt_target) {
MVMFrame *f = tc->cur_frame;
#if MVM_LOG_DEOPTS
fprintf(stderr, "Deopt one requested by JIT in frame '%s' (cuid '%s') (%d -> %d)\n",
fprintf(stderr, "Deopt one requested by JIT in frame '%s' (cuid '%s') (%u -> %u)\n",
MVM_string_utf8_encode_C_string(tc, f->static_info->body.name),
MVM_string_utf8_encode_C_string(tc, f->static_info->body.cuuid),
deopt_offset, deopt_target);
Expand Down
6 changes: 3 additions & 3 deletions src/spesh/deopt.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
void MVM_spesh_deopt_all(MVMThreadContext *tc);
void MVM_spesh_deopt_one(MVMThreadContext *tc);
void MVM_spesh_deopt_one_direct(MVMThreadContext *tc, MVMint32 deopt_offset,
MVMint32 deopt_target);
void MVM_spesh_deopt_one(MVMThreadContext *tc, MVMuint32 deopt_target);
void MVM_spesh_deopt_one_direct(MVMThreadContext *tc, MVMuint32 deopt_offset,
MVMuint32 deopt_target);
3 changes: 2 additions & 1 deletion src/spesh/facts.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,11 @@ static void log_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb,
/* Insert guard instruction. */
guard = MVM_spesh_alloc(tc, g, sizeof(MVMSpeshIns));
guard->info = MVM_op_get_op(guard_op);
guard->operands = MVM_spesh_alloc(tc, g, 2 * sizeof(MVMSpeshOperand));
guard->operands = MVM_spesh_alloc(tc, g, 3 * sizeof(MVMSpeshOperand));
guard->operands[0] = ins->operands[0];
guard->operands[1].lit_i16 = MVM_spesh_add_spesh_slot_try_reuse(tc, g,
(MVMCollectable *)agg_type->st);
guard->operands[2].lit_ui32 = g->deopt_addrs[2 * deopt_one_ann->data.deopt_idx];
if (ins->next)
MVM_spesh_manipulate_insert_ins(tc, bb, ins, guard);
else
Expand Down
4 changes: 4 additions & 0 deletions src/spesh/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ static void build_cfg(MVMThreadContext *tc, MVMSpeshGraph *g, MVMStaticFrame *sf
ins_node->operands[i].lit_i32 = GET_I32(args, arg_size);
arg_size += 4;
break;
case MVM_operand_uint32:
ins_node->operands[i].lit_ui32 = GET_UI32(args, arg_size);
arg_size += 4;
break;
case MVM_operand_int64:
ins_node->operands[i].lit_i64 = MVM_BC_get_I64(args, arg_size);
arg_size += 8;
Expand Down
1 change: 1 addition & 0 deletions src/spesh/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ struct MVMSpeshIns {
union MVMSpeshOperand {
MVMint64 lit_i64;
MVMint32 lit_i32;
MVMuint16 lit_ui32;
MVMint16 lit_i16;
MVMuint16 lit_ui16;
MVMint8 lit_i8;
Expand Down

0 comments on commit 0585b8d

Please sign in to comment.