Chromium Code Reviews| Index: runtime/vm/code_patcher_x64.cc |
| diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc |
| index 1f3f8e18aae25f6667fa7818dbef9e6f2b4d28f1..eacc6bec6a7d764a46f21aa8bb2ca04cc5314df0 100644 |
| --- a/runtime/vm/code_patcher_x64.cc |
| +++ b/runtime/vm/code_patcher_x64.cc |
| @@ -16,6 +16,19 @@ |
| namespace dart { |
| + |
| +static bool MatchesPattern(uword addr, int16_t* pattern, intptr_t size) { |
| + uint8_t* bytes = reinterpret_cast<uint8_t*>(addr); |
| + for (intptr_t i = 0; i < size; i++) { |
| + int16_t val = pattern[i]; |
| + if ((val >= 0) && (val != bytes[i])) { |
| + return false; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| + |
| // The expected pattern of a Dart unoptimized call (static and instance): |
| // 0: 49 8b 9f imm32 mov RBX, [PP + off] |
| // 7: 41 ff 97 imm32 call [PP + off] |
|
srdjan
2015/06/18 21:29:47
You may need to update this comment.
Florian Schneider
2015/06/29 14:50:24
Done.
|
| @@ -25,19 +38,21 @@ class UnoptimizedCall : public ValueObject { |
| UnoptimizedCall(uword return_address, const Code& code) |
| : start_(return_address - kCallPatternSize), |
| object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
| - ASSERT(IsValid(return_address)); |
| ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); |
| + ASSERT(IsValid()); |
| } |
| - static const int kCallPatternSize = 14; |
| - |
| - static bool IsValid(uword return_address) { |
| - uint8_t* code_bytes = |
| - reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); |
| - return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && |
| - (code_bytes[2] == 0x9F) && |
| - (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) && |
| - (code_bytes[9] == 0x97); |
| + static const int kCallPatternSize = 26; |
| + |
| + bool IsValid() const { |
| + static int16_t pattern[kCallPatternSize] = { |
| + 0x49, 0x8b, 0x9f, -1, -1, -1, -1, // movq RBX, [PP + offs] |
| + 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] |
| + 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs] |
| + 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs |
| + 0x41, 0xff, 0xd3 // callq TMP |
| + }; |
| + return MatchesPattern(start_, pattern, kCallPatternSize); |
| } |
| RawObject* ic_data() const { |
| @@ -45,14 +60,16 @@ class UnoptimizedCall : public ValueObject { |
| return object_pool_.ObjectAt(index); |
| } |
| - uword target() const { |
| + RawCode* target() const { |
| intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
| - return object_pool_.RawValueAt(index); |
| + Code& code = Code::Handle(); |
| + code ^= object_pool_.ObjectAt(index); |
| + return code.raw(); |
| } |
| - void set_target(uword target) const { |
| + void set_target(const Code& target) const { |
| intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
| - object_pool_.SetRawValueAt(index, target); |
| + object_pool_.SetObjectAt(index, target); |
| // No need to flush the instruction cache, since the code is not modified. |
| } |
| @@ -97,35 +114,43 @@ class UnoptimizedStaticCall : public UnoptimizedCall { |
| // The expected pattern of a call where the target is loaded from |
| // the object pool: |
| -// 0: 41 ff 97 imm32 call [PP + off] |
| -// 7: <- return address |
| +// 0: 4d 8b a7 imm32 movq CR, [PP + offs] |
| +// 7: 4d 8b 5c 24 07 movq TMP, [CR + insns_offs] |
| +// 12: 49 83 c3 1f addq TMP, entry_offs |
| +// 16: 41 ff d3 callq TMP |
| +// 19: <- return address |
| class PoolPointerCall : public ValueObject { |
| public: |
| explicit PoolPointerCall(uword return_address, const Code& code) |
| : start_(return_address - kCallPatternSize), |
| object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
| - ASSERT(IsValid(return_address)); |
| + ASSERT(IsValid()); |
| } |
| - static const int kCallPatternSize = 7; |
| + static const int kCallPatternSize = 19; |
| - static bool IsValid(uword return_address) { |
| - uint8_t* code_bytes = |
| - reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); |
| - return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && |
| - (code_bytes[2] == 0x97); |
| + bool IsValid() const { |
| + static int16_t pattern[kCallPatternSize] = { |
| + 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] |
| + 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs] |
| + 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs |
| + 0x41, 0xff, 0xd3 // callq TMP |
| + }; |
| + return MatchesPattern(start_, pattern, kCallPatternSize); |
| } |
| intptr_t pp_index() const { |
| return InstructionPattern::IndexFromPPLoad(start_ + 3); |
| } |
| - uword Target() const { |
| - return object_pool_.RawValueAt(pp_index()); |
| + RawCode* Target() const { |
| + Code& code = Code::Handle(); |
| + code ^= object_pool_.ObjectAt(pp_index()); |
| + return code.raw(); |
| } |
| - void SetTarget(uword target) const { |
| - object_pool_.SetRawValueAt(pp_index(), target); |
| + void SetTarget(const Code& target) const { |
| + object_pool_.SetObjectAt(pp_index(), target); |
| // No need to flush the instruction cache, since the code is not modified. |
| } |
| @@ -138,8 +163,8 @@ class PoolPointerCall : 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)); |
| PoolPointerCall call(return_address, code); |
| return call.Target(); |
| @@ -148,14 +173,14 @@ uword CodePatcher::GetStaticCallTargetAt(uword return_address, |
| void CodePatcher::PatchStaticCallAt(uword return_address, |
| const Code& code, |
| - uword new_target) { |
| + const Code& new_target) { |
| PatchPoolPointerCallAt(return_address, code, new_target); |
| } |
| void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
| const Code& code, |
| - uword new_target) { |
| + const Code& new_target) { |
| ASSERT(code.ContainsInstructionAt(return_address)); |
| PoolPointerCall call(return_address, code); |
| call.SetTarget(new_target); |
| @@ -164,16 +189,16 @@ void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
| void CodePatcher::PatchInstanceCallAt(uword return_address, |
| const Code& code, |
| - uword new_target) { |
| + const Code& new_target) { |
| ASSERT(code.ContainsInstructionAt(return_address)); |
| InstanceCall call(return_address, code); |
| call.set_target(new_target); |
| } |
| -uword CodePatcher::GetInstanceCallAt(uword return_address, |
| - const Code& code, |
| - ICData* ic_data) { |
| +RawCode* CodePatcher::GetInstanceCallAt(uword return_address, |
| + const Code& code, |
| + ICData* ic_data) { |
| ASSERT(code.ContainsInstructionAt(return_address)); |
| InstanceCall call(return_address, code); |
| if (ic_data != NULL) { |