From 9eef565c29286280b9cb84726fa76e4738ba755f Mon Sep 17 00:00:00 2001 From: Daniel Green Date: Thu, 29 Dec 2016 19:39:55 -0500 Subject: [PATCH] Make Cursor.MATCH about 10-15% faster By converting more of it to NQP ops and pulling some initial variable declarations out of loops (reducing the number of call frames and garbage collections). --- src/core/Cursor.pm | 58 ++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/core/Cursor.pm b/src/core/Cursor.pm index edc1fb6ccd7..2863c2ab252 100644 --- a/src/core/Cursor.pm +++ b/src/core/Cursor.pm @@ -41,30 +41,32 @@ my class Cursor does NQPCursorRole { nqp::bindattr($match, Match, '$!CURSOR', self); my Mu $list; my Mu $hash := nqp::hash(); - if $to >= $from { + if nqp::isge_i($to, $from) { # For captures with lists, initialize the lists. my $caplist := $NO_CAPS; my $rxsub := nqp::getattr(self, Cursor, '$!regexsub'); my str $onlyname = ''; my int $namecount = 0; - if !nqp::isnull($rxsub) && nqp::defined($rxsub) { + if nqp::not_i(nqp::isnull($rxsub)) { $caplist := nqp::can($rxsub, 'CAPS') ?? nqp::findmethod($rxsub, 'CAPS')($rxsub) !! nqp::null(); - if !nqp::isnull($caplist) && nqp::istrue($caplist) { + if nqp::not_i(nqp::isnull($caplist)) && nqp::istrue($caplist) { my $iter := nqp::iterator($caplist); + my $curcap; + my str $name; while $iter { - my $curcap := nqp::shift($iter); - $namecount = $namecount + 1; + $curcap := nqp::shift($iter); + $namecount = nqp::add_i($namecount, 1); #?if jvm my Mu $curval := nqp::iterval($curcap); if (nqp::isint($curval) && nqp::isge_i($curval, 2)) - || (nqp::isnum($curval) && nqp::p6box_n($curval) >= 2) { + || (nqp::isnum($curval) && nqp::isge_n($curval, 2)) { #?endif #?if !jvm if nqp::iterval($curcap) >= 2 { #?endif - my str $name = nqp::iterkey_s($curcap); - $onlyname = $name if $namecount == 1; + $name = nqp::iterkey_s($curcap); + $onlyname = $name if nqp::iseq_i($namecount, 1); nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0) ?? nqp::bindpos( nqp::if(nqp::isconcrete($list), $list, ($list := nqp::list())), @@ -77,11 +79,11 @@ my class Cursor does NQPCursorRole { # Walk the Cursor stack and populate the Cursor. my Mu $cs := nqp::getattr(self, Cursor, '$!cstack'); - if nqp::isnull($cs) || !nqp::istrue($cs) {} + if nqp::isnull($cs) || nqp::not_i(nqp::istrue($cs)) {} #?if !jvm - elsif !$caplist {} + elsif nqp::not_i(nqp::istrue($caplist)) {} #?endif - elsif $namecount == 1 && $onlyname ne '' && nqp::eqat($onlyname,'$!',0) { + elsif nqp::iseq_i($namecount, 1) && nqp::isgt_i(nqp::chars($onlyname), 0) && nqp::eqat($onlyname, '$!', 0) { # If there's only one destination, avoid repeated hash lookups my int $cselems = nqp::elems($cs); my int $csi = -1; @@ -92,30 +94,34 @@ my class Cursor does NQPCursorRole { ?? nqp::atpos($list, $onlyname) !! nqp::atkey($hash, $onlyname); + my $subcur; + my str $name; while nqp::islt_i(++$csi,$cselems) { - my $subcur := nqp::atpos($cs, $csi); - my str $name = nqp::getattr_s($subcur, $?CLASS, '$!name'); + $subcur := nqp::atpos($cs, $csi); + $name = nqp::getattr_s($subcur, $?CLASS, '$!name'); nqp::push($dest,$subcur.MATCH()) - if !nqp::isnull_s($name) && nqp::defined($name); + if nqp::not_i(nqp::isnull_s($name)); } } else { my int $cselems = nqp::elems($cs); my int $csi = -1; + my $subcur; + my str $name; while nqp::islt_i(++$csi,$cselems) { - my Mu $subcur := nqp::atpos($cs, $csi); - my str $name = nqp::getattr_s($subcur, $?CLASS, '$!name'); - if !nqp::isnull_s($name) && nqp::defined($name) && $name ne '' { + $subcur := nqp::atpos($cs, $csi); + $name = nqp::getattr_s($subcur, $?CLASS, '$!name'); + if nqp::not_i(nqp::isnull_s($name)) && nqp::isgt_i(nqp::chars($name), 0) { my Mu $submatch := $subcur.MATCH; - if nqp::eqat($name, '$', 0) && ($name eq '$!from' || $name eq '$!to') { + if nqp::eqat($name, '$', 0) && (nqp::iseq_s($name, '$!from') || nqp::iseq_s($name, '$!to')) { nqp::bindattr_i($match, Match, $name, $submatch.from); } - elsif nqp::index($name, '=') < 0 { + elsif nqp::islt_i(nqp::index($name, '='), 0) { my Mu $capval := nqp::atkey($caplist, $name); #?if jvm my int $needs_list = nqp::isconcrete($capval) && ((nqp::isint($capval) && nqp::isge_i($capval, 2)) || - (nqp::isnum($capval) && nqp::p6box_n($capval) >= 2)); + (nqp::isnum($capval) && nqp::isge_n($capval, 2))); #?endif #?if !jvm my int $needs_list = nqp::isconcrete($capval) && $capval >= 2; @@ -135,16 +141,18 @@ my class Cursor does NQPCursorRole { else { my $names := nqp::split('=', $name); my $iter := nqp::iterator($names); + my Mu $capval; + my int $needs_list; while $iter { - my str $name = nqp::shift($iter); - my Mu $capval := nqp::atkey($caplist, $name); + $name = nqp::shift($iter); + $capval := nqp::atkey($caplist, $name); #?if jvm - my int $needs_list = nqp::isconcrete($capval) && + $needs_list = nqp::isconcrete($capval) && ((nqp::isint($capval) && nqp::isge_i($capval, 2)) || - (nqp::isnum($capval) && nqp::p6box_n($capval) >= 2)); + (nqp::isnum($capval) && nqp::isge_n($capval, 2))); #?endif #?if !jvm - my int $needs_list = nqp::isconcrete($capval) && $capval >= 2; + $needs_list = nqp::isconcrete($capval) && $capval >= 2; #?endif if nqp::iscclass(nqp::const::CCLASS_NUMERIC, $name, 0) { $list := nqp::list() unless nqp::isconcrete($list);