| Index: runtime/vm/flow_graph_compiler_arm.cc
|
| diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
|
| index 0caab79002ee8b0c0c953989beb9c85412fc91e5..b9d000c27160ede70f072fcdcc6f07e923b6af91 100644
|
| --- a/runtime/vm/flow_graph_compiler_arm.cc
|
| +++ b/runtime/vm/flow_graph_compiler_arm.cc
|
| @@ -1247,33 +1247,10 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall(
|
| __ Comment("MegamorphicCall");
|
| // Load receiver into R0.
|
| __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
|
| - Label done;
|
| - if (ShouldInlineSmiStringHashCode(ic_data)) {
|
| - Label megamorphic_call;
|
| - __ Comment("Inlined get:hashCode for Smi and OneByteString");
|
| - __ tst(R0, Operand(kSmiTagMask));
|
| - __ b(&done, EQ); // Is Smi (result is receiver).
|
| -
|
| - // Use R9 (cache for megamorphic call) as scratch.
|
| - __ CompareClassId(R0, kOneByteStringCid, R9);
|
| - __ b(&megamorphic_call, NE);
|
| -
|
| - __ mov(R9, Operand(R0)); // Preserve receiver in R9.
|
| - __ ldr(R0, FieldAddress(R0, String::hash_offset()));
|
| - ASSERT(Smi::New(0) == 0);
|
| - __ cmp(R0, Operand(0));
|
| -
|
| - __ b(&done, NE); // Return if already computed.
|
| - __ mov(R0, Operand(R9)); // Restore receiver in R0.
|
| -
|
| - __ Bind(&megamorphic_call);
|
| - __ Comment("Slow case: megamorphic call");
|
| - }
|
| __ LoadObject(R9, cache);
|
| __ ldr(LR, Address(THR, Thread::megamorphic_call_checked_entry_offset()));
|
| __ blx(LR);
|
|
|
| - __ Bind(&done);
|
| RecordSafepoint(locs, slow_path_argument_count);
|
| const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
|
| if (FLAG_precompiled_mode) {
|
| @@ -1526,7 +1503,8 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
| intptr_t deopt_id,
|
| TokenPosition token_index,
|
| LocationSummary* locs,
|
| - bool complete) {
|
| + bool complete,
|
| + intptr_t total_ic_calls) {
|
| ASSERT(is_optimizing());
|
| __ Comment("EmitTestAndCall");
|
| const Array& arguments_descriptor = Array::ZoneHandle(
|
| @@ -1572,31 +1550,46 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
| __ Bind(&after_smi_test);
|
|
|
| ASSERT(!ic_data.IsNull() && (num_checks > 0));
|
| - GrowableArray<CidTarget> sorted(num_checks);
|
| + GrowableArray<CidRangeTarget> sorted(num_checks);
|
| SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
|
|
|
| - // Value is not Smi,
|
| - const intptr_t kSortedLen = sorted.length();
|
| - // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
|
| + 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 (kSortedLen == 0) return;
|
| + if (sorted_len == 0) return;
|
|
|
| + // Value is not Smi,
|
| __ LoadClassId(R2, R0);
|
| - for (intptr_t i = 0; i < kSortedLen; i++) {
|
| - const bool kIsLastCheck = (i == (kSortedLen - 1));
|
| - ASSERT(sorted[i].cid != kSmiCid);
|
| +
|
| + bool add_megamorphic_call = false;
|
| + const int kMaxImmediateInInstruction = 256;
|
| + int bias =
|
| + ComputeGoodBiasForCidComparison(sorted, kMaxImmediateInInstruction);
|
| + if (bias != 0) __ AddImmediate(R2, R2, -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)) {
|
| + // This case is hit too rarely to be worth writing class-id checks inline
|
| + // for.
|
| + add_megamorphic_call = true;
|
| + break;
|
| + }
|
| + ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
|
| Label next_test;
|
| - if (!complete) {
|
| - __ CompareImmediate(R2, sorted[i].cid);
|
| - if (kIsLastCheck) {
|
| - __ b(failed, NE);
|
| + if (!complete || !is_last_check) {
|
| + Label* next_label = is_last_check ? failed : &next_test;
|
| + if (cid_start == cid_end) {
|
| + __ CompareImmediate(R2, cid_start - bias);
|
| + __ b(next_label, NE);
|
| } else {
|
| - __ b(&next_test, NE);
|
| - }
|
| - } else {
|
| - if (!kIsLastCheck) {
|
| - __ CompareImmediate(R2, sorted[i].cid);
|
| - __ b(&next_test, NE);
|
| + __ AddImmediate(R2, R2, bias - cid_start);
|
| + bias = cid_start;
|
| + __ CompareImmediate(R2, cid_end - cid_start);
|
| + __ b(next_label, HI); // Unsigned higher.
|
| }
|
| }
|
| // Do not use the code from the function, but let the code be patched so
|
| @@ -1606,11 +1599,16 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
|
| *StubCode::CallStaticFunction_entry(),
|
| RawPcDescriptors::kOther, locs, function);
|
| __ Drop(argument_count);
|
| - if (!kIsLastCheck) {
|
| + if (!is_last_check) {
|
| __ b(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);
|
| + }
|
| }
|
|
|
|
|
|
|