Index: vm/stub_code_ia32.cc |
=================================================================== |
--- vm/stub_code_ia32.cc (revision 700) |
+++ vm/stub_code_ia32.cc (working copy) |
@@ -599,32 +599,6 @@ |
} |
-void StubCode::GenerateCallInstanceFunctionStub(Assembler* assembler) { |
- __ EnterFrame(0); |
- // Stack at this point: |
- // TOS + 0: Saved EBP of previous frame. <== EBP |
- // TOS + 1: Dart code return address |
- // TOS + 2: Last argument of caller. |
- // .... |
- // Total number of args is the first Smi in args descriptor array (EDX). |
- __ movl(EAX, FieldAddress(EDX, Array::data_offset())); // EAX is a Smi. |
- __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Load receiver. |
- __ pushl(EDX); // Preserve arguments descriptor array. |
- __ pushl(ECX); // Preserve ic-data array. |
- __ pushl(EAX); // Push receiver. |
- __ CallRuntimeFromStub(kResolvePatchInstanceCallRuntimeEntry); |
- __ popl(EAX); // Remove receiver pushed earlier. |
- // Pop preserved values |
- __ popl(ECX); // Restore ic-data array. |
- __ popl(EDX); // Restore arguments descriptor array. |
- __ LeaveFrame(); |
- __ popl(EAX); |
- // Reexecute call. |
- __ subl(EAX, Immediate(Assembler::kCallExternalLabelSize)); |
- __ jmp(EAX); |
-} |
- |
- |
void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
__ EnterFrame(0); |
// Stack at this point: |
@@ -1452,6 +1426,94 @@ |
__ ret(); |
} |
+ |
+// Use inline cache data array to invoke the target or continue in inline |
+// cache miss handler. Stub for 1-argument check (receiver class). |
+// ECX: Inline cache data array |
+// EDX: Arguments array |
+// TOS(0): return address |
+void StubCode::GenerateInlineCacheStub(Assembler* assembler) { |
+ Label ic_miss, is_smi, test_class; |
+ // Get receiver. |
+ __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
+ __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); |
+ |
+ __ CompareObject(EAX, Instance::ZoneHandle(Instance::null())); |
+ __ j(EQUAL, &ic_miss, Assembler::kNearJump); // Null receiver -> IC miss. |
+ |
+ // Test if Smi -> load Smi class for comparison. |
+ __ testl(EAX, Immediate(kSmiTagMask)); |
+ __ j(ZERO, &is_smi, Assembler::kNearJump); |
+ __ movl(EAX, FieldAddress(EAX, Object::class_offset())); |
+ __ jmp(&test_class); |
+ __ Bind(&is_smi); |
+ const Class& smi_class = |
+ Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); |
+ __ LoadObject(EAX, smi_class); |
+ |
+ __ Bind(&test_class); |
+ // EAX: receiver's class |
+ // ECX: IC data array. |
+ |
+#if defined(DEBUG) |
+ { Label ok; |
+ // Check that the IC data array has NumberOfArgumentsChecked() == 1. |
+ __ movl(EBX, FieldAddress(ECX, |
+ Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize)); |
+ const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); |
+ __ cmpl(EBX, value); |
+ __ j(EQUAL, &ok, Assembler::kNearJump); |
+ __ Stop("Incorrect stub for IC data"); |
+ __ Bind(&ok); |
+ } |
+#endif // DEBUG |
+ |
+ const Immediate raw_null = |
+ Immediate(reinterpret_cast<intptr_t>(Object::null())); |
+ __ leal(EBX, FieldAddress(ECX, |
+ Array::data_offset() + ICData::kChecksStartIndex * kWordSize)); |
+ Label loop, found, call_target_function; |
+ __ Bind(&loop); |
+ __ movl(EDI, Address(EBX, 0)); // Get class to check. |
+ __ cmpl(EAX, EDI); // Match? |
+ __ j(EQUAL, &found, Assembler::kNearJump); |
+ __ addl(EBX, Immediate(kWordSize * 2)); // next element (class + target). |
+ __ cmpl(EDI, raw_null); // Done? |
+ __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
+ |
+ __ Bind(&ic_miss); |
+ |
+ // Get receiver. |
+ __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
+ __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); |
+ __ EnterFrame(0); |
+ // Setup space for return value on stack by pushing smi 0. |
+ __ pushl(EDX); // Preserve arguments array. |
+ __ pushl(ECX); // Preserve IC data array |
+ __ pushl(Immediate(0)); |
+ __ pushl(EAX); // Push receiver. |
+ __ CallRuntimeFromStub(kInlineCacheMissHandlerRuntimeEntry); |
+ __ popl(EAX); // Remove receiver pushed earlier. |
+ __ popl(EAX); // Pop returned code object into EAX. |
+ __ popl(ECX); // Restore IC data array. |
+ __ popl(EDX); // Restore arguments array. |
+ __ LeaveFrame(); |
+ __ cmpl(EAX, raw_null); |
+ __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
+ // NoSuchMethod or closure. |
+ __ jmp(&StubCode::MegamorphicLookupLabel()); |
+ |
+ __ Bind(&found); |
+ __ movl(EAX, Address(EBX, kWordSize)); // Target function. |
+ |
+ __ Bind(&call_target_function); |
+ // EAX: Target function. |
+ __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
+ __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
+ __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
+ __ jmp(EAX); |
+} |
+ |
} // namespace dart |
#endif // defined TARGET_ARCH_IA32 |