Skip to content

Commit

Permalink
Handle inlining of outer lexical binds
Browse files Browse the repository at this point in the history
This is used in code using native types, and was one source of surprise
slowness when using natives. For example, this:

    my num $x = 1.5e0;
    my num $y = 0e0;
    for ^10_000_000 {
        $y = $y + $x;
    }

Used to run slower than if the native types were not added. Now it runs
in 25% of the time it did before the change, meaning it pulls well ahead
of the case without native types (although EA will, in the future,
likely close down that gap again).
  • Loading branch information
jnthn committed Apr 12, 2019
1 parent 9b1b60f commit c10fee6
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 93 deletions.
63 changes: 62 additions & 1 deletion src/core/interp.c
Expand Up @@ -5727,6 +5727,36 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
cur_op += 6;
goto NEXT;
}
OP(sp_bindlex_in): {
MVMFrame *f = tc->cur_frame;
MVMuint16 outers = GET_UI16(cur_op, 2);
while (outers) {
if (!f->outer)
MVM_exception_throw_adhoc(tc, "bindlex: outer index out of range");
f = f->outer;
outers--;
}
GET_LEX(cur_op, 0, f) = GET_REG(cur_op, 4);
cur_op += 6;
goto NEXT;
}
OP(sp_bindlex_os): {
MVMFrame *f = tc->cur_frame;
MVMuint16 outers = GET_UI16(cur_op, 2);
while (outers) {
if (!f->outer)
MVM_exception_throw_adhoc(tc, "bindlex: outer index out of range");
f = f->outer;
outers--;
}
#if MVM_GC_DEBUG
MVM_ASSERT_NOT_FROMSPACE(tc, GET_REG(cur_op, 4).o);
#endif
MVM_ASSIGN_REF(tc, &(f->header), GET_LEX(cur_op, 0, f).o,
GET_REG(cur_op, 4).o);
cur_op += 6;
goto NEXT;
}
OP(sp_getarg_o):
GET_REG(cur_op, 0).o = tc->cur_frame->params.args[GET_UI16(cur_op, 2)].o;
cur_op += 4;
Expand Down Expand Up @@ -6164,7 +6194,6 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
}
OP(sp_getlexvia_ins): {
MVMFrame *f = ((MVMCode *)GET_REG(cur_op, 6).o)->body.outer;
MVMuint16 idx = GET_UI16(cur_op, 2);
MVMuint16 outers = GET_UI16(cur_op, 4) - 1; /* - 1 as already in outer */
while (outers) {
if (!f->outer)
Expand All @@ -6176,6 +6205,38 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
cur_op += 8;
goto NEXT;
}
OP(sp_bindlexvia_os): {
MVMFrame *f = ((MVMCode *)GET_REG(cur_op, 4).o)->body.outer;
MVMuint16 outers = GET_UI16(cur_op, 2) - 1; /* - 1 as already in outer */
MVMRegister found;
while (outers) {
if (!f->outer)
MVM_exception_throw_adhoc(tc, "getlex: outer index out of range");
f = f->outer;
outers--;
}
#if MVM_GC_DEBUG
MVM_ASSERT_NOT_FROMSPACE(tc, GET_REG(cur_op, 6).o);
#endif
MVM_ASSIGN_REF(tc, &(f->header), GET_LEX(cur_op, 0, f).o,
GET_REG(cur_op, 6).o);
cur_op += 8;
goto NEXT;
}
OP(sp_bindlexvia_in): {
MVMFrame *f = ((MVMCode *)GET_REG(cur_op, 4).o)->body.outer;
MVMuint16 outers = GET_UI16(cur_op, 2) - 1; /* - 1 as already in outer */
MVMRegister found;
while (outers) {
if (!f->outer)
MVM_exception_throw_adhoc(tc, "getlex: outer index out of range");
f = f->outer;
outers--;
}
GET_LEX(cur_op, 0, f) = GET_REG(cur_op, 6);
cur_op += 8;
goto NEXT;
}
OP(sp_getstringfrom): {
MVMCompUnit *dep = (MVMCompUnit *)tc->cur_frame->effective_spesh_slots[GET_UI16(cur_op, 2)];
MVMuint32 idx = GET_UI32(cur_op, 4);
Expand Down
8 changes: 4 additions & 4 deletions src/core/oplabels.h
Expand Up @@ -837,6 +837,8 @@ static const void * const LABELS[] = {
&&OP_sp_getlex_o,
&&OP_sp_getlex_ins,
&&OP_sp_getlex_no,
&&OP_sp_bindlex_in,
&&OP_sp_bindlex_os,
&&OP_sp_getarg_o,
&&OP_sp_getarg_i,
&&OP_sp_getarg_n,
Expand Down Expand Up @@ -891,6 +893,8 @@ static const void * const LABELS[] = {
&&OP_sp_deref_bind_n,
&&OP_sp_getlexvia_o,
&&OP_sp_getlexvia_ins,
&&OP_sp_bindlexvia_os,
&&OP_sp_bindlexvia_in,
&&OP_sp_getstringfrom,
&&OP_sp_getwvalfrom,
&&OP_sp_jit_enter,
Expand Down Expand Up @@ -1021,10 +1025,6 @@ static const void * const LABELS[] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&&OP_CALL_EXTOP,
&&OP_CALL_EXTOP,
&&OP_CALL_EXTOP,
Expand Down
13 changes: 11 additions & 2 deletions src/core/oplist
Expand Up @@ -918,12 +918,19 @@ sp_rebless .s w(obj) r(obj) r(obj) uint32 :noinline :maycausedeopt
sp_resolvecode .s w(obj) r(obj)

# 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.
# the case where we can't JIT-compile, but don't want to keep on logging. Also,
# the separated _o and _ins forms for getlex allow us to avoid a check of if
# this is an object register.
sp_decont .s w(obj) r(obj) :pure :invokish :maycausedeopt
sp_getlex_o .s w(obj) rl(obj) :pure
sp_getlex_ins .s w(`1) rl(`1) :pure
sp_getlex_no .s w(obj) str :pure :noinline

# Specialized forms of bindlex, avoiding the need to check for register type
# (`_in` has no write batter, `_os` has the barrier).
sp_bindlex_in .s wl(`1) r(`1)
sp_bindlex_os .s wl(`1) r(`1)

# Following are for fast, unchecked grabbing of args from the arg buffer.
sp_getarg_o .s w(obj) int16 :pure
sp_getarg_i .s w(obj) int16 :pure
Expand Down Expand Up @@ -1015,11 +1022,13 @@ sp_deref_get_n .s w(num64) r(obj) int16 :pure
sp_deref_bind_i64 .s r(obj) r(int64) int16
sp_deref_bind_n .s r(obj) r(num64) int16

# These read a lexical via. a code ref held in a register. Used for closure
# These read/bind a lexical via. a code ref held in a register. Used for closure
# inlining. The outers count must be at least 1 (e.g. these must never be used
# for lexicals that are in the current scope).
sp_getlexvia_o .s w(obj) int16 int16 r(obj) :pure
sp_getlexvia_ins .s w(`1) int16 int16 r(obj) :pure
sp_bindlexvia_os .s int16 int16 r(obj) r(obj) :pure
sp_bindlexvia_in .s int16 int16 r(obj) r(obj) :pure

sp_getstringfrom .s w(str) sslot int32 :pure
sp_getwvalfrom .s w(obj) sslot int64 :pure
Expand Down
62 changes: 61 additions & 1 deletion src/core/ops.c
Expand Up @@ -12532,6 +12532,36 @@ static const MVMOpInfo MVM_op_infos[] = {
0,
{ MVM_operand_write_reg | MVM_operand_obj, MVM_operand_str }
},
{
MVM_OP_sp_bindlex_in,
"sp_bindlex_in",
".s",
2,
0,
0,
0,
0,
0,
0,
0,
0,
{ MVM_operand_write_lex | MVM_operand_type_var, MVM_operand_read_reg | MVM_operand_type_var }
},
{
MVM_OP_sp_bindlex_os,
"sp_bindlex_os",
".s",
2,
0,
0,
0,
0,
0,
0,
0,
0,
{ MVM_operand_write_lex | MVM_operand_type_var, MVM_operand_read_reg | MVM_operand_type_var }
},
{
MVM_OP_sp_getarg_o,
"sp_getarg_o",
Expand Down Expand Up @@ -13342,6 +13372,36 @@ static const MVMOpInfo MVM_op_infos[] = {
0,
{ MVM_operand_write_reg | MVM_operand_type_var, MVM_operand_int16, MVM_operand_int16, MVM_operand_read_reg | MVM_operand_obj }
},
{
MVM_OP_sp_bindlexvia_os,
"sp_bindlexvia_os",
".s",
4,
1,
0,
0,
0,
0,
0,
0,
0,
{ MVM_operand_int16, MVM_operand_int16, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj }
},
{
MVM_OP_sp_bindlexvia_in,
"sp_bindlexvia_in",
".s",
4,
1,
0,
0,
0,
0,
0,
0,
0,
{ MVM_operand_int16, MVM_operand_int16, MVM_operand_read_reg | MVM_operand_obj, MVM_operand_read_reg | MVM_operand_obj }
},
{
MVM_OP_sp_getstringfrom,
"sp_getstringfrom",
Expand Down Expand Up @@ -13686,7 +13746,7 @@ static const MVMOpInfo MVM_op_infos[] = {
},
};

static const unsigned short MVM_op_counts = 913;
static const unsigned short MVM_op_counts = 917;

MVM_PUBLIC const MVMOpInfo * MVM_op_get_op(unsigned short op) {
if (op >= MVM_op_counts)
Expand Down
158 changes: 81 additions & 77 deletions src/core/ops.h
Expand Up @@ -837,83 +837,87 @@
#define MVM_OP_sp_getlex_o 833
#define MVM_OP_sp_getlex_ins 834
#define MVM_OP_sp_getlex_no 835
#define MVM_OP_sp_getarg_o 836
#define MVM_OP_sp_getarg_i 837
#define MVM_OP_sp_getarg_n 838
#define MVM_OP_sp_getarg_s 839
#define MVM_OP_sp_fastinvoke_v 840
#define MVM_OP_sp_fastinvoke_i 841
#define MVM_OP_sp_fastinvoke_n 842
#define MVM_OP_sp_fastinvoke_s 843
#define MVM_OP_sp_fastinvoke_o 844
#define MVM_OP_sp_speshresolve 845
#define MVM_OP_sp_paramnamesused 846
#define MVM_OP_sp_getspeshslot 847
#define MVM_OP_sp_findmeth 848
#define MVM_OP_sp_fastcreate 849
#define MVM_OP_sp_get_o 850
#define MVM_OP_sp_get_i64 851
#define MVM_OP_sp_get_i32 852
#define MVM_OP_sp_get_i16 853
#define MVM_OP_sp_get_i8 854
#define MVM_OP_sp_get_n 855
#define MVM_OP_sp_get_s 856
#define MVM_OP_sp_bind_o 857
#define MVM_OP_sp_bind_i64 858
#define MVM_OP_sp_bind_i32 859
#define MVM_OP_sp_bind_i16 860
#define MVM_OP_sp_bind_i8 861
#define MVM_OP_sp_bind_n 862
#define MVM_OP_sp_bind_s 863
#define MVM_OP_sp_bind_s_nowb 864
#define MVM_OP_sp_p6oget_o 865
#define MVM_OP_sp_p6ogetvt_o 866
#define MVM_OP_sp_p6ogetvc_o 867
#define MVM_OP_sp_p6oget_i 868
#define MVM_OP_sp_p6oget_n 869
#define MVM_OP_sp_p6oget_s 870
#define MVM_OP_sp_p6oget_bi 871
#define MVM_OP_sp_p6obind_o 872
#define MVM_OP_sp_p6obind_i 873
#define MVM_OP_sp_p6obind_n 874
#define MVM_OP_sp_p6obind_s 875
#define MVM_OP_sp_p6oget_i32 876
#define MVM_OP_sp_p6obind_i32 877
#define MVM_OP_sp_getvt_o 878
#define MVM_OP_sp_getvc_o 879
#define MVM_OP_sp_fastbox_i 880
#define MVM_OP_sp_fastbox_bi 881
#define MVM_OP_sp_fastbox_i_ic 882
#define MVM_OP_sp_fastbox_bi_ic 883
#define MVM_OP_sp_deref_get_i64 884
#define MVM_OP_sp_deref_get_n 885
#define MVM_OP_sp_deref_bind_i64 886
#define MVM_OP_sp_deref_bind_n 887
#define MVM_OP_sp_getlexvia_o 888
#define MVM_OP_sp_getlexvia_ins 889
#define MVM_OP_sp_getstringfrom 890
#define MVM_OP_sp_getwvalfrom 891
#define MVM_OP_sp_jit_enter 892
#define MVM_OP_sp_boolify_iter 893
#define MVM_OP_sp_boolify_iter_arr 894
#define MVM_OP_sp_boolify_iter_hash 895
#define MVM_OP_sp_cas_o 896
#define MVM_OP_sp_atomicload_o 897
#define MVM_OP_sp_atomicstore_o 898
#define MVM_OP_sp_add_I 899
#define MVM_OP_sp_sub_I 900
#define MVM_OP_sp_mul_I 901
#define MVM_OP_sp_bool_I 902
#define MVM_OP_prof_enter 903
#define MVM_OP_prof_enterspesh 904
#define MVM_OP_prof_enterinline 905
#define MVM_OP_prof_enternative 906
#define MVM_OP_prof_exit 907
#define MVM_OP_prof_allocated 908
#define MVM_OP_prof_replaced 909
#define MVM_OP_ctw_check 910
#define MVM_OP_coverage_log 911
#define MVM_OP_breakpoint 912
#define MVM_OP_sp_bindlex_in 836
#define MVM_OP_sp_bindlex_os 837
#define MVM_OP_sp_getarg_o 838
#define MVM_OP_sp_getarg_i 839
#define MVM_OP_sp_getarg_n 840
#define MVM_OP_sp_getarg_s 841
#define MVM_OP_sp_fastinvoke_v 842
#define MVM_OP_sp_fastinvoke_i 843
#define MVM_OP_sp_fastinvoke_n 844
#define MVM_OP_sp_fastinvoke_s 845
#define MVM_OP_sp_fastinvoke_o 846
#define MVM_OP_sp_speshresolve 847
#define MVM_OP_sp_paramnamesused 848
#define MVM_OP_sp_getspeshslot 849
#define MVM_OP_sp_findmeth 850
#define MVM_OP_sp_fastcreate 851
#define MVM_OP_sp_get_o 852
#define MVM_OP_sp_get_i64 853
#define MVM_OP_sp_get_i32 854
#define MVM_OP_sp_get_i16 855
#define MVM_OP_sp_get_i8 856
#define MVM_OP_sp_get_n 857
#define MVM_OP_sp_get_s 858
#define MVM_OP_sp_bind_o 859
#define MVM_OP_sp_bind_i64 860
#define MVM_OP_sp_bind_i32 861
#define MVM_OP_sp_bind_i16 862
#define MVM_OP_sp_bind_i8 863
#define MVM_OP_sp_bind_n 864
#define MVM_OP_sp_bind_s 865
#define MVM_OP_sp_bind_s_nowb 866
#define MVM_OP_sp_p6oget_o 867
#define MVM_OP_sp_p6ogetvt_o 868
#define MVM_OP_sp_p6ogetvc_o 869
#define MVM_OP_sp_p6oget_i 870
#define MVM_OP_sp_p6oget_n 871
#define MVM_OP_sp_p6oget_s 872
#define MVM_OP_sp_p6oget_bi 873
#define MVM_OP_sp_p6obind_o 874
#define MVM_OP_sp_p6obind_i 875
#define MVM_OP_sp_p6obind_n 876
#define MVM_OP_sp_p6obind_s 877
#define MVM_OP_sp_p6oget_i32 878
#define MVM_OP_sp_p6obind_i32 879
#define MVM_OP_sp_getvt_o 880
#define MVM_OP_sp_getvc_o 881
#define MVM_OP_sp_fastbox_i 882
#define MVM_OP_sp_fastbox_bi 883
#define MVM_OP_sp_fastbox_i_ic 884
#define MVM_OP_sp_fastbox_bi_ic 885
#define MVM_OP_sp_deref_get_i64 886
#define MVM_OP_sp_deref_get_n 887
#define MVM_OP_sp_deref_bind_i64 888
#define MVM_OP_sp_deref_bind_n 889
#define MVM_OP_sp_getlexvia_o 890
#define MVM_OP_sp_getlexvia_ins 891
#define MVM_OP_sp_bindlexvia_os 892
#define MVM_OP_sp_bindlexvia_in 893
#define MVM_OP_sp_getstringfrom 894
#define MVM_OP_sp_getwvalfrom 895
#define MVM_OP_sp_jit_enter 896
#define MVM_OP_sp_boolify_iter 897
#define MVM_OP_sp_boolify_iter_arr 898
#define MVM_OP_sp_boolify_iter_hash 899
#define MVM_OP_sp_cas_o 900
#define MVM_OP_sp_atomicload_o 901
#define MVM_OP_sp_atomicstore_o 902
#define MVM_OP_sp_add_I 903
#define MVM_OP_sp_sub_I 904
#define MVM_OP_sp_mul_I 905
#define MVM_OP_sp_bool_I 906
#define MVM_OP_prof_enter 907
#define MVM_OP_prof_enterspesh 908
#define MVM_OP_prof_enterinline 909
#define MVM_OP_prof_enternative 910
#define MVM_OP_prof_exit 911
#define MVM_OP_prof_allocated 912
#define MVM_OP_prof_replaced 913
#define MVM_OP_ctw_check 914
#define MVM_OP_coverage_log 915
#define MVM_OP_breakpoint 916

#define MVM_OP_EXT_BASE 1024
#define MVM_OP_EXT_CU_LIMIT 1024
Expand Down

0 comments on commit c10fee6

Please sign in to comment.