Chromium Code Reviews| Index: runtime/vm/flow_graph_compiler_x64.cc |
| diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc |
| index 8627315296a9e223ea58b9d97eb696c85962f711..09df6243a2ed3015154d8a33100c91494ed93c74 100644 |
| --- a/runtime/vm/flow_graph_compiler_x64.cc |
| +++ b/runtime/vm/flow_graph_compiler_x64.cc |
| @@ -1471,33 +1471,73 @@ void FlowGraphCompiler::ClobberDeadTempRegisters(LocationSummary* locs) { |
| void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
| - Register class_id_reg, |
| intptr_t argument_count, |
| const Array& argument_names, |
| - Label* deopt, |
| + Label* failed, |
| + Label* match_found, |
| intptr_t deopt_id, |
| intptr_t token_index, |
| LocationSummary* locs) { |
| ASSERT(is_optimizing()); |
| - ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0)); |
| - Label match_found; |
| - const intptr_t len = ic_data.NumberOfChecks(); |
| - GrowableArray<CidTarget> sorted(len); |
| - SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false); |
| - ASSERT(class_id_reg != R10); |
| - ASSERT(len > 0); // Why bother otherwise. |
| + |
| + __ Comment("EmitTestAndCall"); |
| const Array& arguments_descriptor = |
| Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| argument_names)); |
| StubCode* stub_code = isolate()->stub_code(); |
| - |
| + // Load receiver into RAX. |
| + __ movq(RAX, |
| + Address(RSP, (argument_count - 1) * kWordSize)); |
| __ LoadObject(R10, arguments_descriptor, PP); |
| - for (intptr_t i = 0; i < len; i++) { |
| - const bool is_last_check = (i == (len - 1)); |
| + |
| + const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
| + const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
| + |
| + ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
| + |
| + Label next_test; |
|
zra
2015/06/15 20:17:23
after_smi_test
|
| + __ testq(RAX, Immediate(kSmiTagMask)); |
| + if (kFirstCheckIsSmi) { |
| + // Jump if receiver is not Smi. |
| + if (kNumChecks == 1) { |
| + __ j(NOT_ZERO, failed); |
| + } else { |
| + __ j(NOT_ZERO, &next_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. |
| + GenerateDartCall(deopt_id, |
| + token_index, |
| + &stub_code->CallStaticFunctionLabel(), |
| + RawPcDescriptors::kOther, |
| + locs); |
| + const Function& function = Function::Handle(ic_data.GetTargetAt(0)); |
| + AddStaticCallTarget(function); |
| + __ Drop(argument_count, RCX); |
| + if (kNumChecks > 1) { |
| + __ jmp(match_found); |
| + } |
| + } else { |
| + // It is Smi, butSmi is not handled here. |
| + __ j(ZERO, failed); |
| + } |
| + __ Bind(&next_test); |
| + |
| + ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
| + GrowableArray<CidTarget> sorted(kNumChecks); |
| + SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); |
| + |
| + const intptr_t kSortedLen = sorted.length(); |
| + if (kSortedLen == 0) return; |
| + |
| + // Value is not Smi, |
| + __ LoadClassId(RDI, RAX); |
| + for (intptr_t i = 0; i < kSortedLen; i++) { |
| + const bool kIsLastCheck = (i == (kSortedLen - 1)); |
| Label next_test; |
| - __ cmpl(class_id_reg, Immediate(sorted[i].cid)); |
| - if (is_last_check) { |
| - __ j(NOT_EQUAL, deopt); |
| + __ cmpl(RDI, Immediate(sorted[i].cid)); |
| + if (kIsLastCheck) { |
| + __ j(NOT_EQUAL, failed); |
| } else { |
| __ j(NOT_EQUAL, &next_test); |
| } |
| @@ -1511,12 +1551,11 @@ void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
| const Function& function = *sorted[i].target; |
| AddStaticCallTarget(function); |
| __ Drop(argument_count, RCX); |
| - if (!is_last_check) { |
| - __ jmp(&match_found); |
| + if (!kIsLastCheck) { |
| + __ jmp(match_found); |
| } |
| __ Bind(&next_test); |
| } |
| - __ Bind(&match_found); |
| } |