Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Significant refactor of lists and iterators. Results in a 50%
speed improvement versus what we had before for a simple counting
loop, although we're _still_ not as fast as Rakudo master.
Working on that next.
  • Loading branch information
pmichaud committed Jun 23, 2011
1 parent 96fdaf8 commit d19672e
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 75 deletions.
5 changes: 3 additions & 2 deletions src/core/Any.pm
Expand Up @@ -7,8 +7,9 @@ my class Any {
# List-like methods for Any.
########

method flat() { self.list.flat }
method list() { (self,).list }
method eager() { nqp::p6list(List, nqp::list(self), 1.Bool).eager }
method flat() { nqp::p6list(List, nqp::list(self), 1.Bool) }
method list() { nqp::p6list(List, nqp::list(self), Mu) }
method elems() { self.list.elems }

method join($separator = ' ') {
Expand Down
32 changes: 21 additions & 11 deletions src/core/List.pm
Expand Up @@ -11,6 +11,10 @@ class List {
method Parcel() { self.gimme(*); pir__perl6_box_rpa__PP(self.RPA) }
method Str(List:D:) { self.join(' ') }

method flat() { self.flattens
?? self
!! nqp::p6list(List, nqp::list(self), 1.Bool)
}
method list() { self }
method flattens() { $!flattens }

Expand All @@ -34,10 +38,6 @@ class List {
nqp::p6bool(nqp::existspos($!items, nqp::unbox_i($pos)))
}

method flat() {
pir::perl6_list_from_rpa__PPPP(List, self.RPA, 1.Bool);
}

method gimme($n) {
# create $!items RPA if it doesn't already exist
pir::defined($!items) or
Expand Down Expand Up @@ -73,12 +73,13 @@ class List {
ListIter, '$!reified', pir__perl6_box_rpa__PP(self.RPA))
}

method munch($n is copy) {
self.gimme($n);
my Mu $rpa := pir::new__Ps('ResizablePMCArray');
pir::push__vPP($rpa, nqp::shift($!items))
while $!items && $n-- > 0;
pir__perl6_box_rpa__PP($rpa)
method munch(\$n) {
self.gimme($n) if nqp::not_i(nqp::p6isa($n, Int))
|| nqp::isnull($!items)
|| nqp::islt_i(nqp::elems($!items), nqp::unbox_i($n));
pir__perl6_box_rpa__PP(
pir::perl6_shiftn__0PPi(nqp::list(), $!items, nqp::unbox_i($n))
)
}

method push(*@values) {
Expand All @@ -92,12 +93,21 @@ class List {
self.gimme(1) && nqp::shift($!items)
}

method sink() {
$!nextiter.defined && $!nextiter.reify(10, :sink(1));
}

multi method perl(List:D \$self:) {
self.gimme(*);
self.Parcel.perl ~ '.list'
~ (pir::is_container__IP($self) ?? '.item' !! '')
}

method REIFY(Parcel \$parcel) {
nqp::splice($!items, $parcel.RPA, nqp::elems($!items), 0);
$parcel
}

method STORE_AT_POS(\$pos, Mu \$v) {
nqp::bindpos($!items, nqp::unbox_i($pos), $v)
}
Expand All @@ -119,7 +129,7 @@ class List {
}

sub eager(|$) {
pir__perl6_box_rpa__PP(pir::perl6_current_args_rpa__P()).flat.eager
pir__perl6_box_rpa__PP(pir::perl6_current_args_rpa__P()).eager
}

sub flat(|$) {
Expand Down
72 changes: 34 additions & 38 deletions src/core/ListIter.pm
Expand Up @@ -5,50 +5,46 @@ my class ListIter {
# has Mu $!rest; # RPA of elements remaining to be reified
# has $!list; # List object associated with this iterator

method reify($n is copy) {
method reify($n is copy, :$sink) {
if !$!reified.defined {
my $rpa := pir::new__Ps('ResizablePMCArray');
my Mu $x;
my $pos = $!list.gimme(0) if $!list.defined;
my $flattens = $!list.defined && $!list.flattens;
my $eager = Whatever.ACCEPTS($n);
while $!rest && ($eager || $n > 0) {
$x := nqp::atpos($!rest, 0);
if pir::not__II(pir::is_container__IP($x)) && $x.defined
&& Iterable.ACCEPTS($x) {
last if $eager && $x.infinite;
pir::splice__vPPii(
$!rest,
pir__perl6_unbox_rpa__PP($x.iterator.reify($n)),
0, 1);
}
elsif $flattens && pir::not__II(pir::is_container__IP($x))
&& $x.defined && Parcel.ACCEPTS($x) {
pir::splice__vPPii(
$!rest,
pir__perl6_unbox_rpa__PP($x),
0, 1);
}
elsif Nil.ACCEPTS($x) { nqp::shift($!rest) }
else {
nqp::shift($!rest);
$x := $!list.STORE_AT_POS($pos, $x) if $!list.defined;
pir::push__vPP($rpa, $x);
$eager or $n = $n - 1;
$pos = $pos + 1;
my $flattens = $!list.defined && $!list.flattens;
my $count = $eager ?? 100000 !! $n;
my $rpa := nqp::list();
my Mu $x;
my $index;
while $!rest && nqp::islt_i(nqp::elems($rpa), nqp::unbox_i($count)) {
$index = nqp::p6box_i(
pir::perl6_rpa_find_type__IPPii(
$!rest, Iterable, 0, nqp::unbox_i($count)));
$index = nqp::p6box_i(
pir::perl6_rpa_find_type__IPPii(
$!rest, Parcel, 0, nqp::unbox_i($index)))
if $flattens;
pir::perl6_shiftn__0PPi($rpa, $!rest, nqp::unbox_i($index));
if $!rest && nqp::islt_i(nqp::elems($rpa), nqp::unbox_i($count)) {
$x := nqp::shift($!rest);
if nqp::isconcrete($x) {
$x := $x.iterator.reify($count) if nqp::p6isa($x, Iterable);
nqp::splice($!rest, nqp::getattr($x, Parcel, '$!storage'), 0, 0);

}
elsif nqp::not_i(nqp::p6isa($x, Nil)) {
nqp::push($rpa, $x);
}
}
}
pir::push__vPP( $rpa,
pir::setattribute__3PPsP(self, ListIter, '$!nextiter',
pir::perl6_iter_from_rpa__PPPP($!rest, $!list)))
my $reified := pir__perl6_box_rpa__PP($rpa);
$reified := $!list.REIFY($reified) if $!list.defined && !$sink;
nqp::push(
nqp::getattr($reified, Parcel, '$!storage'),
nqp::bindattr(self, ListIter, '$!nextiter',
nqp::p6listiter($!rest, $!list)))
if $!rest;
# define our $!reified Parcel. infix:<:=> doesn't seem to work
# on attributes defined in BOOTSTRAP, so use pir::setattribute.
pir::setattribute__0PPsP( self, ListIter, '$!reified',
pir__perl6_box_rpa__PP($rpa));
nqp::bindattr(self, ListIter, '$!reified', $reified);
# free up $!list and $!rest
pir::setattribute__0PPsP(self, ListIter, '$!list', Mu);
pir::setattribute__0PPsP(self, ListIter, '$!rest', Mu);
nqp::bindattr(self, ListIter, '$!list', Mu);
nqp::bindattr(self, ListIter, '$!rest', Mu);
}
$!reified;
}
Expand Down
27 changes: 12 additions & 15 deletions src/core/MapIter.pm
Expand Up @@ -14,31 +14,28 @@ my class MapIter is Iterator {
self
}

method reify($n is copy = 1) {
method reify($n is copy = 1, :$sink) {
if !$!reified.defined {
## we don't have &prefix:<|> or good control blocks yet,
## so we'll temporarily implement MapIter with Q:PIR blocks.

my $count = $!block.count;
my $block := pir::perl6_decontainerize__PP($!block);
$n = 1000 if Whatever.ACCEPTS($n);
my $block := pir::perl6_decontainerize__PP($!block); ### TODO: Why?
$n = nqp::p6isa($n, Whatever) ?? 1000 !! $n.Int;
$!list.gimme($count * $n);
my Mu $rpa := pir::new__Ps('ResizablePMCArray');
my Mu $args :=
pir__perl6_unbox_rpa__PP($!list.munch($!block.count));
while $args && $n > 0 {
pir::push__vPP(
$rpa,
my Mu $args;
repeat {
$args := $!list.munch($!block.count).RPA;
nqp::push($rpa,
Q:PIR {
$P0 = find_lex '$args'
$P1 = find_lex '$block'
%r = $P1($P0 :flat)
});
$n = $n - 1;
$args := pir__perl6_unbox_rpa__PP($!list.munch($count))
if $n > 0;
}
}) if $args;
} while $args
&& nqp::islt_i(nqp::elems($rpa), nqp::unbox_i($n));
# create the next MapIter if we haven't reached the end
pir::push__vPP($rpa, self.CREATE.BUILD($!list, $!block))
nqp::push($rpa, self.CREATE.BUILD($!list, $!block))
if $args;
$!reified := pir__perl6_box_rpa__PP($rpa);
$!list = Any;
Expand Down
8 changes: 8 additions & 0 deletions src/core/Nil.pm
@@ -0,0 +1,8 @@
my class Nil is Iterator {
method new() { Nil }
method iterator() { self }
method reify($n?) { () }
method gist() { 'Nil' }
}


10 changes: 2 additions & 8 deletions src/core/Parcel.pm
Expand Up @@ -31,20 +31,14 @@ my class Parcel {
$perl ~ ')';
}

method RPA() { $!storage }

multi method DUMP(Parcel:D:) {
self.DUMP-ID() ~ '(:storage(' ~ DUMP($!storage) ~ '))'
}
}


my class Nil is Parcel {
method new() { Nil }
method flat() { ().flat }
method list() { ().list }
method gist() { 'Nil' }
}


my sub infix:<,>(|$) {
# pir::perl6_box_rpa__PP(pir::perl6_current_args_rpa__P())
pir::setattribute__0PPsP(
Expand Down
4 changes: 3 additions & 1 deletion src/core/Range.pm
Expand Up @@ -22,11 +22,13 @@ class Range is Iterable {
self;
}

method flat() { nqp::p6list(List, nqp::list(self), 1.Bool) }
method infinite() { $.max == $Inf }
method iterator() { self }
method list() { self.flat }

method reify($n is copy = 10) {
$n = $Inf if Whatever.ACCEPTS($n);
$n = nqp::p6isa($n, Whatever) ?? $Inf !! $n.Num;
fail "request for infinite elements from range"
if $n == $Inf && self.infinite;
my $value = $!excludes_min ?? $!min.succ !! $!min;
Expand Down
69 changes: 69 additions & 0 deletions src/ops/perl6.ops
Expand Up @@ -752,6 +752,75 @@ inline op perl6_list_from_rpa(out PMC, in PMC, in PMC, in PMC) :base_core {
}


/*

=item perl6_rpa_find_type(out INT, in PMC, in PMC, int INT, in INT)

Find the first element of RPA $2 that has type $3, starting at
index $4 and up through (but not including) index $5. Sets $1
to be the index of the first element matching type, otherwise
$1 is set to the highest index searched.

The RPA elements are not decontainerized during scanning,
and thus won't match type (unless you happen to be looking
for the container type).

=cut

*/
inline op perl6_rpa_find_type(out INT, in PMC, in PMC, in INT, in INT)
{
PMC *rpa = $2;
PMC *type = Rakudo_cont_decontainerize(interp, $3);
INTVAL elems = VTABLE_elements(interp, rpa);
INTVAL last = $5;
INTVAL index;

if (elems < last) last = elems;

for (index = $4; index < last; index++) {
PMC *val = VTABLE_get_pmc_keyed_int(interp, rpa, index);
if (STABLE(val)->type_check(interp, val, type)) break;
}

$1 = index;
}


/*

=item perl6_shiftn(inout PMC, in PMC, in INT)

Shifts up to $3 elements from $2, pushing each shifted onto $1.
$1 can be PMCNULL, in which case the shifted elements are
simply discarded.

*/
inline op perl6_shiftn(inout PMC, in PMC, in INT) :base_core {
INTVAL count = $3;
INTVAL elems = VTABLE_elements(interp, $2);
INTVAL i;

if (count > elems) count = elems;

/* if we have a destination PMC in $1, then push the first
count elements of $2 onto it */
if (!PMC_IS_NULL($1)) {
for (i = 0; i < count; i++) {
VTABLE_push_pmc(interp, $1,
VTABLE_get_pmc_keyed_int(interp, $2, i));
}
}

/* now shift count elements off of $2 */
for (i = 0; i < elems - count; i++) {
VTABLE_set_pmc_keyed_int(interp, $2, i,
VTABLE_get_pmc_keyed_int(interp, $2, i+count));
}
VTABLE_set_integer_native(interp, $2, elems-count);
}


/*

=item encodelocaltime(out INT, in PMC)
Expand Down
1 change: 1 addition & 0 deletions tools/build/Makefile.in
Expand Up @@ -135,6 +135,7 @@ CORE_SOURCES = \
src/core/Str.pm \
src/core/Iterable.pm \
src/core/Iterator.pm \
src/core/Nil.pm \
src/core/ListIter.pm \
src/core/MapIter.pm \
src/core/GatherIter.pm \
Expand Down

0 comments on commit d19672e

Please sign in to comment.