Chromium Code Reviews| Index: runtime/vm/stub_code_x64.cc |
| diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc |
| index 1e81cfe29a3e55c756ae16dfd69d5284b312f496..a1dbf92cab2472ae5c01e6271e44cd34564f746e 100644 |
| --- a/runtime/vm/stub_code_x64.cc |
| +++ b/runtime/vm/stub_code_x64.cc |
| @@ -1537,8 +1537,21 @@ void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| // - Match not found -> jump to IC miss. |
| void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| intptr_t num_args) { |
| + ASSERT(num_args > 0); |
| +#if defined(DEBUG) |
| + { Label ok; |
| + // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| + // 'num_args_tested' is stored as an untagged int. |
| + __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
| + __ cmpq(RCX, Immediate(num_args)); |
| + __ j(EQUAL, &ok, Assembler::kNearJump); |
| + __ Stop("Incorrect stub for IC data"); |
| + __ Bind(&ok); |
| + } |
| +#endif // DEBUG |
| + |
| __ movq(RCX, FieldAddress(RBX, ICData::function_offset())); |
| - Label is_hot; |
| + Label is_hot; |
| if (FlowGraphCompiler::CanOptimize()) { |
| ASSERT(FLAG_optimization_counter_threshold > 1); |
| // The usage_counter is always less than FLAG_optimization_counter_threshold |
| @@ -1557,72 +1570,63 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| __ incq(FieldAddress(RCX, Function::usage_counter_offset())); |
| __ Bind(&is_hot); |
| - ASSERT(num_args > 0); |
| - // Get receiver (first read number of arguments from argument descriptor array |
| - // and then access the receiver from the stack). |
| - __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| - __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. |
| - |
| - Label get_class_id_as_smi, ic_miss; |
| - // RBX: IC data array. |
| - |
| -#if defined(DEBUG) |
| - { Label ok; |
| - // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| - // 'num_args_tested' is stored as an untagged int. |
| - __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
| - __ cmpq(RCX, Immediate(num_args)); |
| - __ j(EQUAL, &ok, Assembler::kNearJump); |
| - __ Stop("Incorrect stub for IC data"); |
| - __ Bind(&ok); |
| - } |
| -#endif // DEBUG |
| - |
| // Loop that checks if there is an IC data match. |
| + Label loop, update, test, found, get_class_id_as_smi; |
| // RBX: IC data object (preserved). |
| __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| // R12: ic_data_array with check entries: classes and target functions. |
| __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| // R12: points directly to the first ic data array element. |
| - const Immediate raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| - Label loop, found; |
| - if (num_args == 1) { |
| - __ call(&get_class_id_as_smi); |
| - // RAX: receiver's class id as Smi. |
| - __ Bind(&loop); |
| - __ movq(R13, Address(R12, 0)); // Get class if (Smi) to check. |
| - __ cmpq(RAX, R13); // Match? |
| - __ j(EQUAL, &found, Assembler::kNearJump); |
| - __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). |
| - __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| - __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| - } else { |
| - Label no_match; |
| - __ Bind(&loop); |
| - for (int i = 0; i < num_args; i++) { |
| + |
| + // Get the receiver's class ID (first read number of arguments from |
| + // argument descriptor array and then access the receiver from the stack). |
| + __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| + __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. |
| + __ call(&get_class_id_as_smi); |
| + // RAX: receiver's class ID as smi. |
| + __ movq(R13, Address(R12, 0)); // First class ID (Smi) to check. |
| + __ jmp(&test); |
| + |
| + __ Bind(&loop); |
| + for (int i = 0; i < num_args; i++) { |
| + if (i > 0) { |
| + // If not the first, load the next argument's class ID. |
| __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| __ movq(RAX, Address(RSP, RAX, TIMES_4, - i * kWordSize)); |
| __ call(&get_class_id_as_smi); |
| + // RAX: next argument class ID (smi). |
| __ movq(R13, Address(R12, i * kWordSize)); |
| - __ cmpq(RAX, R13); // Class id match? |
| - if (i < (num_args - 1)) { |
| - __ j(NOT_EQUAL, &no_match); |
| - } else { |
| - // Last check, all checks before matched. |
| - __ j(EQUAL, &found); |
| - } |
| + // R13: next class ID to check (smi). |
| + } |
| + __ cmpq(RAX, R13); // Class id match? |
| + if (i < (num_args - 1)) { |
| + __ j(NOT_EQUAL, &update); // Continue. |
| + } else { |
| + // Last check, all checks before matched. |
| + __ j(EQUAL, &found); // Break. |
| } |
| - __ Bind(&no_match); |
| - // Each test entry has (1 + num_args) array elements. |
| - __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. |
| - __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| - __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| } |
| + __ Bind(&update); |
| + // Reload receiver class ID. It has not been destroyed when num_args == 1. |
| + if (num_args > 1) { |
| + __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
|
Florian Schneider
2012/10/25 12:41:31
Could you keep FieldAddress(R10, Array::data_offse
|
| + __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); |
| + __ call(&get_class_id_as_smi); |
| + } |
| + // Each test entry has (1 + num_args) array elements. |
| + const intptr_t entry_size = (num_args + 1) * kWordSize; |
| + __ addq(R12, Immediate(entry_size)); // Next entry. |
| + __ movq(R13, Address(R12, 0)); // Next class ID. |
| + |
| + __ Bind(&test); |
| + __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| + __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| - __ Bind(&ic_miss); |
| - // Compute address of arguments (first read number of arguments from argument |
| - // descriptor array and then compute address on the stack). |
| + // IC miss. |
| + const Immediate raw_null = |
| + Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| + // Compute address of arguments (first read number of arguments from |
| + // argument descriptor array and then compute address on the stack). |
| __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
| AssemblerMacros::EnterStubFrame(assembler); |