Skip to content

Instantly share code, notes, and snippets.

@MasterDuke17
Last active September 19, 2018 22:34
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 MasterDuke17/1c45e013eac54ac54e6578d49eabd36c to your computer and use it in GitHub Desktop.
Save MasterDuke17/1c45e013eac54ac54e6578d49eabd36c to your computer and use it in GitHub Desktop.
dan@hermes:~/p6/rakudo$ ./perl6-gdb-m t/spec/integration/advent2012-day14.t
================================================================================================
This is Rakudo Perl 6 running in the GNU debugger, which often allows the user to generate useful back-
traces to debug or report issues in Rakudo, the MoarVM backend or the currently running code.
This Rakudo version is 2018.08.109.g.0.a.45.ffbc.6 built on MoarVM version 2018.08.88.gad.12.d.8.e.4.d,
running on ubuntu (18.04.1.LTS.Bionic.Beaver) / linux (4.15.0.34.generic)
Type `bt full` to generate a backtrace if applicable, type `q` to quit or `help` for help.
------------------------------------------------------------------------------------------------
Reading symbols from /home/dan/Source/perl6/install/bin/moar...done.
Starting program: /home/dan/Source/perl6/install/bin/moar --execname=./perl6-gdb-m --libpath=. --libpath=blib --libpath=/home/dan/Source/perl6/install/share/nqp/lib --libpath=/home/dan/Source/perl6/install/share/nqp/lib --libpath=/home/dan/Source/perl6/install/share/nqp/lib /home/dan/Source/perl6/rakudo/perl6.moarvm --nqp-lib=blib t/spec/integration/advent2012-day14.t
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6136700 (LWP 12802)]
1..6
ok 1 - prime (alpha)
ok 2 - prime (beta)
P6opaque: get_boxed_ref could not unbox for the representation 'P6bigint' of type Scalar
in sub is-prime-rm at t/spec/integration/advent2012-day14.t line 40
in block <unit> at t/spec/integration/advent2012-day14.t line 57
# Looks like you planned 6 tests, but ran 2
[Thread 0x7ffff7fd06c0 (LWP 12798) exited]
[Inferior 1 (process 12798) exited with code 0377]
(gdb) b MVM_exception_throw_adhoc
Breakpoint 1 at 0x7ffff74c66d9: file src/core/exceptions.c, line 855.
(gdb) r
Starting program: /home/dan/Source/perl6/install/bin/moar --execname=./perl6-gdb-m --libpath=. --libpath=blib --libpath=/home/dan/Source/perl6/install/share/nqp/lib --libpath=/home/dan/Source/perl6/install/share/nqp/lib --libpath=/home/dan/Source/perl6/install/share/nqp/lib /home/dan/Source/perl6/rakudo/perl6.moarvm --nqp-lib=blib t/spec/integration/advent2012-day14.t
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6136700 (LWP 12804)]
Thread 1 "moar" hit Breakpoint 1, MVM_exception_throw_adhoc (tc=0x555555758cc0, messageFormat=0x7ffff76966a0 "%s positionals passed; expected %d argument%s but got %d") at src/core/exceptions.c:855
855 MVM_NO_RETURN void MVM_exception_throw_adhoc(MVMThreadContext *tc, const char *messageFormat, ...) {
(gdb) c
Continuing.
Thread 1 "moar" hit Breakpoint 1, MVM_exception_throw_adhoc (tc=0x555555758cc0, messageFormat=0x7ffff76966a0 "%s positionals passed; expected %d argument%s but got %d") at src/core/exceptions.c:855
855 MVM_NO_RETURN void MVM_exception_throw_adhoc(MVMThreadContext *tc, const char *messageFormat, ...) {
(gdb) c
Continuing.
1..6
ok 1 - prime (alpha)
ok 2 - prime (beta)
Thread 1 "moar" hit Breakpoint 1, MVM_exception_throw_adhoc (tc=0x555555758cc0, messageFormat=0x7ffff76ab800 "P6opaque: get_boxed_ref could not unbox for the representation '%s' of type %s") at src/core/exceptions.c:855
855 MVM_NO_RETURN void MVM_exception_throw_adhoc(MVMThreadContext *tc, const char *messageFormat, ...) {
(gdb) call MVM_dump_backtrace(tc)
at t/spec/integration/advent2012-day14.t:40 (<ephemeral file>:)
from t/spec/integration/advent2012-day14.t:35 (<ephemeral file>:is-prime-rm)
from t/spec/integration/advent2012-day14.t:24 (<ephemeral file>:is-prime-rm)
from t/spec/integration/advent2012-day14.t:57 (<ephemeral file>:)
from SETTING::src/core/Any-iterable-methods.pm6:942 (./CORE.setting.moarvm:)
from SETTING::src/core/Any-iterable-methods.pm6:423 (./CORE.setting.moarvm:push-all)
from SETTING::src/core/Iterator.pm6:69 (./CORE.setting.moarvm:push-until-lazy)
from SETTING::src/core/Array.pm6:197 (./CORE.setting.moarvm:from-iterator)
from SETTING::src/core/array_operators.pm6:36 (./CORE.setting.moarvm:circumfix:<[ ]>)
from t/spec/integration/advent2012-day14.t:57 (<ephemeral file>:<unit>)
from t/spec/integration/advent2012-day14.t:1 (<ephemeral file>:<unit-outer>)
from gen/moar/stage2/NQPHLL.nqp:1675 (/home/dan/Source/perl6/install/share/nqp/lib/NQPHLL.moarvm:eval)
from gen/moar/stage2/NQPHLL.nqp:1914 (/home/dan/Source/perl6/install/share/nqp/lib/NQPHLL.moarvm:evalfiles)
from gen/moar/stage2/NQPHLL.nqp:1804 (/home/dan/Source/perl6/install/share/nqp/lib/NQPHLL.moarvm:command_eval)
from src/Perl6/Compiler.nqp:42 (blib/Perl6/Compiler.moarvm:command_eval)
from gen/moar/stage2/NQPHLL.nqp:1763 (/home/dan/Source/perl6/install/share/nqp/lib/NQPHLL.moarvm:command_line)
from gen/moar/main.nqp:47 (/home/dan/Source/perl6/rakudo/perl6.moarvm:MAIN)
from gen/moar/main.nqp:38 (/home/dan/Source/perl6/rakudo/perl6.moarvm:<mainline>)
from <unknown>:1 (/home/dan/Source/perl6/rakudo/perl6.moarvm:<main>)
from <unknown>:1 (/home/dan/Source/perl6/rakudo/perl6.moarvm:<entry>)
(gdb) bt
#0 MVM_exception_throw_adhoc (tc=0x555555758cc0, messageFormat=0x7ffff76ab800 "P6opaque: get_boxed_ref could not unbox for the representation '%s' of type %s") at src/core/exceptions.c:855
#1 0x00007ffff7564300 in get_boxed_ref (tc=0x555555758cc0, st=0x555555e05ac0, root=0x7ffff27edaf8, data=0x7ffff27edb10, repr_id=20) at src/6model/reprs/P6opaque.c:597
#2 0x00007ffff762e86d in get_bigint_body (tc=0x555555758cc0, obj=0x7ffff27edaf8) at src/math/bigintops.c:148
#3 0x00007ffff762f147 in MVM_bigint_add (tc=0x555555758cc0, result_type=0x555555e07368, a=0x7ffff27edaf8, b=0x555556d87cf8) at src/math/bigintops.c:455
#4 0x00007ffff74dfb36 in MVM_interp_run (tc=0x555555758cc0, initial_invoke=0x7ffff764040c <toplevel_initial_invoke>, invoke_data=0x5555557e5270) at src/core/interp.c:3273
#5 0x00007ffff7640571 in MVM_vm_run_file (instance=0x555555758260, filename=0x7fffffffe1fa "/home/dan/Source/perl6/rakudo/perl6.moarvm") at src/moar.c:420
#6 0x0000555555555b4e in main (argc=10, argv=0x7fffffffdd58) at src/main.c:300
(gdb)
diff --git a/src/Perl6/Optimizer.nqp b/src/Perl6/Optimizer.nqp
index 728834369..7ca8dedc0 100644
--- a/src/Perl6/Optimizer.nqp
+++ b/src/Perl6/Optimizer.nqp
@@ -892,6 +892,8 @@ class Perl6::Optimizer {
has $!debug;
+ has %!range_bounds;
+
# Entry point for the optimization process.
method optimize($past, *%adverbs) {
# Initialize.
@@ -916,6 +918,33 @@ class Perl6::Optimizer {
$!eliminated_block_contents := QAST::Op.new( :op('die_s'),
QAST::SVal.new( :value('INTERNAL ERROR: Execution of block eliminated by optimizer') ) );
+ %!range_bounds := nqp::hash(
+ '&infix:<..>', -> $op {
+ my @lb := get_bound($op[0], 0, $!symbols);
+ my @ub := get_bound($op[1], 0, $!symbols);
+ @lb && @ub ?? [@lb[0], @ub[0]] !! []
+ },
+ '&infix:<..^>', -> $op {
+ my @lb := get_bound($op[0], 0, $!symbols);
+ my @ub := get_bound($op[1],-1, $!symbols);
+ @lb && @ub ?? [@lb[0], @ub[0]] !! []
+ },
+ '&infix:<^..>', -> $op {
+ my @lb := get_bound($op[0], 1, $!symbols);
+ my @ub := get_bound($op[1], 0, $!symbols);
+ @lb && @ub ?? [@lb[0], @ub[0]] !! []
+ },
+ '&infix:<^..^>', -> $op {
+ my @lb := get_bound($op[0], 1, $!symbols);
+ my @ub := get_bound($op[1],-1, $!symbols);
+ @lb && @ub ?? [@lb[0], @ub[0]] !! []
+ },
+ '&prefix:<^>', -> $op {
+ my @ub := get_bound($op[0],-1, $!symbols);
+ @ub ?? [QAST::IVal.new( :value(0) ), @ub[0]] !! []
+ },
+ );
+
# Walk and optimize the program.
self.visit_block($!symbols.UNIT);
@@ -1024,7 +1053,7 @@ class Perl6::Optimizer {
}
# Range operators we can optimize into loops, and how to do it.
- sub get_bound($node,$extra) {
+ sub get_bound($node,$extra,$symbols) {
# 0
if nqp::istype($node, QAST::Want) && $node[1] eq 'Ii' {
@@ -1044,47 +1073,41 @@ class Perl6::Optimizer {
}
}
+ elsif nqp::istype($node, QAST::Var) {
# my int $foo
- elsif nqp::istype($node, QAST::Var)
- && nqp::objprimspec($node.returns) == 1 {
- return [$extra
- ?? QAST::Op.new( :op<add_i>, :returns($node.returns),
- $node,
- QAST::IVal.new( :value($extra) )
- )
- !! $node
- ]
+ if nqp::objprimspec($node.returns) == 1 {
+ return [$extra
+ ?? QAST::Op.new( :op<add_i>, :returns($node.returns),
+ $node,
+ QAST::IVal.new( :value($extra) )
+ )
+ !! $node
+ ]
+ }
+ # my Int $foo
+ elsif nqp::objprimspec($node.returns) == 0 {
+ my int $found := 0;
+ my $vname;
+ try {
+ $vname := $symbols.find_lexical_symbol($node.name);
+ $found := 1;
+ }
+ if $found && $vname<type> =:= $symbols.find_in_setting("Int") {
+ return [$extra
+ ?? QAST::Op.new( :op<add_I>, :returns($node.returns),
+ $node,
+ QAST::IVal.new( :value($extra) ),
+ QAST::WVal.new( :value($symbols.find_in_setting("Int")) )
+ )
+ !! $node
+ ]
+ }
+ }
}
# No way we can make this faster
[]
}
- my %range_bounds := nqp::hash(
- '&infix:<..>', -> $op {
- my @lb := get_bound($op[0], 0);
- my @ub := get_bound($op[1], 0);
- @lb && @ub ?? [@lb[0], @ub[0]] !! []
- },
- '&infix:<..^>', -> $op {
- my @lb := get_bound($op[0], 0);
- my @ub := get_bound($op[1],-1);
- @lb && @ub ?? [@lb[0], @ub[0]] !! []
- },
- '&infix:<^..>', -> $op {
- my @lb := get_bound($op[0], 1);
- my @ub := get_bound($op[1], 0);
- @lb && @ub ?? [@lb[0], @ub[0]] !! []
- },
- '&infix:<^..^>', -> $op {
- my @lb := get_bound($op[0], 1);
- my @ub := get_bound($op[1],-1);
- @lb && @ub ?? [@lb[0], @ub[0]] !! []
- },
- '&prefix:<^>', -> $op {
- my @ub := get_bound($op[0],-1);
- @ub ?? [QAST::IVal.new( :value(0) ), @ub[0]] !! []
- },
- );
# Poisonous calls.
my %poison_calls := nqp::hash(
@@ -1112,11 +1135,12 @@ class Perl6::Optimizer {
# If it's a for 1..1000000 { } we can simplify it to a while loop. We
# check this here, before the tree is transformed by call inline opts.
if ($optype eq 'p6for' || $optype eq 'p6forstmt') && $op.sunk && @($op) == 2 {
+# note("about to optimize a ^ for");
my $theop := $op[0];
if nqp::istype($theop, QAST::Stmts) { $theop := $theop[0] }
if nqp::istype($theop, QAST::Op)
- && nqp::existskey(%range_bounds, $theop.name)
+ && nqp::existskey(%!range_bounds, $theop.name)
&& $!symbols.is_from_core($theop.name)
&& $op[1].has_ann('code_object') {
self.optimize_for_range($op, $op[1], $theop);
@@ -1133,10 +1157,10 @@ class Perl6::Optimizer {
&& $op[0][1].has_ann('code_object')
&& (
nqp::istype((my $c1 := $op[0][0]), QAST::Op)
- && nqp::existskey(%range_bounds, $c1.name)
+ && nqp::existskey(%!range_bounds, $c1.name)
|| nqp::istype($op[0][0], QAST::Stmts)
&& nqp::istype(($c1 := $op[0][0][0]), QAST::Op)
- && nqp::existskey(%range_bounds, $c1.name)
+ && nqp::existskey(%!range_bounds, $c1.name)
) && $!symbols.is_from_core($c1.name)
{
self.optimize_for_range($op, $op[0][1], $c1);
@@ -2245,12 +2269,13 @@ class Perl6::Optimizer {
my $phasers := nqp::istype($code, $block)
?? nqp::getattr($code, $block, '$!phasers')
!! nqp::null();
- if $count == 1 && nqp::isnull($phasers) && %range_bounds{$c2.name}($c2) -> @bounds {
+ if $count == 1 && nqp::isnull($phasers) && %!range_bounds{$c2.name}($c2) -> @bounds {
my $it_var := QAST::Node.unique('range_it_');
my $max_var := QAST::Node.unique('range_max_');
my $callee_var := QAST::Node.unique('range_callee_');
$op.shift while $op.list;
$op.op('stmts');
+ if nqp::objprimspec(@bounds[0]) == 1 && nqp::objprimspec(@bounds[1]) == 1 {
$op.push(QAST::Stmts.new(
# my int $it := @bounds[0] - 1
@@ -2305,6 +2330,65 @@ class Perl6::Optimizer {
# return Nil
QAST::WVal.new( :value($!symbols.Nil) )
));
+ }
+ else {
+ $op.push(QAST::Stmts.new(
+
+# my Int $it := @bounds[0] - 1
+ QAST::Op.new( :op<bind>,
+ QAST::Var.new(
+ :name($it_var), :scope<local>, :decl<var>, :returns($!symbols.find_in_setting("Int"))
+ ),
+ QAST::Op.new( :op<sub_I>,
+ QAST::Op.new( :op<decont>, @bounds[0]),
+ QAST::IVal.new( :value(1)),
+ QAST::WVal.new( :value($!symbols.find_in_setting("Int")) )
+ )
+ ),
+
+# my Int $max := @bounds[1]
+ QAST::Op.new( :op<bind>,
+ QAST::Var.new(
+ :name($max_var), :scope<local>, :decl<var>, :returns($!symbols.find_in_setting("Int"))
+ ),
+ @bounds[1]
+ ),
+
+# my $callee := { };
+ QAST::Op.new( :op<bind>,
+ QAST::Var.new(:name($callee_var), :scope<local>, :decl<var>),
+ $callee
+ ),
+
+# nqp::while(
+# nqp::isle_I(
+# nqp::bind($it,nqp::add_I($it,1,Int)),
+# $max
+# )
+ QAST::Op.new( :op<while>,
+ QAST::Op.new( :op<isle_I>,
+ QAST::Op.new( :op<bind>,
+ QAST::Var.new(:name($it_var), :scope<local>, :returns($!symbols.find_in_setting("Int"))),
+ QAST::Op.new( :op<add_I>,
+ QAST::Op.new( :op<decont>, QAST::Var.new(:name($it_var),:scope<local>,:returns($!symbols.find_in_setting("Int")))),
+ QAST::IVal.new( :value(1) ),
+ QAST::WVal.new( :value($!symbols.find_in_setting("Int")) )
+ )
+ ),
+ QAST::Op.new( :op<decont>, QAST::Var.new(:name($max_var), :scope<local>, :returns($!symbols.find_in_setting("Int"))))
+ ),
+
+# nqp::call($callee, $it)
+ QAST::Op.new( :op<call>,
+ QAST::Var.new(:name($callee_var), :scope<local> ),
+ QAST::Var.new(:name($it_var), :scope<local>, :returns($!symbols.find_in_setting("Int")))
+ )
+ ),
+
+# return Nil
+ QAST::WVal.new( :value($!symbols.Nil) )
+ ));
+ }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment