Skip to content

Instantly share code, notes, and snippets.

@FROGGS

FROGGS/xor.diff Secret

Created November 27, 2013 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FROGGS/6e3c00076afcb5c3c1f0 to your computer and use it in GitHub Desktop.
Save FROGGS/6e3c00076afcb5c3c1f0 to your computer and use it in GitHub Desktop.
diff --git a/src/vm/moar/QAST/QASTOperationsMAST.nqp b/src/vm/moar/QAST/QASTOperationsMAST.nqp
index 5f53311..fd2f934 100644
--- a/src/vm/moar/QAST/QASTOperationsMAST.nqp
+++ b/src/vm/moar/QAST/QASTOperationsMAST.nqp
@@ -784,6 +784,84 @@ QAST::MASTOperations.add_core_op('defor', -> $qastcomp, $op {
$expr
});
+sub say_line(@ops, $n) {
+ my $sreg := $*REGALLOC.fresh_s();
+ push_op(@ops, 'const_s', $sreg, MAST::SVal.new( :value($n) ));
+ push_op(@ops, 'say', $sreg);
+}
+
+QAST::MASTOperations.add_core_op('xor', -> $qastcomp, $op {
+ my @ops;
+ my $res_kind := $MVM_reg_obj;
+ my $res_reg := $*REGALLOC.fresh_register($res_kind);
+ my $falselabel := MAST::Label.new(:name('xor_false'));
+ my $endlabel := MAST::Label.new(:name('xor_end'));
+
+ my @comp_ops;
+ my $fpast;
+ for $op.list {
+ if $_.named eq 'false' {
+ $fpast := $qastcomp.as_mast($_);
+ }
+ else {
+ nqp::push(@comp_ops, $qastcomp.as_mast($_));
+ }
+ }
+
+ my $t := $*REGALLOC.fresh_i();
+ my $u := $*REGALLOC.fresh_i();
+
+ my $apast := nqp::shift(@comp_ops);
+ my $apost := $qastcomp.coerce($apast, $MVM_reg_obj);
+ push_ilist(@ops, $apost);
+ push_op(@ops, 'set', $res_reg, $apost.result_reg);
+ push_op(@ops, 'istrue', $t, $apost.result_reg);
+
+ my $have_middle_child := 1;
+ my $bpost;
+ while $have_middle_child {
+ my $bpast := nqp::shift(@comp_ops);
+ my $jumplabel := MAST::Label.new(:name('xor_jump'));
+ $bpost := $qastcomp.coerce($bpast, $MVM_reg_obj);
+ push_ilist(@ops, $bpost);
+ push_op(@ops, 'istrue', $u, $bpost.result_reg);
+
+ push_op(@ops, 'unless_i', $t, $jumplabel);
+ push_op(@ops, 'unless_i', $u, $jumplabel);
+ push_op(@ops, 'goto', $falselabel);
+ nqp::push(@ops, $jumplabel);
+
+
+ if @comp_ops {
+ my $truelabel := MAST::Label.new(:name('xor_true'));
+ push_op(@ops, 'if_i', $t, $truelabel);
+ push_op(@ops, 'set', $res_reg, $bpost.result_reg);
+ push_op(@ops, 'set', $t, $u.result_reg);
+ nqp::push(@ops, $truelabel);
+ }
+ else {
+ $have_middle_child := 0;
+ }
+ }
+
+ push_op(@ops, 'if_i', $t, $endlabel);
+ push_op(@ops, 'set', $res_reg, $bpost.result_reg);
+ push_op(@ops, 'goto', $endlabel);
+ nqp::push(@ops, $falselabel);
+
+ if $fpast {
+ my $fpost := $qastcomp.coerce($fpast, $res_kind);
+ push_ilist(@ops, $fpost);
+ push_op(@ops, 'set', $res_reg, $fpost.result_reg);
+ }
+ else {
+ push_op(@ops, 'null', $res_reg);
+ }
+
+ nqp::push(@ops, $endlabel);
+
+ MAST::InstructionList.new(@ops, $res_reg, $res_kind)
+});
+
QAST::MASTOperations.add_core_op('ifnull', -> $qastcomp, $op {
if +$op.list != 2 {
nqp::die("The 'ifnull' op expects two children");
diff --git a/src/vm/parrot/pmc/qrpa.pmc b/src/vm/parrot/pmc/qrpa.pmc
index ded6173..7051b7c 100644
--- a/src/vm/parrot/pmc/qrpa.pmc
+++ b/src/vm/parrot/pmc/qrpa.pmc
@@ -171,7 +171,10 @@ Resizes the array to C<n> elements.
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"QRPA: Can't resize to negative elements");
- if (n == elems) { return; }
+ if (n == elems) {
+ PObj_custom_mark_destroy_SETALL(SELF);
+ return;
+ }
/* if there aren't enough slots at the end, shift off empty slots
* from the beginning first */
@@ -189,6 +192,7 @@ Resizes the array to C<n> elements.
qrpa->elems = n;
if (n <= ssize) {
/* we already have n slots available, we can just return */
+ PObj_custom_mark_destroy_SETALL(SELF);
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment