Skip to content
Permalink
Browse files

Make @A >>op=<< ... about 1.5x as fast for core ops

- create a lazily filled cache of += %= -= *= ~=
- whenever a METAOP_ASSIGN is called, check for core ops
- the first time this happens, the cache will be filled
  - so we don't incur this overhead at every startup
- more ops could be easily added if deemed necessary
  • Loading branch information...
lizmat committed Nov 20, 2018
1 parent becbdeb commit 005261a4c2b6b421c0e069a92933d8467852eeef
Showing with 29 additions and 2 deletions.
  1. +21 −0 src/core/Rakudo/Internals.pm6
  2. +8 −2 src/core/metaops.pm6
@@ -15,6 +15,8 @@ my class X::Str::Sprintf::Directives::Count { ... }
my class X::Str::Sprintf::Directives::Unsupported { ... }
my class X::TypeCheck { ... }

my $CORE_METAOP_ASSIGN := nqp::null; # lazy storage for core METAOP_ASSIGN ops

my class Rakudo::Internals {

# for use in nqp::splice
@@ -1615,6 +1617,25 @@ my class Rakudo::Internals {
)
}

# Method for lazily installing fast versions of METAOP_ASSIGN ops for
# core infix ops. Since the compilation of &[op] happens at build time
# of the setting, we're sure we're referring to the core ops and not one
# that has been locally installed. Called by METAOP_ASSIGN. Please add
# any other core ops that seem to be necessary.
method INSTALL-CORE-METAOPS() {
$CORE_METAOP_ASSIGN := nqp::create(Rakudo::Internals::IterationSet);
for (
&[+], -> Mu \a, Mu \b { a = a.DEFINITE ?? a + b !! +b },
&[%], -> Mu \a, Mu \b { a = a.DEFINITE ?? a % b !! Failure.new("No zero-arg meaning for infix:<%>")},
&[-], -> Mu \a, Mu \b { a = a.DEFINITE ?? a - b !! -b },
&[*], -> Mu \a, Mu \b { a = a.DEFINITE ?? a * b !! +b },
&[~], -> Mu \a, Mu \b { a = a.DEFINITE ?? a ~ b !! ~b },
) -> \op, \metaop {
metaop.set_name(op.name ~ ' + {assigning}');
nqp::bindkey($CORE_METAOP_ASSIGN,nqp::objectid(op),metaop);
}
$CORE_METAOP_ASSIGN
}
}

# expose the number of bits a native int has
@@ -1,7 +1,13 @@

sub METAOP_ASSIGN(\op) {
my \op-is := -> Mu \a, Mu \b { a = op.( ( a.DEFINITE ?? a !! op.() ), b) }
op-is.set_name(op.name ~ ' + {assigning}'); # checked for in Hyper.new
my \op-is := nqp::ifnull(
nqp::atkey( # is it a core op?
nqp::ifnull($CORE_METAOP_ASSIGN,Rakudo::Internals.INSTALL-CORE-METAOPS),
nqp::objectid(op)
),
-> Mu \a, Mu \b { a = op.( ( a.DEFINITE ?? a !! op.() ), b) }
);
op-is.set_name(op.name ~ ' + {assigning}'); # checked for in Hyper.new
op-is
}

0 comments on commit 005261a

Please sign in to comment.
You can’t perform that action at this time.