| 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
 | 
| 
 |