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

Unified Diff: runtime/vm/intermediate_language.cc

Issue 2809583002: Use off-heap data for type feedback in PolymorphicInstanceCallInstr (Closed)
Patch Set: Created 3 years, 8 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
Index: runtime/vm/intermediate_language.cc
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 1ed759b493a3e8fd8574373539a3366afc7cdde3..27c7461e76c8280d9df85dc470ecffbcc17a4dd2 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3167,10 +3167,66 @@ bool InstanceCallInstr::MatchesCoreName(const String& name) {
bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const {
if (FLAG_precompiled_mode && with_checks()) return false;
+ return targets_.HasSingleRecognizedTarget();
+}
+
+
+bool PolymorphicTargets::HasSingleRecognizedTarget() const {
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 Please don't intersperse implementations of two di
erikcorry 2017/04/19 15:06:40 Done.
+ if (!HasSingleTarget()) return false;
+ return MethodRecognizer::RecognizeKind(FirstTarget()) !=
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 I think FirstTarget() should better be named Singl
erikcorry 2017/04/19 15:06:40 I'd like to leave it because it is sometimes used
+ MethodRecognizer::kUnknown;
+}
+
+
+bool PolymorphicTargets::HasSingleTarget() const {
+ ASSERT(length() != 0);
+ for (int i = 0; i < length(); i++) {
+ if (cid_ranges_[i].target->raw() != cid_ranges_[0].target->raw())
+ return false;
+ }
+ return true;
+}
- return ic_data().HasOneTarget() &&
- (MethodRecognizer::RecognizeKind(Function::Handle(
- ic_data().GetTargetAt(0))) != MethodRecognizer::kUnknown);
+
+bool PolymorphicInstanceCallInstr::HasOnlyDispatcherOrImplicitAccessorTargets()
+ const {
+ const intptr_t len = targets_.length();
+ Function& target = Function::Handle();
+ for (intptr_t i = 0; i < len; i++) {
+ target ^= targets_[i].target->raw();
+ if (!target.IsDispatcherOrImplicitAccessor()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool PolymorphicInstanceCallInstr::HasSingleRecognizedCid() const {
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 Why is this function called HasSingleRecognizedCid
erikcorry 2017/04/19 15:06:40 Done.
+ if (targets_.length() != 1) return false;
+ return targets_[0].cid_start == targets_[0].cid_end;
+}
+
+
+intptr_t PolymorphicInstanceCallInstr::SingleCid() const {
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 Better name would be MonomorphicReceiverCid().
erikcorry 2017/04/19 15:06:40 Done.
+ ASSERT(HasSingleRecognizedCid());
+ return targets_[0].cid_start;
+}
+
+
+Function& PolymorphicTargets::FirstTarget() const {
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 This should probably be SingleTarget()
erikcorry 2017/04/19 15:06:40 See above.
+ ASSERT(length() != 0);
+ ASSERT(cid_ranges_[0].target->IsZoneHandle());
+ return *cid_ranges_[0].target;
+}
+
+
+intptr_t PolymorphicInstanceCallInstr::CallCount() const {
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 This should probably be just calling the method on
erikcorry 2017/04/19 15:06:40 Done.
+ intptr_t sum = 0;
+ for (int i = 0; i < targets_.length(); i++) {
+ sum += targets_[i].count;
+ }
+ return sum;
}
@@ -3178,10 +3234,9 @@ bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const {
// PolymorphicInstanceCallInstr.
#if !defined(TARGET_ARCH_DBC)
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(ic_data().NumArgsTested() == 1);
if (!with_checks()) {
- ASSERT(ic_data().HasOneTarget());
- const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
+ ASSERT(HasSingleTarget());
+ const Function& target = Function::ZoneHandle(targets_[0].target->raw());
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 Instead of the targets[0].target access use target
erikcorry 2017/04/19 15:06:40 Done.
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(),
target, instance_call()->ArgumentCount(),
instance_call()->argument_names(), locs(),
@@ -3190,7 +3245,7 @@ void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
compiler->EmitPolymorphicInstanceCall(
- ic_data(), instance_call()->ArgumentCount(),
+ targets_, *instance_call(), instance_call()->ArgumentCount(),
instance_call()->argument_names(), deopt_id(),
instance_call()->token_pos(), locs(), complete(), total_call_count());
}
@@ -3198,22 +3253,29 @@ void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType(
- const ICData& ic_data) {
+ const PolymorphicTargets& targets) {
bool is_string = true;
bool is_integer = true;
bool is_double = true;
- const intptr_t num_checks = ic_data.NumberOfChecks();
+ const intptr_t num_checks = targets.length();
for (intptr_t i = 0; i < num_checks; i++) {
- const intptr_t cid = ic_data.GetReceiverClassIdAt(i);
- is_string = is_string && RawObject::IsStringClassId(cid);
- is_integer = is_integer && RawObject::IsIntegerClassId(cid);
- is_double = is_double && (cid == kDoubleCid);
+ ASSERT(targets[i].target->raw() == targets[0].target->raw());
+ const intptr_t start = targets[i].cid_start;
+ const intptr_t end = targets[i].cid_end;
+ for (intptr_t cid = start; cid <= end; cid++) {
+ is_string = is_string && RawObject::IsStringClassId(cid);
+ is_integer = is_integer && RawObject::IsIntegerClassId(cid);
+ is_double = is_double && (cid == kDoubleCid);
+ }
}
if (is_string) {
+ ASSERT(!is_integer);
+ ASSERT(!is_double);
return Type::StringType();
} else if (is_integer) {
+ ASSERT(!is_double);
return Type::IntType();
} else if (is_double) {
return Type::Double();
@@ -3226,12 +3288,20 @@ RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType(
Definition* InstanceCallInstr::Canonicalize(FlowGraph* flow_graph) {
const intptr_t receiver_cid = PushArgumentAt(0)->value()->Type()->ToCid();
- if (!HasICData()) return this;
+ if (ic_data()->NumArgsTested() != 1) return this;
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 Please elaborate why this check is here so that th
erikcorry 2017/04/19 15:06:40 I can't remember :-/. I have the benchmarking ser
+
+ // TODO(erikcorry): Even for cold call sites we could still try to look up
+ // methods when we know the receiver cid. We don't currently do this because
+ // it turns the InstanceCall into a PolymorphicInstanceCall which doesn't get
+ // recognized or inlined when it is cold.
Vyacheslav Egorov (Google) 2017/04/10 10:59:28 I don't think coldness has anything to do with it.
erikcorry 2017/04/19 15:06:40 Things seem to work with this check here, that che
+ if (ic_data()->NumberOfUsedChecks() == 0) return this;
- const ICData& new_ic_data =
- FlowGraphCompiler::TrySpecializeICDataByReceiverCid(*ic_data(),
- receiver_cid);
- if (new_ic_data.raw() == ic_data()->raw()) {
+ const PolymorphicTargets* new_target =
+ FlowGraphCompiler::TrySpecializeByReceiverCid(
+ Array::Handle(flow_graph->zone(), ic_data()->arguments_descriptor()),
+ String::Handle(flow_graph->zone(), ic_data()->target_name()),
+ receiver_cid);
+ if (new_target == NULL) {
// No specialization.
return this;
}
@@ -3239,21 +3309,21 @@ Definition* InstanceCallInstr::Canonicalize(FlowGraph* flow_graph) {
const bool with_checks = false;
const bool complete = false;
PolymorphicInstanceCallInstr* specialized = new PolymorphicInstanceCallInstr(
- this, new_ic_data, with_checks, complete);
+ this, *new_target, with_checks, complete);
flow_graph->InsertBefore(this, specialized, env(), FlowGraph::kValue);
return specialized;
}
Definition* PolymorphicInstanceCallInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasSingleRecognizedTarget() || with_checks()) {
+ if (!HasSingleRecognizedTarget()) {
return this;
}
- const Function& target = Function::Handle(ic_data().GetTargetAt(0));
+ const Function& target = FirstTarget();
if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) {
const AbstractType& type =
- AbstractType::Handle(ComputeRuntimeType(ic_data()));
+ AbstractType::Handle(ComputeRuntimeType(targets_));
if (!type.IsNull()) {
return flow_graph->GetConstant(type);
}

Powered by Google App Engine
This is Rietveld 408576698