Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Unified Diff: runtime/vm/flow_graph_type_propagator.cc

Issue 3010673002: [vm] Implement gradual refinement of types (Closed)
Patch Set: Address review comments Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/aot_optimizer.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_type_propagator.cc
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 7ac2516bb0dbdd158eb0b81dd613ffa6f3bd72dd..b703e00ae1486e50e77253b7661f16e4452ca564 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -19,8 +19,6 @@ DEFINE_FLAG(bool,
false,
"Trace flow graph type propagation");
-DECLARE_FLAG(bool, propagate_types);
-
static void TraceStrongModeType(const Instruction* instr,
const AbstractType& type) {
if (FLAG_trace_experimental_strong_mode) {
@@ -204,13 +202,22 @@ void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) {
void FlowGraphTypePropagator::VisitValue(Value* value) {
CompileType* type = TypeOf(value->definition());
- value->SetReachingType(type);
+
+ // Force propagation of None type (which means unknown) to inputs of phis
+ // in order to avoid contamination of cycles of phis with previously inferred
+ // types.
+ if (type->IsNone() && value->instruction()->IsPhi()) {
+ value->SetReachingType(type);
+ } else {
+ value->RefineReachingType(type);
+ }
if (FLAG_support_il_printer && FLAG_trace_type_propagation &&
FlowGraphPrinter::ShouldPrint(flow_graph_->function())) {
THR_Print("reaching type to %s for v%" Pd " is %s\n",
value->instruction()->ToCString(),
- value->definition()->ssa_temp_index(), type->ToCString());
+ value->definition()->ssa_temp_index(),
+ value->Type()->ToCString());
}
}
@@ -326,9 +333,9 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
comparison->InputAt(0)->definition()->AsLoadClassId();
InstanceCallInstr* call =
comparison->InputAt(0)->definition()->AsInstanceCall();
- InstanceOfInstr* instanceOf =
+ InstanceOfInstr* instance_of =
comparison->InputAt(0)->definition()->AsInstanceOf();
- bool is_simpleInstanceOf =
+ bool is_simple_instance_of =
(call != NULL) && call->MatchesCoreName(Symbols::_simpleInstanceOf());
RedefinitionInstr* redef = NULL;
if (load_cid != NULL && comparison->InputAt(1)->BindsToConstant()) {
@@ -338,7 +345,7 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
redef = flow_graph_->EnsureRedefinition(true_successor,
load_cid->object()->definition(),
CompileType::FromCid(cid));
- } else if ((is_simpleInstanceOf || (instanceOf != NULL)) &&
+ } else if ((is_simple_instance_of || (instance_of != NULL)) &&
comparison->InputAt(1)->BindsToConstant() &&
comparison->InputAt(1)->BoundConstant().IsBool()) {
if (comparison->InputAt(1)->BoundConstant().raw() == Bool::False().raw()) {
@@ -348,7 +355,7 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
negated ? instr->false_successor() : instr->true_successor();
const AbstractType* type = NULL;
Definition* left = NULL;
- if (is_simpleInstanceOf) {
+ if (is_simple_instance_of) {
ASSERT(call->ArgumentAt(1)->IsConstant());
const Object& type_obj = call->ArgumentAt(1)->AsConstant()->value();
if (!type_obj.IsType()) {
@@ -357,8 +364,8 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
type = &Type::Cast(type_obj);
left = call->ArgumentAt(0);
} else {
- type = &(instanceOf->type());
- left = instanceOf->value()->definition();
+ type = &(instance_of->type());
+ left = instance_of->value()->definition();
}
if (!type->IsDynamicType() && !type->IsObjectType()) {
const bool is_nullable = type->IsNullType() ? CompileType::kNullable
@@ -508,13 +515,13 @@ void CompileType::Union(CompileType* other) {
cid_ = kDynamicCid;
}
- const AbstractType* compile_type = ToAbstractType();
- const AbstractType* other_compile_type = other->ToAbstractType();
- if (compile_type->IsMoreSpecificThan(*other_compile_type, NULL, NULL,
- Heap::kOld)) {
- type_ = other_compile_type;
- } else if (other_compile_type->IsMoreSpecificThan(*compile_type, NULL, NULL,
- Heap::kOld)) {
+ const AbstractType* abstract_type = ToAbstractType();
+ const AbstractType* other_abstract_type = other->ToAbstractType();
+ if (abstract_type->IsMoreSpecificThan(*other_abstract_type, NULL, NULL,
+ Heap::kOld)) {
+ type_ = other_abstract_type;
+ } else if (other_abstract_type->IsMoreSpecificThan(*abstract_type, NULL, NULL,
+ Heap::kOld)) {
// Nothing to do.
} else {
// Can't unify.
@@ -522,6 +529,53 @@ void CompileType::Union(CompileType* other) {
}
}
+CompileType* CompileType::ComputeRefinedType(CompileType* old_type,
+ CompileType* new_type) {
+ // In general, prefer the newly inferred type over old type.
+ // It is possible that new and old types are unrelated or do not intersect
+ // at all (for example, in case of unreachable code).
+
+ // Discard None type as it is used to denote an unknown type.
+ if (old_type->IsNone()) {
+ return new_type;
+ }
+ if (new_type->IsNone()) {
+ return old_type;
+ }
+
+ // Prefer exact Cid if known.
+ if (new_type->ToCid() != kDynamicCid) {
+ return new_type;
+ }
+ if (old_type->ToCid() != kDynamicCid) {
+ return old_type;
+ }
+
+ const AbstractType* old_abstract_type = old_type->ToAbstractType();
+ const AbstractType* new_abstract_type = new_type->ToAbstractType();
+
+ CompileType* preferred_type;
+ if (old_abstract_type->IsMoreSpecificThan(*new_abstract_type, NULL, NULL,
+ Heap::kOld)) {
+ // Prefer old type, as it is clearly more specific.
+ preferred_type = old_type;
+ } else {
+ // Prefer new type as it is more recent, even though it might be
+ // no better than the old type.
+ preferred_type = new_type;
+ }
+
+ // Refine non-nullability.
+ bool is_nullable = old_type->is_nullable() && new_type->is_nullable();
+
+ if (preferred_type->is_nullable() && !is_nullable) {
+ return new CompileType(preferred_type->CopyNonNullable());
+ } else {
+ ASSERT(preferred_type->is_nullable() == is_nullable);
+ return preferred_type;
+ }
+}
+
static bool IsNullableCid(intptr_t cid) {
ASSERT(cid != kIllegalCid);
return cid == kNullCid || cid == kDynamicCid;
@@ -714,6 +768,15 @@ CompileType* Value::Type() {
return reaching_type_;
}
+void Value::RefineReachingType(CompileType* type) {
+ ASSERT(type != NULL);
+ if (reaching_type_ == NULL) {
+ reaching_type_ = type;
+ } else {
+ reaching_type_ = CompileType::ComputeRefinedType(reaching_type_, type);
+ }
+}
+
CompileType PhiInstr::ComputeType() const {
// Initially type of phis is unknown until type propagation is run
// for the first time.
« no previous file with comments | « runtime/vm/aot_optimizer.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698