| Index: runtime/vm/code_patcher_ia32.cc | 
| diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc | 
| index 95d64e08e59c73a8175017f3b67af494df5627e5..e1f54839c44a723a23eb81fb46670aded5a5d961 100644 | 
| --- a/runtime/vm/code_patcher_ia32.cc | 
| +++ b/runtime/vm/code_patcher_ia32.cc | 
| @@ -18,52 +18,38 @@ namespace dart { | 
|  | 
| // The expected pattern of a Dart unoptimized call (static and instance): | 
| //  mov ECX, ic-data | 
| +//  mov EDI, target-code-object | 
| //  call target_address (stub) | 
| //  <- return address | 
| class UnoptimizedCall : public ValueObject { | 
| public: | 
| explicit UnoptimizedCall(uword return_address) | 
| -      : start_(return_address - (kNumInstructions * kInstructionSize)) { | 
| -    ASSERT(IsValid(return_address)); | 
| -    ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize); | 
| -  } | 
| - | 
| -  static bool IsValid(uword return_address) { | 
| -    uint8_t* code_bytes = | 
| -        reinterpret_cast<uint8_t*>( | 
| -            return_address - (kNumInstructions * kInstructionSize)); | 
| -    return (code_bytes[0] == 0xB9) && | 
| -           (code_bytes[1 * kInstructionSize] == 0xE8); | 
| -  } | 
| - | 
| -  uword target() const { | 
| -    const uword offset = *reinterpret_cast<uword*>(call_address() + 1); | 
| -    return return_address() + offset; | 
| -  } | 
| - | 
| -  void set_target(uword target) const { | 
| -    uword* target_addr = reinterpret_cast<uword*>(call_address() + 1); | 
| -    uword offset = target - return_address(); | 
| -    WritableInstructionsScope writable(reinterpret_cast<uword>(target_addr), | 
| -                                       sizeof(offset)); | 
| -    *target_addr = offset; | 
| -    CPU::FlushICache(call_address(), kInstructionSize); | 
| +      : start_(return_address - kPatternSize) { | 
| +    ASSERT(IsValid()); | 
| } | 
|  | 
| RawObject* ic_data() const { | 
| return *reinterpret_cast<RawObject**>(start_ + 1); | 
| } | 
|  | 
| -  static const int kNumInstructions = 2; | 
| -  static const int kInstructionSize = 5;  // All instructions have same length. | 
| +  static const int kMovInstructionSize = 5; | 
| +  static const int kCallInstructionSize = 3; | 
| +  static const int kPatternSize = | 
| +      2 * kMovInstructionSize + kCallInstructionSize; | 
|  | 
| private: | 
| +  bool IsValid() { | 
| +    uint8_t* code_bytes = reinterpret_cast<uint8_t*>(start_); | 
| +    return (code_bytes[0] == 0xB9) && | 
| +           (code_bytes[2 * kMovInstructionSize] == 0xFF); | 
| +  } | 
| + | 
| uword return_address() const { | 
| -    return start_ + kNumInstructions * kInstructionSize; | 
| +    return start_ + kPatternSize; | 
| } | 
|  | 
| uword call_address() const { | 
| -    return start_ + 1 * kInstructionSize; | 
| +    return start_ + 2 * kMovInstructionSize; | 
| } | 
|  | 
| protected: | 
| @@ -127,45 +113,43 @@ class UnoptimizedStaticCall : public UnoptimizedCall { | 
|  | 
| // The expected pattern of a dart static call: | 
| //  mov EDX, arguments_descriptor_array (optional in polymorphic calls) | 
| -//  call target_address | 
| +//  mov EDI, Immediate(code_object) | 
| +//  call [EDI + entry_point_offset] | 
| //  <- return address | 
| class StaticCall : public ValueObject { | 
| public: | 
| explicit StaticCall(uword return_address) | 
| -      : start_(return_address - (kNumInstructions * kInstructionSize)) { | 
| -    ASSERT(IsValid(return_address)); | 
| -    ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize); | 
| +      : start_(return_address - (kMovInstructionSize + kCallInstructionSize)) { | 
| +    ASSERT(IsValid()); | 
| } | 
|  | 
| -  static bool IsValid(uword return_address) { | 
| -    uint8_t* code_bytes = | 
| -        reinterpret_cast<uint8_t*>( | 
| -            return_address - (kNumInstructions * kInstructionSize)); | 
| -    return (code_bytes[0] == 0xE8); | 
| +  bool IsValid() { | 
| +    uint8_t* code_bytes = reinterpret_cast<uint8_t*>(start_); | 
| +    return (code_bytes[0] == 0xBF) && (code_bytes[5] == 0xFF); | 
| } | 
|  | 
| -  uword target() const { | 
| -    const uword offset = *reinterpret_cast<uword*>(call_address() + 1); | 
| -    return return_address() + offset; | 
| +  RawCode* target() const { | 
| +    const uword imm = *reinterpret_cast<uword*>(start_ + 1); | 
| +    return reinterpret_cast<RawCode*>(imm); | 
| } | 
|  | 
| -  void set_target(uword target) const { | 
| -    uword* target_addr = reinterpret_cast<uword*>(call_address() + 1); | 
| -    uword offset = target - return_address(); | 
| -    *target_addr = offset; | 
| -    CPU::FlushICache(call_address(), kInstructionSize); | 
| +  void set_target(const Code& target) const { | 
| +    uword* target_addr = reinterpret_cast<uword*>(start_ + 1); | 
| +    uword imm = reinterpret_cast<uword>(target.raw()); | 
| +    *target_addr = imm; | 
| +    CPU::FlushICache(start_ + 1, sizeof(imm)); | 
| } | 
|  | 
| -  static const int kNumInstructions = 1; | 
| -  static const int kInstructionSize = 5;  // All instructions have same length. | 
| +  static const int kMovInstructionSize = 5; | 
| +  static const int kCallInstructionSize = 3; | 
|  | 
| private: | 
| uword return_address() const { | 
| -    return start_ + kNumInstructions * kInstructionSize; | 
| +    return start_ + kMovInstructionSize +  kCallInstructionSize; | 
| } | 
|  | 
| uword call_address() const { | 
| -    return start_; | 
| +    return start_ + kMovInstructionSize; | 
| } | 
|  | 
| uword start_; | 
| @@ -174,8 +158,8 @@ class StaticCall : public ValueObject { | 
| }; | 
|  | 
|  | 
| -uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 
| -                                         const Code& code) { | 
| +RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, | 
| +                                            const Code& code) { | 
| ASSERT(code.ContainsInstructionAt(return_address)); | 
| StaticCall call(return_address); | 
| return call.target(); | 
| @@ -184,23 +168,16 @@ uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 
|  | 
| void CodePatcher::PatchStaticCallAt(uword return_address, | 
| const Code& code, | 
| -                                    uword new_target) { | 
| +                                    const Code& new_target) { | 
| +  const Instructions& instrs = Instructions::Handle(code.instructions()); | 
| +  WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); | 
| ASSERT(code.ContainsInstructionAt(return_address)); | 
| StaticCall call(return_address); | 
| call.set_target(new_target); | 
| } | 
|  | 
|  | 
| -void CodePatcher::PatchInstanceCallAt(uword return_address, | 
| -                                      const Code& code, | 
| -                                      uword new_target) { | 
| -  ASSERT(code.ContainsInstructionAt(return_address)); | 
| -  InstanceCall call(return_address); | 
| -  call.set_target(new_target); | 
| -} | 
| - | 
| - | 
| -void CodePatcher::InsertCallAt(uword start, uword target) { | 
| +void CodePatcher::InsertDeoptimizationCallAt(uword start, uword target) { | 
| // The inserted call should not overlap the lazy deopt jump code. | 
| ASSERT(start + CallPattern::pattern_length_in_bytes() <= target); | 
| *reinterpret_cast<uint8_t*>(start) = 0xE8; | 
| @@ -210,14 +187,14 @@ void CodePatcher::InsertCallAt(uword start, uword target) { | 
| } | 
|  | 
|  | 
| -uword CodePatcher::GetInstanceCallAt( | 
| +RawCode* CodePatcher::GetInstanceCallAt( | 
| uword return_address, const Code& code, ICData* ic_data) { | 
| ASSERT(code.ContainsInstructionAt(return_address)); | 
| InstanceCall call(return_address); | 
| if (ic_data != NULL) { | 
| *ic_data ^= call.ic_data(); | 
| } | 
| -  return call.target(); | 
| +  return Code::null(); | 
| } | 
|  | 
|  | 
| @@ -238,26 +215,21 @@ void CodePatcher::PatchNativeCallAt(uword return_address, | 
| const Code& code, | 
| NativeFunction target, | 
| const Code& trampoline) { | 
| -  ASSERT(code.ContainsInstructionAt(return_address)); | 
| -  NativeCall call(return_address); | 
| -  call.set_target(trampoline.EntryPoint()); | 
| -  call.set_native_function(target); | 
| +  UNREACHABLE(); | 
| } | 
|  | 
|  | 
| -uword CodePatcher::GetNativeCallAt(uword return_address, | 
| -                                   const Code& code, | 
| -                                   NativeFunction* target) { | 
| -  ASSERT(code.ContainsInstructionAt(return_address)); | 
| -  NativeCall call(return_address); | 
| -  *target = call.native_function(); | 
| -  return call.target(); | 
| +RawCode* CodePatcher::GetNativeCallAt(uword return_address, | 
| +                                      const Code& code, | 
| +                                      NativeFunction* target) { | 
| +  UNREACHABLE(); | 
| +  return NULL; | 
| } | 
|  | 
|  | 
|  | 
| intptr_t CodePatcher::InstanceCallSizeInBytes() { | 
| -  return InstanceCall::kNumInstructions * InstanceCall::kInstructionSize; | 
| +  return InstanceCall::kPatternSize; | 
| } | 
|  | 
|  | 
|  |