Index: runtime/vm/code_patcher_ia32.cc |
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc |
index 08c7caf03b2ac44ea8bf3d027643369ed5393084..95d64e08e59c73a8175017f3b67af494df5627e5 100644 |
--- a/runtime/vm/code_patcher_ia32.cc |
+++ b/runtime/vm/code_patcher_ia32.cc |
@@ -44,6 +44,8 @@ class UnoptimizedCall : public ValueObject { |
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); |
} |
@@ -64,11 +66,33 @@ class UnoptimizedCall : public ValueObject { |
return start_ + 1 * kInstructionSize; |
} |
+ protected: |
uword start_; |
+ |
+ private: |
DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); |
}; |
+class NativeCall : public UnoptimizedCall { |
+ public: |
+ explicit NativeCall(uword return_address) : UnoptimizedCall(return_address) { |
+ } |
+ |
+ NativeFunction native_function() const { |
+ return *reinterpret_cast<NativeFunction*>(start_ + 1); |
+ } |
+ |
+ void set_native_function(NativeFunction func) const { |
+ WritableInstructionsScope writable(start_ + 1, sizeof(func)); |
+ *reinterpret_cast<NativeFunction*>(start_ + 1) = func; |
+ } |
+ |
+ private: |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NativeCall); |
+}; |
+ |
+ |
class InstanceCall : public UnoptimizedCall { |
public: |
explicit InstanceCall(uword return_address) |
@@ -210,6 +234,28 @@ RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( |
} |
+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); |
+} |
+ |
+ |
+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(); |
+} |
+ |
+ |
+ |
intptr_t CodePatcher::InstanceCallSizeInBytes() { |
return InstanceCall::kNumInstructions * InstanceCall::kInstructionSize; |
} |