Permalink
Browse files

Merge branch 'rescalar'

Extensively re-works Scalar containers and various things around them.
Of note:

* The process of type-checking, Nil-handling, and doing vivification of
  Scalar containers has moved to NQP code, away from C/Java code
* A number of cases of assignment are now optimized via. spesh plugins
  on the MoarVM backend, thus eliminating type checks, Nil checks, and
  auto-viv checks
* The auto-viv process is now handled through the descriptor mechanism,
  meaning that every Scalar gets a pointer smaller. This means every
  Array and Scalar gets a pointer smaller per assigned element too.
* Various extops have gone away in favor of code generation and spesh
  plugins. Of note, return value decont/recont is now emitted as a
  spesh plugin call, and often virtually disappears.
* The return value decont handling is fixed with regard to Proxy; it
  failed to decontainerize them before

There's still some re-turning and optimizing to come atop of this work,
but this is being merged now to allow more testing of this very major
set of changes ahead of the release.
  • Loading branch information...
jnthn committed Jul 9, 2018
2 parents c2446b0 + 05d7c39 commit 68ed6f2d874c9d75022eb14118c9a569c80ef04c

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
@@ -628,7 +628,7 @@ my class BlockVarOptimizer {
next unless $scope eq 'lexical';
# Also ensure not dynamic.
my $dynamic := try nqp::getattr($qast.value, nqp::p6var($qast.value).WHAT, '$!descriptor').dynamic;
my $dynamic := try nqp::getattr($qast.value, nqp::what_nd($qast.value), '$!descriptor').dynamic;
next if $dynamic;
# Consider name. Can't lower if it's used by any nested blocks.
@@ -1132,7 +1132,7 @@ class Perl6::Optimizer {
# Let's see if we can catch a type mismatch in assignment at compile-time.
# Especially with Num, Rat, and Int there's often surprises at run-time.
if ($optype eq 'assign' || $optype eq 'assign_n' || $optype eq 'assign_i')
if ($optype eq 'p6assign' || $optype eq 'assign_n' || $optype eq 'assign_i')
&& nqp::istype($op[0], QAST::Var)
&& ($op[0].scope eq 'lexical' || $op[0].scope eq 'lexicalref') {
if nqp::istype($op[1], QAST::Want) {
@@ -1914,7 +1914,7 @@ class Perl6::Optimizer {
$is-always-definite := 1;
}
elsif $sigil eq '$' {
$assignop := 'assign';
$assignop := 'p6assign';
}
elsif $sigil eq '@' || $sigil eq '%' {
$assignop := 'p6store';
@@ -1979,7 +1979,7 @@ class Perl6::Optimizer {
$op.annotate_self: 'METAOP_opt_result', 1;
$op.returns: $assignee.returns
if $assignop ne 'assign'
if $assignop ne 'p6assign'
&& nqp::objprimspec($assignee.returns);
my $*NO-COMPILE-TIME-THROWAGE := 1;
@@ -1569,9 +1569,9 @@ class Perl6::World is HLL::World {
}
# Creates a new container descriptor and adds it to the SC.
method create_container_descriptor($of, $rw, $name, $default = $of, $dynamic = nqp::chars($name) > 2 && nqp::eqat($name, '*', 1)) {
method create_container_descriptor($of, $name, $default = $of, $dynamic = nqp::chars($name) > 2 && nqp::eqat($name, '*', 1)) {
my $cd_type := self.find_symbol(['ContainerDescriptor'], :setting-only);
my $cd := $cd_type.new( :$of, :$rw, :$name, :$default, :$dynamic );
my $cd := $cd_type.new( :$of, :$name, :$default, :$dynamic );
self.add_object($cd);
$cd
}
@@ -1797,7 +1797,7 @@ class Perl6::World is HLL::World {
'scalar_value', $WHAT,
);
my $desc :=
self.create_container_descriptor($Mu, 1, $name, $WHAT, 1);
self.create_container_descriptor($Mu, $name, $WHAT, 1);
my $cont := self.build_container_and_add_to_sc(%info, $desc);
@@ -1870,7 +1870,7 @@ class Perl6::World is HLL::World {
my %cont_info := self.container_type_info(NQPMu, $var<sigil>,
$*OFTYPE ?? [$*OFTYPE.ast] !! [], []);
%cont_info<value_type> := self.find_symbol(['Any'], :setting-only);
my $descriptor := self.create_container_descriptor(%cont_info<value_type>, 1, $name);
my $descriptor := self.create_container_descriptor(%cont_info<value_type>, $name);
nqp::die("auto_declare_var") unless nqp::objectid($*PACKAGE) == nqp::objectid($*LEAF.package);
self.install_lexical_container($BLOCK, $name, %cont_info, $descriptor,
@@ -2060,6 +2060,7 @@ class Perl6::World is HLL::World {
# Walk parameters, setting up parameter objects.
my $default_type := self.find_symbol([$default_type_name]);
my $param_type := self.find_symbol(['Parameter'], :setting-only);
my @param_objs;
my %seen_names;
for @params {
@@ -2097,26 +2098,26 @@ class Perl6::World is HLL::World {
$_<sub_signature_params>, $lexpad, $default_type_name);
}
# Create parameter object and apply any traits.
my $param_obj := self.create_parameter($/, $_);
self.apply_traits($_<traits>, $param_obj) if $_<traits>;
# Add variable as needed.
my int $flags := nqp::getattr_i($param_obj, $param_type, '$!flags');
my $varname := $_<variable_name>;
if $varname {
if $varname && ($flags +& $SIG_ELEM_IS_RW || $flags +& $SIG_ELEM_IS_COPY) {
my %sym := $lexpad.symbol($varname);
if +%sym && !nqp::existskey(%sym, 'descriptor') {
$_<container_descriptor> := self.create_container_descriptor(
$_<nominal_type>, $_<is_rw> ?? 1 !! 0, $varname);
$lexpad.symbol($varname, :descriptor($_<container_descriptor>));
my $desc := self.create_container_descriptor($_<nominal_type>, $varname);
$_<container_descriptor> := $desc;
nqp::bindattr($param_obj, $param_type, '$!container_descriptor', $desc);
$lexpad.symbol($varname, :descriptor($desc));
}
}
# Create parameter object and apply any traits.
my $param_obj := self.create_parameter($/, $_);
self.apply_traits($_<traits>, $param_obj) if $_<traits>;
# If it's natively typed and we got "is rw" set, need to mark the
# container as being a lexical ref.
if $varname && nqp::objprimspec($_<nominal_type>) {
my $param_type := self.find_symbol(['Parameter'], :setting-only);
my int $flags := nqp::getattr_i($param_obj, $param_type, '$!flags');
if $flags +& $SIG_ELEM_IS_RW {
for @($lexpad[0]) {
if nqp::istype($_, QAST::Var) && $_.name eq $varname {
@@ -3912,7 +3913,7 @@ class Perl6::World is HLL::World {
%info<bind_constraint> := self.find_symbol(['Associative'], :setting-only);
%info<value_type> := $mu;
self.install_lexical_container($*UNIT, '!INIT_VALUES', %info,
self.create_container_descriptor($mu, 1, '!INIT_VALUES'));
self.create_container_descriptor($mu, '!INIT_VALUES'));
}
$*UNIT[0].push(QAST::Op.new(
:op('callmethod'), :name('BIND-KEY'),
@@ -251,30 +251,10 @@ my class Any { # declared in BOOTSTRAP
proto method AT-POS(|) is nodal {*}
multi method AT-POS(Any:U \SELF: int \pos) is raw {
nqp::p6bindattrinvres(
my $scalar,
Scalar,
'$!whence',
-> { nqp::if(
nqp::isconcrete(SELF),
SELF,
(SELF = Array.new)
).BIND-POS(pos, $scalar)
}
)
nqp::p6scalarfromdesc(ContainerDescriptor::VivifyArray.new(SELF, pos))
}
multi method AT-POS(Any:U \SELF: Int:D \pos) is raw {
nqp::p6bindattrinvres(
my $scalar,
Scalar,
'$!whence',
-> { nqp::if(
nqp::isconcrete(SELF),
SELF,
(SELF = Array.new)
).BIND-POS(pos, $scalar)
}
)
nqp::p6scalarfromdesc(ContainerDescriptor::VivifyArray.new(SELF, pos))
}
multi method AT-POS(Any:U: Num:D \pos) is raw {
nqp::isnanorinf(pos)
@@ -405,21 +385,7 @@ my class Any { # declared in BOOTSTRAP
)
}
multi method AT-KEY(Any:U \SELF: \key) is raw {
nqp::p6bindattrinvres(
my $scalar,
Scalar,
'$!whence',
# NOTE: even though the signature indicates a non-concrete SELF,
# by the time the below code is executed, it *may* have become
# concrete: and then we don't want the execution to reset it to
# an empty Hash.
-> { nqp::if(
nqp::isconcrete(SELF),
SELF,
(SELF = nqp::create(Hash))
).BIND-KEY(key, $scalar)
}
)
nqp::p6scalarfromdesc(ContainerDescriptor::VivifyHash.new(SELF, key))
}
proto method BIND-KEY(|) is nodal {*}
Oops, something went wrong.

0 comments on commit 68ed6f2

Please sign in to comment.