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

Unified Diff: runtime/vm/flow_graph_compiler_ia32.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/flow_graph_compiler_ia32.cc
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 8052e0cc43c75632fe8c8447f1851321a2f514e2..8345aee7a80b5e1f9f2f6651c8b4842de6d96d48 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1183,16 +1183,14 @@ void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
void FlowGraphCompiler::EmitMegamorphicInstanceCall(
- const ICData& ic_data,
+ const String& name,
+ const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
TokenPosition token_pos,
LocationSummary* locs,
intptr_t try_index,
intptr_t slow_path_argument_count) {
- const String& name = String::Handle(zone(), ic_data.target_name());
- const Array& arguments_descriptor =
- Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
zone(),
@@ -1392,7 +1390,8 @@ void FlowGraphCompiler::ClobberDeadTempRegisters(LocationSummary* locs) {
#endif
-void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
+void FlowGraphCompiler::EmitTestAndCall(const PolymorphicTargets& targets,
+ const String& function_name,
intptr_t argument_count,
const Array& argument_names,
Label* failed,
@@ -1411,47 +1410,60 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
__ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
__ LoadObject(EDX, arguments_descriptor);
- const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
- const intptr_t num_checks = ic_data.NumberOfChecks();
-
- ASSERT(!ic_data.IsNull() && (num_checks > 0));
+ const int kNoCase = -1;
+ int smi_case = kNoCase;
+ int which_case_to_skip = kNoCase;
+
+ const int length = targets.length();
+ 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;
+ }
+ }
- Label after_smi_test;
__ testl(EAX, Immediate(kSmiTagMask));
- if (kFirstCheckIsSmi) {
+
+ if (smi_case != kNoCase) {
+ Label after_smi_test;
// Jump if receiver is not Smi.
- if (num_checks == 1) {
- __ j(NOT_ZERO, failed);
- } else {
- __ j(NOT_ZERO, &after_smi_test);
- }
+ __ j(NOT_ZERO, non_smi_length == 0 ? failed : &after_smi_test);
// 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;
GenerateDartCall(deopt_id, token_index,
*StubCode::CallStaticFunction_entry(),
RawPcDescriptors::kOther, locs);
- const Function& function =
- Function::ZoneHandle(zone(), ic_data.GetTargetAt(0));
AddStaticCallTarget(function);
+
__ Drop(argument_count);
- if (num_checks > 1) {
+ if (non_smi_length > 0) {
__ jmp(match_found);
}
+ __ Bind(&after_smi_test);
} else {
// Receiver is Smi, but Smi is not a valid class therefore fail.
- // (Smi class must be first in the list).
__ j(ZERO, failed);
}
- __ Bind(&after_smi_test);
- ASSERT(!ic_data.IsNull() && (num_checks > 0));
- GrowableArray<CidRangeTarget> sorted(num_checks);
- SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
+ ASSERT(length > 0);
- const intptr_t sorted_len = sorted.length();
- // If sorted_len 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.
- if (sorted_len == 0) return;
+ // 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.
+ if (non_smi_length == 0) return;
// Value is not Smi,
__ LoadClassId(EDI, EAX);
@@ -1459,51 +1471,54 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
bool add_megamorphic_call = false;
const int kMaxImmediateInInstruction = 127;
int bias =
- ComputeGoodBiasForCidComparison(sorted, kMaxImmediateInInstruction);
+ ComputeGoodBiasForCidComparison(targets, kMaxImmediateInInstruction);
if (bias != 0) __ addl(EDI, Immediate(-bias));
- for (intptr_t i = 0; i < sorted_len; i++) {
- const bool is_last_check = (i == (sorted_len - 1));
- int cid_start = sorted[i].cid_start;
- int cid_end = sorted[i].cid_end;
- int count = sorted[i].count;
- if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
+ 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);
+ int cid_start = targets[i].cid_start;
+ int cid_end = targets[i].cid_end;
+ 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.
+ // 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 HasSingleRecognizedCid.
add_megamorphic_call = true;
break;
}
- ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
Label next_test;
- if (!complete || !is_last_check) {
- Label* next_label = is_last_check ? failed : &next_test;
- if (cid_start == cid_end) {
- __ cmpl(EDI, Immediate(cid_start - bias));
- __ j(NOT_EQUAL, next_label);
- } else {
- __ addl(EDI, Immediate(bias - cid_start));
- bias = cid_start;
- __ cmpl(EDI, Immediate(cid_end - cid_start));
- __ j(ABOVE, next_label); // Unsigned higher.
- }
+ Label* next_label = is_last_check ? failed : &next_test;
+ if (cid_start == cid_end) {
+ __ cmpl(EDI, Immediate(cid_start - bias));
+ __ j(NOT_EQUAL, next_label);
+ } else {
+ __ addl(EDI, Immediate(bias - cid_start));
+ bias = cid_start;
+ __ cmpl(EDI, Immediate(cid_end - cid_start));
+ __ j(ABOVE, next_label); // Unsigned higher.
}
// 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 = *sorted[i].target;
+ const Function& function = *targets[i].target;
GenerateDartCall(deopt_id, token_index,
*StubCode::CallStaticFunction_entry(),
RawPcDescriptors::kOther, locs);
AddStaticCallTarget(function);
__ Drop(argument_count);
- if (!is_last_check) {
+ if (!is_last_check || add_megamorphic_call) {
__ jmp(match_found);
}
__ Bind(&next_test);
}
if (add_megamorphic_call) {
- int try_index = CatchClauseNode::kInvalidTryIndex;
- EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
- locs, try_index, argument_count);
+ const int try_index = CatchClauseNode::kInvalidTryIndex;
+ EmitMegamorphicInstanceCall(function_name, arguments_descriptor,
+ argument_count, deopt_id, token_index, locs,
+ try_index);
}
}

Powered by Google App Engine
This is Rietveld 408576698