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

Unified Diff: runtime/vm/jit_optimizer.cc

Issue 2836043002: Revert "Reland "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
« no previous file with comments | « runtime/vm/jit_optimizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/jit_optimizer.cc
diff --git a/runtime/vm/jit_optimizer.cc b/runtime/vm/jit_optimizer.cc
index fb6ee1d43be1d01be334cbb573a14b2f57af868e..bdfcddcf09c00fd4e391dfcdc6dc4debc786c0ba 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -209,13 +209,9 @@ void JitOptimizer::SpecializePolymorphicInstanceCall(
return; // No information about receiver was infered.
}
- const ICData& ic_data = *call->instance_call()->ic_data();
-
- const CallTargets* targets =
- FlowGraphCompiler::ResolveCallTargetsForReceiverCid(
- receiver_cid, String::Handle(zone(), ic_data.target_name()),
- Array::Handle(zone(), ic_data.arguments_descriptor()));
- if (targets == NULL) {
+ const ICData& ic_data = FlowGraphCompiler::TrySpecializeICDataByReceiverCid(
+ call->ic_data(), receiver_cid);
+ if (ic_data.raw() == call->ic_data().raw()) {
// No specialization.
return;
}
@@ -223,7 +219,7 @@ void JitOptimizer::SpecializePolymorphicInstanceCall(
const bool with_checks = false;
const bool complete = false;
PolymorphicInstanceCallInstr* specialized =
- new (Z) PolymorphicInstanceCallInstr(call->instance_call(), *targets,
+ new (Z) PolymorphicInstanceCallInstr(call->instance_call(), ic_data,
with_checks, complete);
call->ReplaceWith(specialized, current_iterator());
}
@@ -1452,6 +1448,85 @@ void JitOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
}
+bool JitOptimizer::LookupMethodFor(int class_id,
+ const ArgumentsDescriptor& args_desc,
+ const String& name,
+ Function* fn_return) {
+ if (class_id < 0) return false;
+ if (class_id >= I->class_table()->NumCids()) return false;
+
+ RawClass* raw_class = I->class_table()->At(class_id);
+ if (raw_class == NULL) return false;
+ Class& cls = Class::Handle(Z, raw_class);
+ if (cls.IsNull()) return false;
+ if (!cls.is_finalized()) return false;
+ if (Array::Handle(cls.functions()).IsNull()) return false;
+
+ bool allow_add = false;
+ Function& target_function =
+ Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass(
+ cls, name, args_desc, allow_add));
+ if (target_function.IsNull()) return false;
+ *fn_return ^= target_function.raw();
+ return true;
+}
+
+
+static int OrderById(const intptr_t* a, const intptr_t* b) {
+ // Negative if 'a' should sort before 'b'.
+ return *a - *b;
+}
+
+
+void JitOptimizer::TryExpandClassesInICData(const ICData& ic_data) {
+ if (ic_data.NumberOfChecks() == 0) return;
+
+ Function& dummy = Function::Handle(Z);
+
+ GrowableArray<intptr_t> ids;
+ for (int i = 0; i < ic_data.NumberOfChecks(); i++) {
+ // The API works for multi dispatch ICs that check more than one argument,
+ // but we know we only check one arg here, so only the 0th element of id
+ // will be used.
+ GrowableArray<intptr_t> id;
+ ic_data.GetCheckAt(i, &id, &dummy);
+ ids.Add(id[0]);
+ }
+ ids.Sort(OrderById);
+
+ Array& args_desc_array = Array::Handle(Z, ic_data.arguments_descriptor());
+ ArgumentsDescriptor args_desc(args_desc_array);
+ String& name = String::Handle(Z, ic_data.target_name());
+
+ Function& fn = Function::Handle(Z);
+ Function& fn_high = Function::Handle(Z);
+ Function& possible_match = Function::Handle(Z);
+
+ for (int cid_index = 0; cid_index < ids.length() - 1; cid_index++) {
+ int low_cid = ids[cid_index];
+ int high_cid = ids[cid_index + 1];
+ if (low_cid + 1 == high_cid) continue;
+ if (LookupMethodFor(low_cid, args_desc, name, &fn) &&
+ LookupMethodFor(high_cid, args_desc, name, &fn_high) &&
+ fn.raw() == fn_high.raw()) {
+ // Try to fill in the IC table by going downwards from a known class-id.
+ bool can_fill_in = true;
+ for (int i = low_cid + 1; i < high_cid; i++) {
+ if (!LookupMethodFor(i, args_desc, name, &possible_match) ||
+ possible_match.raw() != fn.raw()) {
+ can_fill_in = false;
+ break;
+ }
+ }
+ if (can_fill_in) {
+ for (int i = low_cid + 1; i < high_cid; i++) {
+ ic_data.AddReceiverCheck(i, fn, 0);
+ }
+ }
+ }
+ }
+}
+
// Tries to optimize instance call by replacing it with a faster instruction
// (e.g, binary op, field load, ..).
void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
@@ -1509,9 +1584,11 @@ void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
return;
}
- CallTargets* targets = CallTargets::Create(Z, unary_checks);
+ // Now we are done trying the inlining options that benefit from only having
+ // 1 entry in the IC table.
+ TryExpandClassesInICData(unary_checks);
- bool has_one_target = targets->HasSingleTarget();
+ bool has_one_target = unary_checks.HasOneTarget();
if (has_one_target) {
// Check if the single target is a polymorphic target, if it is,
@@ -1519,7 +1596,7 @@ void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0));
if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) {
has_one_target = PolymorphicInstanceCallInstr::ComputeRuntimeType(
- *targets) != Type::null();
+ unary_checks) != Type::null();
} else {
const bool polymorphic_target =
MethodRecognizer::PolymorphicTarget(target);
@@ -1532,7 +1609,7 @@ void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
const RawFunction::Kind function_kind = target.kind();
if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) {
PolymorphicInstanceCallInstr* call =
- new (Z) PolymorphicInstanceCallInstr(instr, *targets,
+ new (Z) PolymorphicInstanceCallInstr(instr, unary_checks,
/* call_with_checks = */ false,
/* complete = */ false);
instr->ReplaceWith(call, current_iterator());
@@ -1555,17 +1632,15 @@ void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
(!instr->ic_data()->HasDeoptReason(ICData::kDeoptCheckClass) ||
unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
// Type propagation has not run yet, we cannot eliminate the check.
- // TODO(erikcorry): The receiver check should use the off-heap targets
- // array, not the IC array.
AddReceiverCheck(instr);
// Call can still deoptimize, do not detach environment from instr.
call_with_checks = false;
} else {
call_with_checks = true;
}
- PolymorphicInstanceCallInstr* call =
- new (Z) PolymorphicInstanceCallInstr(instr, *targets, call_with_checks,
- /* complete = */ false);
+ PolymorphicInstanceCallInstr* call = new (Z)
+ PolymorphicInstanceCallInstr(instr, unary_checks, call_with_checks,
+ /* complete = */ false);
instr->ReplaceWith(call, current_iterator());
}
« no previous file with comments | « runtime/vm/jit_optimizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698