1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 17:30:16 +00:00

[vm/compiler] handle non-nullable null situation better

Rationale:
Previously, we avoided introducing redefinitions that
introduced the empty non-nullable null type. This situation
arises when we do a null check on an actual null value
(making all subsequent uses effectively dead code). This
is too simple, however, since it still allows hoisting the
uses before the check. This CL gives a better solution
by introducing redefinitions without a constraining type
(which are not removed and avoid the type). In the long
run perhaps the best solution would be to simply remove
all subsequent uses as dead.

https://github.com/dart-lang/sdk/issues/32167
https://github.com/dart-lang/sdk/issues/34473
https://github.com/dart-lang/sdk/issues/35335

Change-Id: Ib5dd072a9e546f6b91faa52ea08e8c0f6350d7e0
Reviewed-on: https://dart-review.googlesource.com/c/89922
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Aart Bik <ajcbik@google.com>
This commit is contained in:
Aart Bik 2019-01-17 22:22:32 +00:00 committed by commit-bot@chromium.org
parent b692a6d183
commit c701e76506
3 changed files with 16 additions and 4 deletions

View File

@ -80,7 +80,13 @@ class CompileType : public ZoneAllocated {
// abstract type. The pair is assumed to be coherent.
static CompileType Create(intptr_t cid, const AbstractType& type);
CompileType CopyNonNullable() const {
// Return the non-nullable version of this type.
CompileType CopyNonNullable() {
if (IsNull()) {
// Represent a non-nullable null type (typically arising for
// unreachable values) as None.
return None();
}
return CompileType(kNonNullable, kIllegalCid, type_);
}

View File

@ -1559,7 +1559,13 @@ RedefinitionInstr* FlowGraph::EnsureRedefinition(Instruction* prev,
}
}
RedefinitionInstr* redef = new RedefinitionInstr(new Value(original));
redef->set_constrained_type(new CompileType(compile_type));
// Don't set the constrained type when the type is None(), which denotes an
// unreachable value (e.g. using value null after an explicit null check).
if (!compile_type.IsNone()) {
redef->set_constrained_type(new CompileType(compile_type));
}
InsertAfter(prev, redef, NULL, FlowGraph::kValue);
RenameDominatedUses(original, redef, redef);
return redef;

View File

@ -283,7 +283,7 @@ void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) {
void FlowGraphTypePropagator::VisitCheckNull(CheckNullInstr* check) {
Definition* receiver = check->value()->definition();
CompileType* type = TypeOf(receiver);
if (type->is_nullable() && !type->IsNull()) {
if (type->is_nullable()) {
// Insert redefinition for the receiver to guard against invalid
// code motion.
EnsureMoreAccurateRedefinition(check, receiver, type->CopyNonNullable());
@ -305,7 +305,7 @@ void FlowGraphTypePropagator::CheckNonNullSelector(
if (target.IsNull()) {
// If the selector is not defined on Null, we can propagate non-nullness.
CompileType* type = TypeOf(receiver);
if (type->is_nullable() && !type->IsNull()) {
if (type->is_nullable()) {
// Insert redefinition for the receiver to guard against invalid
// code motion.
EnsureMoreAccurateRedefinition(call, receiver, type->CopyNonNullable());