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

Unified Diff: runtime/vm/jit_optimizer.cc

Issue 2809583002: Use off-heap data for type feedback in PolymorphicInstanceCallInstr (Closed)
Patch Set: More feedback from Slava 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 f85d9c46fb3b212ad580ed0ee36a5428469b0e57..6dbb8194964a4c4b3d569fce522910fa3cab3e01 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -209,9 +209,13 @@ void JitOptimizer::SpecializePolymorphicInstanceCall(
return; // No information about receiver was infered.
}
- const ICData& ic_data = FlowGraphCompiler::TrySpecializeICDataByReceiverCid(
- call->ic_data(), receiver_cid);
- if (ic_data.raw() == call->ic_data().raw()) {
+ 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) {
// No specialization.
return;
}
@@ -219,7 +223,7 @@ void JitOptimizer::SpecializePolymorphicInstanceCall(
const bool with_checks = false;
const bool complete = false;
PolymorphicInstanceCallInstr* specialized =
- new (Z) PolymorphicInstanceCallInstr(call->instance_call(), ic_data,
+ new (Z) PolymorphicInstanceCallInstr(call->instance_call(), *targets,
with_checks, complete);
call->ReplaceWith(specialized, current_iterator());
}
@@ -1444,83 +1448,6 @@ 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;
-
- Function& target_function = Function::Handle(
- Z, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
- 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) {
@@ -1578,11 +1505,9 @@ void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
return;
}
- // Now we are done trying the inlining options that benefit from only having
- // 1 entry in the IC table.
- TryExpandClassesInICData(unary_checks);
+ CallTargets* targets = CallTargets::Create(Z, unary_checks);
- bool has_one_target = unary_checks.HasOneTarget();
+ bool has_one_target = targets->HasSingleTarget();
if (has_one_target) {
// Check if the single target is a polymorphic target, if it is,
@@ -1590,7 +1515,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(
- unary_checks) != Type::null();
+ *targets) != Type::null();
} else {
const bool polymorphic_target =
MethodRecognizer::PolymorphicTarget(target);
@@ -1603,7 +1528,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, unary_checks,
+ new (Z) PolymorphicInstanceCallInstr(instr, *targets,
/* call_with_checks = */ false,
/* complete = */ false);
instr->ReplaceWith(call, current_iterator());
@@ -1614,15 +1539,17 @@ void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
bool call_with_checks;
if (has_one_target && FLAG_polymorphic_with_deopt) {
// 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, unary_checks, call_with_checks,
- /* complete = */ false);
+ PolymorphicInstanceCallInstr* call =
+ new (Z) PolymorphicInstanceCallInstr(instr, *targets, 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