Skip to content

Commit ab80bb3

Browse files
committed
faster cstack traversal
Cut down statement lists by 3/4 by not pushing cursors that MATCH won't be interested in. In MATCH, if there's only one destination, don't keep looking up the same hash entry over and over.
1 parent 6aeeff1 commit ab80bb3

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

src/QRegex/Cursor.nqp

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,13 @@ role NQPCursorRole is export {
246246
}
247247

248248
method !cursor_push_cstack($capture) {
249-
$!cstack := [] unless nqp::defined($!cstack);
250-
nqp::push($!cstack, $capture);
249+
if !nqp::defined($!cstack) { $!cstack := [$capture] }
250+
elsif !nqp::isnull($capture) {
251+
my $name := nqp::getattr($capture, $?CLASS, '$!name');
252+
if !nqp::isnull($name) && nqp::defined($name) {
253+
nqp::push($!cstack, $capture);
254+
}
255+
}
251256
$!cstack;
252257
}
253258

@@ -855,15 +860,19 @@ class NQPCursor does NQPCursorRole {
855860
# For captures with lists, initialize the lists.
856861
my %caplist := $NO_CAPS;
857862
my $rxsub := nqp::getattr(self, NQPCursor, '$!regexsub');
863+
my $onlyname := '';
864+
my int $namecount := 0;
858865
if !nqp::isnull($rxsub) && nqp::defined($rxsub) {
859866
%caplist := nqp::can($rxsub, 'CAPS') ?? $rxsub.CAPS() !! nqp::null();
860867
if !nqp::isnull(%caplist) && nqp::istrue(%caplist) {
861868
my $iter := nqp::iterator(%caplist);
862869
while $iter {
863870
my $curcap := nqp::shift($iter);
871+
my str $name := nqp::iterkey_s($curcap);
872+
$namecount++;
864873
if nqp::iterval($curcap) >= 2 {
865-
my str $name := nqp::iterkey_s($curcap);
866-
nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0)
874+
$onlyname := $name if $namecount == 1;
875+
nqp::ord($name) < 58
867876
?? nqp::bindpos(
868877
nqp::defor($list, $list := nqp::list()),
869878
$name, nqp::list())
@@ -875,9 +884,32 @@ class NQPCursor does NQPCursorRole {
875884

876885
# Walk the Cursor stack and populate the Cursor.
877886
my $cs := nqp::getattr(self, NQPCursor, '$!cstack');
878-
if !nqp::isnull(%caplist) && %caplist && !nqp::isnull($cs) && nqp::istrue($cs) {
887+
if nqp::isnull($cs) || !nqp::istrue($cs) {}
888+
elsif $namecount == 1 && $onlyname ne '' && !nqp::eqat($onlyname,'$!',0) {
889+
# If there's only one destination, avoid repeated hash lookups
890+
my int $cselems := nqp::elems($cs);
891+
my int $csi;
892+
my $dest;
893+
if nqp::ord($onlyname) < 58 {
894+
$dest := nqp::atpos($list, $onlyname);
895+
}
896+
else {
897+
$dest := nqp::atkey($hash, $onlyname);
898+
}
899+
while $csi < $cselems {
900+
my $subcur := nqp::atpos($cs, $csi);
901+
my $name := nqp::getattr($subcur, $?CLASS, '$!name');
902+
if !nqp::isnull($name) && nqp::defined($name) {
903+
my $submatch := $subcur.MATCH();
904+
nqp::push($dest, $submatch);
905+
}
906+
$csi++;
907+
}
908+
}
909+
elsif !nqp::isnull(%caplist) && %caplist {
879910
my int $cselems := nqp::elems($cs);
880911
my int $csi;
912+
# note($cselems);
881913
while $csi < $cselems {
882914
my $subcur := nqp::atpos($cs, $csi);
883915
my $name := nqp::getattr($subcur, $?CLASS, '$!name');
@@ -888,7 +920,7 @@ class NQPCursor does NQPCursorRole {
888920
}
889921
elsif nqp::index($name, '=') < 0 {
890922
my int $needs_list := %caplist{$name} >= 2;
891-
if nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0) {
923+
if nqp::ord($name) < 58 {
892924
$list := nqp::list() unless nqp::isconcrete($list);
893925
$needs_list
894926
?? nqp::push(nqp::atpos($list, $name), $submatch)
@@ -903,7 +935,7 @@ class NQPCursor does NQPCursorRole {
903935
else {
904936
for nqp::split('=', $name) -> $name {
905937
my int $needs_list := %caplist{$name} >= 2;
906-
if nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0) {
938+
if nqp::ord($name) < 58 {
907939
$list := nqp::list() unless nqp::isconcrete($list);
908940
$needs_list
909941
?? nqp::push(nqp::atpos($list, $name), $submatch)
@@ -919,6 +951,30 @@ class NQPCursor does NQPCursorRole {
919951
}
920952
$csi++;
921953
}
954+
# {
955+
# my $iter := nqp::iterator(%caplist);
956+
# while $iter {
957+
# my $curcap := nqp::shift($iter);
958+
# my str $name := nqp::iterkey_s($curcap);
959+
# my int $iv := nqp::iterval($curcap);
960+
# if $iv >= 2 {
961+
# if nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0) {
962+
# note("\t" ~ $name ~ "\t" ~ nqp::elems(nqp::atpos($list, $name)));
963+
# }
964+
# else {
965+
# note("\t" ~ $name ~ "\t" ~ nqp::elems(nqp::atkey($hash, $name)));
966+
# }
967+
# }
968+
# elsif $iv >= 1 {
969+
# if nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0) {
970+
# note("\t" ~ $name ~ "\t" ~ nqp::defined(nqp::atpos($list, $name)));
971+
# }
972+
# else {
973+
# note("\t" ~ $name ~ "\t" ~ nqp::defined(nqp::atkey($hash, $name)));
974+
# }
975+
# }
976+
# }
977+
# }
922978
}
923979
nqp::bindattr($match, NQPCapture, '@!array', nqp::isconcrete($list) ?? $list !! @EMPTY_LIST);
924980
nqp::bindattr($match, NQPCapture, '%!hash', $hash);

0 commit comments

Comments
 (0)