Index: runtime/vm/code_patcher_ia32.cc |
=================================================================== |
--- runtime/vm/code_patcher_ia32.cc (revision 15101) |
+++ runtime/vm/code_patcher_ia32.cc (working copy) |
@@ -14,7 +14,7 @@ |
namespace dart { |
-// The pattern of a Dart call is: |
+// The pattern of a Dart instance call is: |
// 1: mov ECX, immediate 1 |
// 2: mov EDX, immediate 2 |
// 3: call target_address |
@@ -97,45 +97,74 @@ |
}; |
-// The expected pattern of a dart static call: |
-// mov ECX, function_object |
+// The expected pattern of a dart instance call: |
+// mov ECX, ic-data |
// mov EDX, argument_descriptor_array |
// call target_address |
// <- return address |
-class StaticCall : public DartCallPattern { |
+class InstanceCall : public DartCallPattern { |
public: |
- explicit StaticCall(uword return_address) |
+ explicit InstanceCall(uword return_address) |
: DartCallPattern(return_address) {} |
- RawFunction* function() const { |
- Function& f = Function::Handle(); |
- f ^= reinterpret_cast<RawObject*>(immediate_one()); |
- return f.raw(); |
+ RawICData* ic_data() const { |
+ ICData& ic_data = ICData::Handle(); |
+ ic_data ^= reinterpret_cast<RawObject*>(immediate_one()); |
+ return ic_data.raw(); |
} |
private: |
- DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); |
}; |
-// The expected pattern of a dart instance call: |
-// mov ECX, ic-data |
+// The expected pattern of a dart static call: |
// mov EDX, argument_descriptor_array |
// call target_address |
// <- return address |
-class InstanceCall : public DartCallPattern { |
+class StaticCall : public ValueObject { |
public: |
- explicit InstanceCall(uword return_address) |
- : DartCallPattern(return_address) {} |
+ explicit StaticCall(uword return_address) |
+ : start_(return_address - (kNumInstructions * kInstructionSize)) { |
+ ASSERT(IsValid(return_address)); |
+ ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize); |
+ } |
- RawICData* ic_data() const { |
- ICData& ic_data = ICData::Handle(); |
- ic_data ^= reinterpret_cast<RawObject*>(immediate_one()); |
- return ic_data.raw(); |
+ static bool IsValid(uword return_address) { |
+ uint8_t* code_bytes = |
+ reinterpret_cast<uint8_t*>( |
+ return_address - (kNumInstructions * kInstructionSize)); |
+ return (code_bytes[0] == 0xBA) && |
+ (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(); |
+ *target_addr = offset; |
+ CPU::FlushICache(call_address(), kInstructionSize); |
+ } |
+ |
+ static const int kNumInstructions = 2; |
+ static const int kInstructionSize = 5; // All instructions have same length. |
+ |
private: |
- DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); |
+ uword return_address() const { |
+ return start_ + kNumInstructions * kInstructionSize; |
+ } |
+ |
+ uword call_address() const { |
+ return start_ + 1 * kInstructionSize; |
+ } |
+ |
+ uword start_; |
+ |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); |
}; |