diff --git a/src/vm/moar/Perl6/Ops.nqp b/src/vm/moar/Perl6/Ops.nqp index ac11c91ce42..3688b77da21 100644 --- a/src/vm/moar/Perl6/Ops.nqp +++ b/src/vm/moar/Perl6/Ops.nqp @@ -81,67 +81,59 @@ sub register_op_desugar($name, $desugar, :$inlinable = 1) is export { # Perl 6 opcode specific mappings. my $ops := nqp::getcomp('QAST').operations; $ops.add_hll_op('perl6', 'p6store', -> $qastcomp, $op { - my @ops; my $cont_res := $qastcomp.as_mast($op[0], :want($MVM_reg_obj)); my $value_res := $qastcomp.as_mast($op[1], :want($MVM_reg_obj)); - push_ilist(@ops, $cont_res); - push_ilist(@ops, $value_res); my $iscont_reg := $*REGALLOC.fresh_i(); my $decont_reg := $*REGALLOC.fresh_o(); my $no_cont_lbl := MAST::Label.new(); my $done_lbl := MAST::Label.new(); - nqp::push(@ops, MAST::Op.new( :op('iscont'), $iscont_reg, $cont_res.result_reg )); - nqp::push(@ops, MAST::Op.new( :op('unless_i'), $iscont_reg, $no_cont_lbl )); + MAST::Op.new( :op('iscont'), $iscont_reg, $cont_res.result_reg ); + MAST::Op.new( :op('unless_i'), $iscont_reg, $no_cont_lbl ); $*REGALLOC.release_register($iscont_reg, $MVM_reg_int64); - nqp::push(@ops, MAST::Op.new( :op('decont'), $decont_reg, $value_res.result_reg )); - nqp::push(@ops, MAST::Op.new( :op('assign'), $cont_res.result_reg, $decont_reg )); + MAST::Op.new( :op('decont'), $decont_reg, $value_res.result_reg ); + MAST::Op.new( :op('assign'), $cont_res.result_reg, $decont_reg ); $*REGALLOC.release_register($decont_reg, $MVM_reg_obj); - nqp::push(@ops, MAST::Op.new( :op('goto'), $done_lbl )); + MAST::Op.new( :op('goto'), $done_lbl ); my $meth_reg := $*REGALLOC.fresh_o(); - nqp::push(@ops, $no_cont_lbl); - nqp::push(@ops, MAST::Op.new( :op('findmeth'), $meth_reg, $cont_res.result_reg, - MAST::SVal.new( :value('STORE') ) )); - nqp::push(@ops, MAST::Call.new( + $*MAST_FRAME.add-label($no_cont_lbl); + MAST::Op.new( :op('findmeth'), $meth_reg, $cont_res.result_reg, + MAST::SVal.new( :value('STORE') ) ); + MAST::Call.new( :target($meth_reg), :flags($Arg::obj, $Arg::obj), $cont_res.result_reg, $value_res.result_reg - )); - nqp::push(@ops, $done_lbl); + ); + $*MAST_FRAME.add-label($done_lbl); $*REGALLOC.release_register($meth_reg, $MVM_reg_obj); - MAST::InstructionList.new(@ops, $cont_res.result_reg, $MVM_reg_obj) + MAST::InstructionList.new($cont_res.result_reg, $MVM_reg_obj) }); $ops.add_hll_op('perl6', 'p6definite', -> $qastcomp, $op { - my @ops; my $value_res := $qastcomp.as_mast($op[0], :want($MVM_reg_obj)); - push_ilist(@ops, $value_res); my $tmp_reg := $*REGALLOC.fresh_i(); my $res_reg := $*REGALLOC.fresh_o(); - nqp::push(@ops, MAST::Op.new( :op('decont'), $res_reg, $value_res.result_reg )); - nqp::push(@ops, MAST::Op.new( :op('isconcrete'), $tmp_reg, $res_reg )); - nqp::push(@ops, MAST::Op.new( :op('hllbool'), $res_reg, $tmp_reg )); + MAST::Op.new( :op('decont'), $res_reg, $value_res.result_reg ); + MAST::Op.new( :op('isconcrete'), $tmp_reg, $res_reg ); + MAST::Op.new( :op('hllbool'), $res_reg, $tmp_reg ); $*REGALLOC.release_register($value_res.result_reg, $MVM_reg_obj); $*REGALLOC.release_register($tmp_reg, $MVM_reg_int64); - MAST::InstructionList.new(@ops, $res_reg, $MVM_reg_obj) + MAST::InstructionList.new($res_reg, $MVM_reg_obj) }); $ops.add_hll_moarop_mapping('perl6', 'p6capturelex', 'p6capturelex'); $ops.add_hll_op('perl6', 'p6bindassert', -> $qastcomp, $op { # Compile the bind value and the type. - my @ops; my $value_res := $qastcomp.as_mast($op[0], :want($MVM_reg_obj)); my $type_res := $qastcomp.as_mast($op[1], :want($MVM_reg_obj)); - push_ilist(@ops, $value_res); - push_ilist(@ops, $type_res); # Emit a type check. my $tcr_reg := $*REGALLOC.fresh_i(); my $dc_reg := $*REGALLOC.fresh_o(); my $lbl_done := MAST::Label.new(); - nqp::push(@ops, MAST::Op.new( :op('decont'), $dc_reg, $value_res.result_reg )); - nqp::push(@ops, MAST::Op.new( :op('istype'), $tcr_reg, $dc_reg, $type_res.result_reg )); - nqp::push(@ops, MAST::Op.new( :op('if_i'), $tcr_reg, $lbl_done )); + MAST::Op.new( :op('decont'), $dc_reg, $value_res.result_reg ); + MAST::Op.new( :op('istype'), $tcr_reg, $dc_reg, $type_res.result_reg ); + MAST::Op.new( :op('if_i'), $tcr_reg, $lbl_done ); $*REGALLOC.release_register($dc_reg, $MVM_reg_obj); $*REGALLOC.release_register($tcr_reg, $MVM_reg_int64); @@ -158,16 +150,15 @@ $ops.add_hll_op('perl6', 'p6bindassert', -> $qastcomp, $op { } } my $err_rep := $qastcomp.as_mast(QAST::WVal.new( :value(nqp::getcodeobj(&bind_error)) )); - push_ilist(@ops, $err_rep); - nqp::push(@ops, MAST::Call.new( + MAST::Call.new( :target($err_rep.result_reg), :flags($Arg::obj, $Arg::obj), $value_res.result_reg, $type_res.result_reg - )); - nqp::push(@ops, $lbl_done); + ); + $*MAST_FRAME.add-label($lbl_done); $*REGALLOC.release_register($err_rep.result_reg, $MVM_reg_obj); - MAST::InstructionList.new(@ops, $value_res.result_reg, $MVM_reg_obj) + MAST::InstructionList.new($value_res.result_reg, $MVM_reg_obj) }); $ops.add_hll_moarop_mapping('perl6', 'p6stateinit', 'p6stateinit'); $ops.add_hll_moarop_mapping('perl6', 'p6setpre', 'p6setpre'); @@ -175,82 +166,73 @@ $ops.add_hll_moarop_mapping('perl6', 'p6clearpre', 'p6clearpre'); $ops.add_hll_moarop_mapping('perl6', 'p6setfirstflag', 'p6setfirstflag'); $ops.add_hll_moarop_mapping('perl6', 'p6takefirstflag', 'p6takefirstflag'); $ops.add_hll_op('perl6', 'p6return', :!inlinable, -> $qastcomp, $op { - my @ops; my $value_res := $qastcomp.as_mast($op[0], :want($MVM_reg_obj)); - push_ilist(@ops, $value_res); my $ex_reg := $*REGALLOC.fresh_o(); - nqp::push(@ops, MAST::Op.new( :op('exception'), $ex_reg )); - nqp::push(@ops, MAST::Op.new( :op('exreturnafterunwind'), $ex_reg )); + MAST::Op.new( :op('exception'), $ex_reg ); + MAST::Op.new( :op('exreturnafterunwind'), $ex_reg ); $*REGALLOC.release_register($ex_reg, $MVM_reg_obj); - nqp::push(@ops, MAST::Op.new( :op('return_o'), $value_res.result_reg )); - MAST::InstructionList.new(@ops, $value_res.result_reg, $MVM_reg_obj) + MAST::Op.new( :op('return_o'), $value_res.result_reg ); + MAST::InstructionList.new($value_res.result_reg, $MVM_reg_obj) }); $ops.add_hll_moarop_mapping('perl6', 'p6getouterctx', 'p6getouterctx', :decont(0)); $ops.add_hll_moarop_mapping('perl6', 'p6captureouters', 'p6captureouters', 0); $ops.add_hll_moarop_mapping('nqp', 'p6captureouters2', 'p6captureouters', 0); $ops.add_hll_op('perl6', 'p6argvmarray', -> $qastcomp, $op { - my @ops; my $res_reg := $*REGALLOC.fresh_o(); - nqp::push(@ops, MAST::Op.new( :op('param_sp'), $res_reg, - MAST::IVal.new( :value(0), :size(16) ))); + MAST::Op.new( :op('param_sp'), $res_reg, + MAST::IVal.new( :value(0), :size(16) )); my $i_reg := $*REGALLOC.fresh_i(); my $n_reg := $*REGALLOC.fresh_i(); my $cmp_reg := $*REGALLOC.fresh_i(); my $tmp_reg := $*REGALLOC.fresh_o(); my $lbl_next := MAST::Label.new(); my $lbl_done := MAST::Label.new(); - nqp::push(@ops, MAST::Op.new( :op('elems'), $n_reg, $res_reg )); - nqp::push(@ops, MAST::Op.new( :op('const_i64'), $i_reg, MAST::IVal.new( :value(0) ) )); - nqp::push(@ops, $lbl_next); - nqp::push(@ops, MAST::Op.new( :op('lt_i'), $cmp_reg, $i_reg, $n_reg )); - nqp::push(@ops, MAST::Op.new( :op('unless_i'), $cmp_reg, $lbl_done )); - nqp::push(@ops, MAST::Op.new( :op('atpos_o'), $tmp_reg, $res_reg, $i_reg )); - nqp::push(@ops, MAST::Op.new( :op('hllize'), $tmp_reg, $tmp_reg )); - nqp::push(@ops, MAST::Op.new( :op('bindpos_o'), $res_reg, $i_reg, $tmp_reg )); - nqp::push(@ops, MAST::Op.new( :op('const_i64'), $cmp_reg, MAST::IVal.new( :value(1) ) )); - nqp::push(@ops, MAST::Op.new( :op('add_i'), $i_reg, $i_reg, $cmp_reg )); - nqp::push(@ops, MAST::Op.new( :op('goto'), $lbl_next )); - nqp::push(@ops, $lbl_done); + MAST::Op.new( :op('elems'), $n_reg, $res_reg ); + MAST::Op.new( :op('const_i64'), $i_reg, MAST::IVal.new( :value(0) ) ); + $*MAST_FRAME.add-label($lbl_next); + MAST::Op.new( :op('lt_i'), $cmp_reg, $i_reg, $n_reg ); + MAST::Op.new( :op('unless_i'), $cmp_reg, $lbl_done ); + MAST::Op.new( :op('atpos_o'), $tmp_reg, $res_reg, $i_reg ); + MAST::Op.new( :op('hllize'), $tmp_reg, $tmp_reg ); + MAST::Op.new( :op('bindpos_o'), $res_reg, $i_reg, $tmp_reg ); + MAST::Op.new( :op('const_i64'), $cmp_reg, MAST::IVal.new( :value(1) ) ); + MAST::Op.new( :op('add_i'), $i_reg, $i_reg, $cmp_reg ); + MAST::Op.new( :op('goto'), $lbl_next ); + $*MAST_FRAME.add-label($lbl_done); $*REGALLOC.release_register($i_reg, $MVM_reg_int64); $*REGALLOC.release_register($n_reg, $MVM_reg_int64); $*REGALLOC.release_register($cmp_reg, $MVM_reg_int64); $*REGALLOC.release_register($tmp_reg, $MVM_reg_obj); - MAST::InstructionList.new(@ops, $res_reg, $MVM_reg_obj) + MAST::InstructionList.new($res_reg, $MVM_reg_obj) }); $ops.add_hll_op('perl6', 'p6bindattrinvres', -> $qastcomp, $op { - my @ops; - my $inv_res := $qastcomp.as_mast($op[0], :want($MVM_reg_obj)); - push_ilist(@ops, $inv_res); my $ch_res := $qastcomp.as_mast( nqp::istype($op[1], QAST::WVal) && !nqp::isconcrete($op[1].value) ?? $op[1] !! QAST::Op.new( :op('decont'), $op[1] ), :want($MVM_reg_obj)); - push_ilist(@ops, $ch_res); my $val_res := $qastcomp.as_mast($op[3], :want($MVM_reg_obj)); - push_ilist(@ops, $val_res); my $name := $op[2]; $name := $name[2] if nqp::istype($name, QAST::Want) && $name[1] eq 'Ss'; if nqp::istype($name, QAST::SVal) { - nqp::push(@ops, MAST::Op.new( :op('bindattr_o'), $inv_res.result_reg, + MAST::Op.new( :op('bindattr_o'), $inv_res.result_reg, $ch_res.result_reg, MAST::SVal.new( :value($name.value) ), $val_res.result_reg, - MAST::IVal.new( :value(-1) ))); + MAST::IVal.new( :value(-1) )); } else { my $nam_res := $qastcomp.as_mast($name, :want($MVM_reg_str)); - push_ilist(@ops, $nam_res); - nqp::push(@ops, MAST::Op.new( :op('bindattrs_o'), $inv_res.result_reg, - $ch_res.result_reg, $nam_res.result_reg, $val_res.result_reg)); + MAST::Op.new( :op('bindattrs_o'), $inv_res.result_reg, + $ch_res.result_reg, $nam_res.result_reg, $val_res.result_reg); $*REGALLOC.release_register($nam_res.result_reg, $MVM_reg_str); } $*REGALLOC.release_register($ch_res.result_reg, $MVM_reg_obj); $*REGALLOC.release_register($val_res.result_reg, $MVM_reg_obj); - MAST::InstructionList.new(@ops, $inv_res.result_reg, $MVM_reg_obj) + MAST::InstructionList.new($inv_res.result_reg, $MVM_reg_obj) }); $ops.add_hll_moarop_mapping('perl6', 'p6finddispatcher', 'p6finddispatcher'); $ops.add_hll_moarop_mapping('perl6', 'p6argsfordispatcher', 'p6argsfordispatcher'); @@ -268,32 +250,30 @@ $ops.add_hll_op('perl6', 'p6sink', -> $qastcomp, $op { my $sinkee_res := $qastcomp.as_mast($op[0]); if $sinkee_res.result_kind == $MVM_reg_obj { # Put computation of sinkee first. - my @ops; - push_ilist(@ops, $sinkee_res); # Check it's concrete try to find the sink method. my $sinkee_reg := $sinkee_res.result_reg; my $itmp := $*REGALLOC.fresh_i(); my $meth := $*REGALLOC.fresh_o(); my $done_lbl := MAST::Label.new(); - nqp::push(@ops, MAST::Op.new( :op('isconcrete'), $itmp, $sinkee_reg )); - nqp::push(@ops, MAST::Op.new( :op('unless_i'), $itmp, $done_lbl )); - nqp::push(@ops, MAST::Op.new( :op('tryfindmeth'), $meth, $sinkee_reg, - MAST::SVal.new( :value('sink') ))); - nqp::push(@ops, MAST::Op.new( :op('isnull'), $itmp, $meth )); - nqp::push(@ops, MAST::Op.new( :op('if_i'), $itmp, $done_lbl )); + MAST::Op.new( :op('isconcrete'), $itmp, $sinkee_reg ); + MAST::Op.new( :op('unless_i'), $itmp, $done_lbl ); + MAST::Op.new( :op('tryfindmeth'), $meth, $sinkee_reg, + MAST::SVal.new( :value('sink') )); + MAST::Op.new( :op('isnull'), $itmp, $meth ); + MAST::Op.new( :op('if_i'), $itmp, $done_lbl ); $*REGALLOC.release_register($itmp, $MVM_reg_int64); # Emit sink method call. - nqp::push(@ops, MAST::Call.new( + MAST::Call.new( :target($meth), :flags([$Arg::obj]), $sinkee_reg - )); + ); $*REGALLOC.release_register($meth, $MVM_reg_obj); # Add end label, and we're done. - nqp::push(@ops, $done_lbl); + $*MAST_FRAME.add-label($done_lbl); $*REGALLOC.release_register($sinkee_res.result_reg, $MVM_reg_obj); - MAST::InstructionList.new(@ops, MAST::VOID, $MVM_reg_void); + MAST::InstructionList.new(MAST::VOID, $MVM_reg_void); } else { $sinkee_res @@ -334,12 +314,11 @@ $ops.add_hll_op('perl6', 'defor', -> $qastcomp, $op { # Boxing and unboxing configuration. sub boxer($kind, $box_op, $type_op) { -> $qastcomp, $reg { - my @ops; my $res_reg := $*REGALLOC.fresh_register($MVM_reg_obj); - nqp::push(@ops, MAST::Op.new( :op($type_op), $res_reg )); - nqp::push(@ops, MAST::Op.new( :op($box_op), $res_reg, $reg, $res_reg )); + MAST::Op.new( :op($type_op), $res_reg ); + MAST::Op.new( :op($box_op), $res_reg, $reg, $res_reg ); $*REGALLOC.release_register($reg, $kind); - MAST::InstructionList.new(@ops, $res_reg, $MVM_reg_obj) + MAST::InstructionList.new($res_reg, $MVM_reg_obj) } } $ops.add_hll_box('perl6', $MVM_reg_int64, boxer($MVM_reg_int64, 'box_i', 'hllboxtype_i')); @@ -347,38 +326,33 @@ $ops.add_hll_box('perl6', $MVM_reg_num64, boxer($MVM_reg_num64, 'box_n', 'hllbox $ops.add_hll_box('perl6', $MVM_reg_str, boxer($MVM_reg_str, 'box_s', 'hllboxtype_s')); $ops.add_hll_box('perl6', $MVM_reg_uint64, boxer($MVM_reg_uint64, 'box_u', 'hllboxtype_i')); QAST::MASTOperations.add_hll_unbox('perl6', $MVM_reg_int64, -> $qastcomp, $reg { - my $il := nqp::list(); my $res_reg := $*REGALLOC.fresh_register($MVM_reg_int64); - nqp::push($il, MAST::Op.new( :op('decont_i'), $res_reg, $reg )); + MAST::Op.new( :op('decont_i'), $res_reg, $reg ); $*REGALLOC.release_register($reg, $MVM_reg_obj); - MAST::InstructionList.new($il, $res_reg, $MVM_reg_int64) + MAST::InstructionList.new($res_reg, $MVM_reg_int64) }); QAST::MASTOperations.add_hll_unbox('perl6', $MVM_reg_num64, -> $qastcomp, $reg { - my $il := nqp::list(); my $res_reg := $*REGALLOC.fresh_register($MVM_reg_num64); - nqp::push($il, MAST::Op.new( :op('decont_n'), $res_reg, $reg )); + MAST::Op.new( :op('decont_n'), $res_reg, $reg ); $*REGALLOC.release_register($reg, $MVM_reg_obj); - MAST::InstructionList.new($il, $res_reg, $MVM_reg_num64) + MAST::InstructionList.new($res_reg, $MVM_reg_num64) }); QAST::MASTOperations.add_hll_unbox('perl6', $MVM_reg_str, -> $qastcomp, $reg { - my $il := nqp::list(); my $res_reg := $*REGALLOC.fresh_register($MVM_reg_str); - nqp::push($il, MAST::Op.new( :op('decont_s'), $res_reg, $reg )); + MAST::Op.new( :op('decont_s'), $res_reg, $reg ); $*REGALLOC.release_register($reg, $MVM_reg_obj); - MAST::InstructionList.new($il, $res_reg, $MVM_reg_str) + MAST::InstructionList.new($res_reg, $MVM_reg_str) }); QAST::MASTOperations.add_hll_unbox('perl6', $MVM_reg_uint64, -> $qastcomp, $reg { - my $il := nqp::list(); my $res_reg := $*REGALLOC.fresh_register($MVM_reg_uint64); - nqp::push($il, MAST::Op.new( :op('decont_u'), $res_reg, $reg )); + MAST::Op.new( :op('decont_u'), $res_reg, $reg ); $*REGALLOC.release_register($reg, $MVM_reg_obj); - MAST::InstructionList.new($il, $res_reg, $MVM_reg_uint64) + MAST::InstructionList.new($res_reg, $MVM_reg_uint64) }); # Signature binding related bits. our $Binder; $ops.add_hll_op('perl6', 'p6bindsig', :!inlinable, -> $qastcomp, $op { - my @ops; my $isnull_result := $*REGALLOC.fresh_i(); my $dont_return_lbl := MAST::Label.new(); my $bind_res := $qastcomp.as_mast( @@ -388,15 +362,14 @@ $ops.add_hll_op('perl6', 'p6bindsig', :!inlinable, -> $qastcomp, $op { QAST::Op.new( :op('savecapture') ), ), :want($MVM_reg_obj) ); - push_ilist(@ops, $bind_res); - nqp::push(@ops, MAST::Op.new( :op('isnull'), $isnull_result, $bind_res.result_reg )); - nqp::push(@ops, MAST::Op.new( :op('if_i'), $isnull_result, $dont_return_lbl )); - nqp::push(@ops, MAST::Op.new( :op('return_o'), $bind_res.result_reg )); - nqp::push(@ops, $dont_return_lbl); + MAST::Op.new( :op('isnull'), $isnull_result, $bind_res.result_reg ); + MAST::Op.new( :op('if_i'), $isnull_result, $dont_return_lbl ); + MAST::Op.new( :op('return_o'), $bind_res.result_reg ); + $*MAST_FRAME.add-label($dont_return_lbl); $*REGALLOC.release_register($bind_res.result_reg, $MVM_reg_obj); $*REGALLOC.release_register($isnull_result, $MVM_reg_int64); - MAST::InstructionList.new(@ops, MAST::VOID, $MVM_reg_void); + MAST::InstructionList.new(MAST::VOID, $MVM_reg_void); }); my $is_bindable := -> $qastcomp, $op { $qastcomp.as_mast(QAST::Op.new( @@ -444,29 +417,26 @@ $ops.add_hll_op('perl6', 'p6typecheckrv', -> $qastcomp, $op { } else { # Use a spesh plugin to appropriately optimize return type checks. - my @ops; my $value_res := $qastcomp.as_mast($op[0], :want($MVM_reg_obj)); my $type_res := $qastcomp.as_mast(QAST::WVal.new( :value($type) ), :want($MVM_reg_obj)); - push_ilist(@ops, $value_res); - push_ilist(@ops, $type_res); my $plugin_reg := $*REGALLOC.fresh_o(); - nqp::push(@ops, MAST::Call.new( + MAST::Call.new( :target(MAST::SVal.new( :value('typecheckrv') )), :flags([$Arg::obj, $Arg::obj]), $value_res.result_reg, $type_res.result_reg, :result($plugin_reg), :op(2) - )); - nqp::push(@ops, MAST::Call.new( + ); + MAST::Call.new( :target($plugin_reg), :flags([$Arg::obj]), $value_res.result_reg, :result($value_res.result_reg), - )); + ); $*REGALLOC.release_register($plugin_reg, $MVM_reg_obj); $*REGALLOC.release_register($type_res.result_reg, $MVM_reg_obj); - MAST::InstructionList.new(@ops, $value_res.result_reg, $MVM_reg_obj) + MAST::InstructionList.new($value_res.result_reg, $MVM_reg_obj) } } else { @@ -508,7 +478,3 @@ $ops.add_hll_op('perl6', 'p6configposbindfailover', :inlinable, -> $qastcomp, $o QAST::WVal.new( :value($Binder) ), $op[0], $op[1]), :want($MVM_reg_obj)); }); - -sub push_ilist(@dest, $src) { - nqp::splice(@dest, $src.instructions, +@dest, 0); -}