Skip to content
Permalink
Browse files

Slightly cheaper hanlding of untyped scalars

This allows for a simpler guard sequence when we are checking an
assignment into such a container (we need only check against the type of
the descriptor, and we're done), resulting in a slight speedup.
  • Loading branch information...
jnthn committed Apr 8, 2019
1 parent 5598ddf commit 17643d495d3f8ac6a5b4e1e18e15f53c3aa591b2
Showing with 27 additions and 16 deletions.
  1. +9 −3 src/Perl6/Metamodel/BOOTSTRAP.nqp
  2. +4 −1 src/Perl6/World.nqp
  3. +14 −12 src/vm/moar/spesh-plugins.nqp
@@ -1161,6 +1161,10 @@ class ContainerDescriptor {
$ins
}
}
class ContainerDescriptor::Untyped is ContainerDescriptor {
# Container descriptor for when the type is Mu; the type of this
# container descriptor is used as a marker
}
role ContainerDescriptor::Whence {
has $!next-descriptor;

@@ -1611,7 +1615,8 @@ BEGIN {
my $type := $desc.of;
if nqp::eqaddr($type, Mu) || nqp::istype($val, $type) {
nqp::bindattr($cont, Scalar, '$!value', $val);
unless nqp::eqaddr($desc.WHAT, ContainerDescriptor) {
unless nqp::eqaddr($desc.WHAT, ContainerDescriptor) ||
nqp::eqaddr($desc.WHAT, ContainerDescriptor::Untyped) {
$desc.assigned($cont);
nqp::bindattr($cont, Scalar, '$!descriptor', $desc.next);
}
@@ -1633,7 +1638,8 @@ BEGIN {
'store_unchecked', nqp::getstaticcode(sub ($cont, $val) {
nqp::bindattr($cont, Scalar, '$!value', $val);
my $desc := nqp::getattr($cont, Scalar, '$!descriptor');
unless nqp::eqaddr($desc.WHAT, ContainerDescriptor) {
unless nqp::eqaddr($desc.WHAT, ContainerDescriptor) ||
nqp::eqaddr($desc.WHAT, ContainerDescriptor::Untyped) {
$desc.assigned($cont);
nqp::bindattr($cont, Scalar, '$!descriptor', $desc.next);
}
@@ -1687,7 +1693,7 @@ BEGIN {
# Cache a single default Scalar container spec, to ensure we only get
# one of them.
Scalar.HOW.cache_add(Scalar, 'default_cont_spec',
ContainerDescriptor.new(
ContainerDescriptor::Untyped.new(
:of(Mu), :default(Any), :name('element')));

# Set up various native reference types.
@@ -1715,7 +1715,10 @@ class Perl6::World is HLL::World {

# Creates a new container descriptor and adds it to the SC.
method create_container_descriptor($of, $name, $default = $of, $dynamic = is_dynamic($name)) {
my $cd_type := self.find_symbol(['ContainerDescriptor'], :setting-only);
my $cd_type_name := nqp::eqaddr($of, self.find_symbol(['Mu'], :setting-only))
?? ['ContainerDescriptor', 'Untyped']
!! ['ContainerDescriptor'];
my $cd_type := self.find_symbol($cd_type_name, :setting-only);
my $cd := $cd_type.new( :$of, :$name, :$default, :$dynamic );
self.add_object_if_no_sc($cd);
$cd
@@ -362,27 +362,17 @@ nqp::speshreg('perl6', 'assign', sub ($cont, $value) {
}
else {
# No whence, no Nil. Is it a nominal type? If yes, we can check
# it here. There are two interesting cases. One is if the type
# constraint is Mu. To avoid a huge guard set at megamorphic
# assignment sites, for this case we just guard $!of being Mu
# and the value not being Nil. For other cases, where there is
# a type constraint, we guard on the descriptor and the value,
# provided it typechecks OK.
# it here.
my $of := $desc.of;
unless $of.HOW.archetypes.nominal {
nqp::speshguardobj($desc);
return &assign-scalar-no-whence;
}
if nqp::eqaddr($of, Mu) {
if nqp::istype($value, $of) {
nqp::speshguardtype($desc, $desc.WHAT);
nqp::speshguardconcrete($desc);
my $of := nqp::speshguardgetattr($desc, ContainerDescriptor, '$!of');
nqp::speshguardobj($of);
nqp::speshguardnotobj($value, Nil);
return &assign-scalar-no-whence-no-typecheck;
}
elsif nqp::istype($value, $of) {
nqp::speshguardobj($desc);
nqp::speshguardtype($value, $value.WHAT);
return &assign-scalar-no-whence-no-typecheck;
}
@@ -392,6 +382,18 @@ nqp::speshreg('perl6', 'assign', sub ($cont, $value) {
}
}
}
elsif nqp::eqaddr($desc.WHAT, ContainerDescriptor::Untyped) && nqp::isconcrete($desc) {
# Assignment to an untyped container descriptor; handle this
# more simply.
if nqp::eqaddr($value, Nil) {
# Nil case is NYI.
}
else {
nqp::speshguardtype($desc, $desc.WHAT);
nqp::speshguardnotobj($value, Nil);
return &assign-scalar-no-whence-no-typecheck;
}
}
elsif nqp::eqaddr($desc.WHAT, ContainerDescriptor::BindArrayPos) {
# Bind into an array. We can produce a fast path for this, though
# should check what the ultimate descriptor is. It really should

0 comments on commit 17643d4

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