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 8b8e9618a3a43af14d77388ea858df2630a7d99c..aa5dd158d7d116052447cc1c2caeac9a4867d4f3 100644 |
--- a/runtime/vm/flow_graph_type_propagator.cc |
+++ b/runtime/vm/flow_graph_type_propagator.cc |
@@ -21,6 +21,24 @@ DEFINE_FLAG(bool, |
DECLARE_FLAG(bool, propagate_types); |
+static void TraceStrongModeType(const Instruction* instr, |
+ const AbstractType& type) { |
+ if (FLAG_trace_experimental_strong_mode) { |
+ THR_Print("[Strong mode] Type of %s - %s\n", instr->ToCString(), |
+ type.ToCString()); |
+ } |
+} |
+ |
+static void TraceStrongModeType(const Instruction* instr, |
+ CompileType* compileType) { |
+ if (FLAG_trace_experimental_strong_mode) { |
+ const AbstractType* type = compileType->ToAbstractType(); |
+ if ((type != NULL) && !type->IsDynamicType()) { |
+ TraceStrongModeType(instr, *type); |
+ } |
+ } |
+} |
+ |
void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) { |
#ifndef PRODUCT |
Thread* thread = flow_graph->thread(); |
@@ -828,6 +846,13 @@ CompileType ParameterInstr::ComputeType() const { |
return CompileType(CompileType::kNonNullable, cid, &type); |
} |
+ if (FLAG_experimental_strong_mode && block_->IsGraphEntry()) { |
+ LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope(); |
+ const AbstractType& param_type = scope->VariableAt(index())->type(); |
+ TraceStrongModeType(this, param_type); |
+ return CompileType::FromAbstractType(param_type); |
+ } |
+ |
return CompileType::Dynamic(); |
} |
@@ -928,12 +953,36 @@ CompileType AllocateUninitializedContextInstr::ComputeType() const { |
&Object::dynamic_type()); |
} |
+CompileType InstanceCallInstr::ComputeType() const { |
+ if (FLAG_experimental_strong_mode) { |
+ const Function& target = interface_target(); |
+ if (!target.IsNull()) { |
+ // TODO(alexmarkov): instantiate generic result_type |
+ const AbstractType& result_type = |
+ AbstractType::ZoneHandle(target.result_type()); |
+ TraceStrongModeType(this, result_type); |
+ return CompileType::FromAbstractType(result_type); |
+ } |
+ } |
+ |
+ return CompileType::Dynamic(); |
+} |
+ |
CompileType PolymorphicInstanceCallInstr::ComputeType() const { |
- if (!IsSureToCallSingleRecognizedTarget()) return CompileType::Dynamic(); |
- const Function& target = *targets_.TargetAt(0)->target; |
- return (target.recognized_kind() != MethodRecognizer::kUnknown) |
- ? CompileType::FromCid(MethodRecognizer::ResultCid(target)) |
- : CompileType::Dynamic(); |
+ if (IsSureToCallSingleRecognizedTarget()) { |
+ const Function& target = *targets_.TargetAt(0)->target; |
+ if (target.recognized_kind() != MethodRecognizer::kUnknown) { |
+ return CompileType::FromCid(MethodRecognizer::ResultCid(target)); |
+ } |
+ } |
+ |
+ if (FLAG_experimental_strong_mode) { |
+ CompileType* type = instance_call()->Type(); |
+ TraceStrongModeType(this, type); |
+ return *type; |
+ } |
+ |
+ return CompileType::Dynamic(); |
} |
CompileType StaticCallInstr::ComputeType() const { |
@@ -941,20 +990,25 @@ CompileType StaticCallInstr::ComputeType() const { |
return CompileType::FromCid(result_cid_); |
} |
- if (Isolate::Current()->type_checks()) { |
+ if (function_.recognized_kind() != MethodRecognizer::kUnknown) { |
+ return CompileType::FromCid(MethodRecognizer::ResultCid(function_)); |
+ } |
+ |
+ if (FLAG_experimental_strong_mode || Isolate::Current()->type_checks()) { |
const AbstractType& result_type = |
AbstractType::ZoneHandle(function().result_type()); |
+ TraceStrongModeType(this, result_type); |
return CompileType::FromAbstractType(result_type); |
} |
- return (function_.recognized_kind() != MethodRecognizer::kUnknown) |
- ? CompileType::FromCid(MethodRecognizer::ResultCid(function_)) |
- : CompileType::Dynamic(); |
+ return CompileType::Dynamic(); |
} |
CompileType LoadLocalInstr::ComputeType() const { |
- if (Isolate::Current()->type_checks()) { |
- return CompileType::FromAbstractType(local().type()); |
+ if (FLAG_experimental_strong_mode || Isolate::Current()->type_checks()) { |
+ const AbstractType& local_type = local().type(); |
+ TraceStrongModeType(this, local_type); |
+ return CompileType::FromAbstractType(local_type); |
} |
return CompileType::Dynamic(); |
} |
@@ -986,9 +1040,10 @@ CompileType LoadStaticFieldInstr::ComputeType() const { |
intptr_t cid = kDynamicCid; |
AbstractType* abstract_type = NULL; |
const Field& field = this->StaticField(); |
- if (Isolate::Current()->type_checks()) { |
+ if (FLAG_experimental_strong_mode || Isolate::Current()->type_checks()) { |
cid = kIllegalCid; |
abstract_type = &AbstractType::ZoneHandle(field.type()); |
+ TraceStrongModeType(this, *abstract_type); |
} |
ASSERT(field.is_static()); |
if (field.is_final()) { |
@@ -1039,9 +1094,11 @@ CompileType LoadFieldInstr::ComputeType() const { |
} |
const AbstractType* abstract_type = NULL; |
- if (Isolate::Current()->type_checks() && |
- (type().IsFunctionType() || type().HasResolvedTypeClass())) { |
+ if (FLAG_experimental_strong_mode || |
+ (Isolate::Current()->type_checks() && |
+ (type().IsFunctionType() || type().HasResolvedTypeClass()))) { |
abstract_type = &type(); |
+ TraceStrongModeType(this, *abstract_type); |
} |
if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid)) { |
@@ -1106,6 +1163,24 @@ CompileType UnaryInt64OpInstr::ComputeType() const { |
return CompileType::Int(); |
} |
+CompileType CheckedSmiOpInstr::ComputeType() const { |
+ if (FLAG_experimental_strong_mode) { |
+ CompileType* type = call()->Type(); |
+ TraceStrongModeType(this, type); |
+ return *type; |
+ } |
+ return CompileType::Dynamic(); |
+} |
+ |
+CompileType CheckedSmiComparisonInstr::ComputeType() const { |
+ if (FLAG_experimental_strong_mode) { |
+ CompileType* type = call()->Type(); |
+ TraceStrongModeType(this, type); |
+ return *type; |
+ } |
+ return CompileType::Dynamic(); |
+} |
+ |
CompileType BoxIntegerInstr::ComputeType() const { |
return ValueFitsSmi() ? CompileType::FromCid(kSmiCid) : CompileType::Int(); |
} |