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

Unified Diff: runtime/vm/flow_graph_compiler.cc

Issue 2833413002: Revert "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/flow_graph_compiler.h ('k') | runtime/vm/flow_graph_compiler_arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_compiler.cc
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 4c56e30828ca2921ddf92a9ab78e479b49001cbd..866cab4de2588fd832ce9d9a245ef424aee606ec 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -23,7 +23,6 @@
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/raw_object.h"
-#include "vm/resolver.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
@@ -1170,12 +1169,8 @@ void FlowGraphCompiler::GenerateInstanceCall(intptr_t deopt_id,
}
if (is_optimizing()) {
- String& name = String::Handle(ic_data_in.target_name());
- Array& arguments_descriptor =
- Array::Handle(ic_data_in.arguments_descriptor());
- EmitMegamorphicInstanceCall(name, arguments_descriptor, argument_count,
- deopt_id, token_pos, locs,
- CatchClauseNode::kInvalidTryIndex);
+ EmitMegamorphicInstanceCall(ic_data_in, argument_count, deopt_id, token_pos,
+ locs, CatchClauseNode::kInvalidTryIndex);
return;
}
@@ -1792,70 +1787,84 @@ void FlowGraphCompiler::EndCodeSourceRange(TokenPosition token_pos) {
}
-const CallTargets* FlowGraphCompiler::ResolveCallTargetsForReceiverCid(
- intptr_t cid,
- const String& selector,
- const Array& args_desc_array) {
+const ICData& FlowGraphCompiler::TrySpecializeICDataByReceiverCid(
+ const ICData& ic_data,
+ intptr_t cid) {
Zone* zone = Thread::Current()->zone();
-
- ArgumentsDescriptor args_desc(args_desc_array);
-
- Function& fn = Function::ZoneHandle(zone);
- if (!LookupMethodFor(cid, selector, args_desc, &fn)) return NULL;
-
- CallTargets* targets = new (zone) CallTargets();
- targets->Add(CidRangeTarget(cid, cid, &fn, /* count = */ 1));
-
- return targets;
-}
-
-
-bool FlowGraphCompiler::LookupMethodFor(int class_id,
- const String& name,
- const ArgumentsDescriptor& args_desc,
- Function* fn_return) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- Zone* zone = thread->zone();
- if (class_id < 0) return false;
- if (class_id >= isolate->class_table()->NumCids()) return false;
-
- RawClass* raw_class = isolate->class_table()->At(class_id);
- if (raw_class == NULL) return false;
- Class& cls = Class::Handle(zone, raw_class);
- if (cls.IsNull()) return false;
- if (!cls.is_finalized()) return false;
- if (Array::Handle(cls.functions()).IsNull()) return false;
-
- const bool allow_add = false;
- Function& target_function =
- Function::Handle(zone, Resolver::ResolveDynamicForReceiverClass(
- cls, name, args_desc, allow_add));
- if (target_function.IsNull()) return false;
- *fn_return ^= target_function.raw();
- return true;
+ if (ic_data.NumArgsTested() != 1) return ic_data;
+
+ if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) {
+ return ic_data; // Nothing to do
+ }
+
+ intptr_t count = 1;
+ const Function& function =
+ Function::Handle(zone, ic_data.GetTargetForReceiverClassId(cid, &count));
+ // TODO(fschneider): Try looking up the function on the class if it is
+ // not found in the ICData.
+ if (!function.IsNull()) {
+ const ICData& new_ic_data = ICData::ZoneHandle(
+ zone, ICData::New(Function::Handle(zone, ic_data.Owner()),
+ String::Handle(zone, ic_data.target_name()),
+ Object::empty_array(), // Dummy argument descriptor.
+ ic_data.deopt_id(), ic_data.NumArgsTested(), false));
+ new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
+ new_ic_data.AddReceiverCheck(cid, function, count);
+ return new_ic_data;
+ }
+
+ return ic_data;
+}
+
+
+intptr_t FlowGraphCompiler::ComputeGoodBiasForCidComparison(
+ const GrowableArray<CidRangeTarget>& sorted,
+ intptr_t max_immediate) {
+ // Sometimes a bias can be useful so we can emit more compact compare
+ // instructions.
+ intptr_t min_cid = 1000000;
+ intptr_t max_cid = -1;
+
+ const intptr_t sorted_len = sorted.length();
+
+ for (intptr_t i = 0; i < sorted_len + 1; i++) {
+ bool done = (i == sorted_len);
+ intptr_t start = done ? 0 : sorted[i].cid_start;
+ intptr_t end = done ? 0 : sorted[i].cid_end;
+ bool is_range = start != end;
+ bool spread_too_big = start - min_cid > max_immediate;
+ if (done || is_range || spread_too_big) {
+ if (i >= 2 && max_cid - min_cid <= max_immediate &&
+ max_cid > max_immediate) {
+ return min_cid;
+ } else {
+ return 0;
+ }
+ }
+ min_cid = Utils::Minimum(min_cid, start);
+ max_cid = Utils::Maximum(max_cid, end);
+ }
+ UNREACHABLE();
+ return 0;
}
#if !defined(TARGET_ARCH_DBC)
// DBC emits calls very differently from other architectures due to its
// interpreted nature.
-void FlowGraphCompiler::EmitPolymorphicInstanceCall(
- const CallTargets& targets,
- const InstanceCallInstr& original_call,
- intptr_t argument_count,
- const Array& argument_names,
- intptr_t deopt_id,
- TokenPosition token_pos,
- LocationSummary* locs,
- bool complete,
- intptr_t total_ic_calls) {
+void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data,
+ intptr_t argument_count,
+ const Array& argument_names,
+ intptr_t deopt_id,
+ TokenPosition token_pos,
+ LocationSummary* locs,
+ bool complete,
+ intptr_t total_ic_calls) {
if (FLAG_polymorphic_with_deopt) {
Label* deopt =
AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail);
Label ok;
- EmitTestAndCall(targets, original_call.function_name(), argument_count,
- argument_names,
+ EmitTestAndCall(ic_data, argument_count, argument_names,
deopt, // No cid match.
&ok, // Found cid.
deopt_id, token_pos, locs, complete, total_ic_calls);
@@ -1863,142 +1872,17 @@ void FlowGraphCompiler::EmitPolymorphicInstanceCall(
} else {
if (complete) {
Label ok;
- EmitTestAndCall(targets, original_call.function_name(), argument_count,
- argument_names,
+ EmitTestAndCall(ic_data, argument_count, argument_names,
NULL, // No cid match.
&ok, // Found cid.
deopt_id, token_pos, locs, true, total_ic_calls);
assembler()->Bind(&ok);
} else {
- const ICData& unary_checks = ICData::ZoneHandle(
- zone(), original_call.ic_data()->AsUnaryClassChecks());
- EmitSwitchableInstanceCall(unary_checks, argument_count, deopt_id,
- token_pos, locs);
- }
- }
-}
-
-
-#define __ assembler()->
-void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
- const String& function_name,
- intptr_t argument_count,
- const Array& argument_names,
- Label* failed,
- Label* match_found,
- intptr_t deopt_id,
- TokenPosition token_index,
- LocationSummary* locs,
- bool complete,
- intptr_t total_ic_calls) {
- ASSERT(is_optimizing());
-
- const Array& arguments_descriptor = Array::ZoneHandle(
- zone(), ArgumentsDescriptor::New(argument_count, argument_names));
-
- EmitTestAndCallLoadReceiver(argument_count, arguments_descriptor);
-
- static const int kNoCase = -1;
- int smi_case = kNoCase;
- int which_case_to_skip = kNoCase;
-
- const int length = targets.length();
- ASSERT(length > 0);
- int non_smi_length = length;
-
- // Find out if one of the classes in one of the cases is the Smi class. We
- // will be handling that specially.
- for (int i = 0; i < length; i++) {
- const intptr_t start = targets[i].cid_start;
- if (start > kSmiCid) continue;
- const intptr_t end = targets[i].cid_end;
- if (end >= kSmiCid) {
- smi_case = i;
- if (start == kSmiCid && end == kSmiCid) {
- // If this case has only the Smi class then we won't need to emit it at
- // all later.
- which_case_to_skip = i;
- non_smi_length--;
- }
- break;
- }
- }
-
- if (smi_case != kNoCase) {
- Label after_smi_test;
- EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
- false); // Jump if receiver is not Smi.
-
- // Do not use the code from the function, but let the code be patched so
- // that we can record the outgoing edges to other code.
- const Function& function = *targets[smi_case].target;
- GenerateStaticDartCall(deopt_id, token_index,
- *StubCode::CallStaticFunction_entry(),
- RawPcDescriptors::kOther, locs, function);
- __ Drop(argument_count);
- if (match_found != NULL) {
- __ Jump(match_found);
- }
- __ Bind(&after_smi_test);
- } else {
- if (!complete) {
- // Smi is not a valid class.
- EmitTestAndCallSmiBranch(failed,
- true); // Jump to failed if it's a Smi.
- }
- }
-
- if (non_smi_length == 0) {
- // If non_smi_length is 0 then only a Smi check was needed; the Smi check
- // above will fail if there was only one check and receiver is not Smi.
- return;
- }
-
- bool add_megamorphic_call = false;
- int bias = 0;
-
- // Value is not Smi.
- EmitTestAndCallLoadCid();
-
- int last_check = which_case_to_skip == length - 1 ? length - 2 : length - 1;
-
- for (intptr_t i = 0; i < length; i++) {
- if (i == which_case_to_skip) continue;
- const bool is_last_check = (i == last_check);
- const int count = targets[i].count;
- if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
- // This case is hit too rarely to be worth writing class-id checks inline
- // for. Note that we can't do this for calls with only one target because
- // the type propagator may have made use of that and expects a deopt if
- // a new class is seen at this calls site. See IsMonomorphic.
- add_megamorphic_call = true;
- break;
- }
- Label next_test;
- if (!complete || !is_last_check) {
- bias = EmitTestAndCallCheckCid(is_last_check ? failed : &next_test,
- targets[i], bias);
+ EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos,
+ locs);
}
- // Do not use the code from the function, but let the code be patched so
- // that we can record the outgoing edges to other code.
- const Function& function = *targets[i].target;
- GenerateStaticDartCall(deopt_id, token_index,
- *StubCode::CallStaticFunction_entry(),
- RawPcDescriptors::kOther, locs, function);
- __ Drop(argument_count);
- if (!is_last_check || add_megamorphic_call) {
- __ Jump(match_found);
- }
- __ Bind(&next_test);
- }
- if (add_megamorphic_call) {
- int try_index = CatchClauseNode::kInvalidTryIndex;
- EmitMegamorphicInstanceCall(function_name, arguments_descriptor,
- argument_count, deopt_id, token_index, locs,
- try_index);
}
}
-#undef __
#endif
#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
« no previous file with comments | « runtime/vm/flow_graph_compiler.h ('k') | runtime/vm/flow_graph_compiler_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698