Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/instructions.h" | 13 #include "vm/instructions.h" |
| 14 #include "vm/object.h" | 14 #include "vm/object.h" |
| 15 #include "vm/raw_object.h" | 15 #include "vm/raw_object.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 | |
| 20 static bool MatchesPattern(uword addr, int16_t* pattern, intptr_t size) { | |
| 21 uint8_t* bytes = reinterpret_cast<uint8_t*>(addr); | |
| 22 for (intptr_t i = 0; i < size; i++) { | |
| 23 int16_t val = pattern[i]; | |
| 24 if ((val >= 0) && (val != bytes[i])) { | |
| 25 return false; | |
| 26 } | |
| 27 } | |
| 28 return true; | |
| 29 } | |
| 30 | |
| 31 | |
| 19 // The expected pattern of a Dart unoptimized call (static and instance): | 32 // The expected pattern of a Dart unoptimized call (static and instance): |
| 20 // 0: 49 8b 9f imm32 mov RBX, [PP + off] | 33 // 0: 49 8b 9f imm32 mov RBX, [PP + off] |
| 21 // 7: 41 ff 97 imm32 call [PP + off] | 34 // 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.
| |
| 22 // 14 <- return address | 35 // 14 <- return address |
| 23 class UnoptimizedCall : public ValueObject { | 36 class UnoptimizedCall : public ValueObject { |
| 24 public: | 37 public: |
| 25 UnoptimizedCall(uword return_address, const Code& code) | 38 UnoptimizedCall(uword return_address, const Code& code) |
| 26 : start_(return_address - kCallPatternSize), | 39 : start_(return_address - kCallPatternSize), |
| 27 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { | 40 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
| 28 ASSERT(IsValid(return_address)); | |
| 29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); | 41 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); |
| 42 ASSERT(IsValid()); | |
| 30 } | 43 } |
| 31 | 44 |
| 32 static const int kCallPatternSize = 14; | 45 static const int kCallPatternSize = 26; |
| 33 | 46 |
| 34 static bool IsValid(uword return_address) { | 47 bool IsValid() const { |
| 35 uint8_t* code_bytes = | 48 static int16_t pattern[kCallPatternSize] = { |
| 36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 49 0x49, 0x8b, 0x9f, -1, -1, -1, -1, // movq RBX, [PP + offs] |
| 37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && | 50 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] |
| 38 (code_bytes[2] == 0x9F) && | 51 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs] |
| 39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) && | 52 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs |
| 40 (code_bytes[9] == 0x97); | 53 0x41, 0xff, 0xd3 // callq TMP |
| 54 }; | |
| 55 return MatchesPattern(start_, pattern, kCallPatternSize); | |
| 41 } | 56 } |
| 42 | 57 |
| 43 RawObject* ic_data() const { | 58 RawObject* ic_data() const { |
| 44 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); | 59 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); |
| 45 return object_pool_.ObjectAt(index); | 60 return object_pool_.ObjectAt(index); |
| 46 } | 61 } |
| 47 | 62 |
| 48 uword target() const { | 63 RawCode* target() const { |
| 49 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); | 64 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
| 50 return object_pool_.RawValueAt(index); | 65 Code& code = Code::Handle(); |
| 66 code ^= object_pool_.ObjectAt(index); | |
| 67 return code.raw(); | |
| 51 } | 68 } |
| 52 | 69 |
| 53 void set_target(uword target) const { | 70 void set_target(const Code& target) const { |
| 54 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); | 71 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
| 55 object_pool_.SetRawValueAt(index, target); | 72 object_pool_.SetObjectAt(index, target); |
| 56 // No need to flush the instruction cache, since the code is not modified. | 73 // No need to flush the instruction cache, since the code is not modified. |
| 57 } | 74 } |
| 58 | 75 |
| 59 private: | 76 private: |
| 60 uword start_; | 77 uword start_; |
| 61 const ObjectPool& object_pool_; | 78 const ObjectPool& object_pool_; |
| 62 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); | 79 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); |
| 63 }; | 80 }; |
| 64 | 81 |
| 65 | 82 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 90 #endif // DEBUG | 107 #endif // DEBUG |
| 91 } | 108 } |
| 92 | 109 |
| 93 private: | 110 private: |
| 94 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); | 111 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); |
| 95 }; | 112 }; |
| 96 | 113 |
| 97 | 114 |
| 98 // The expected pattern of a call where the target is loaded from | 115 // The expected pattern of a call where the target is loaded from |
| 99 // the object pool: | 116 // the object pool: |
| 100 // 0: 41 ff 97 imm32 call [PP + off] | 117 // 0: 4d 8b a7 imm32 movq CR, [PP + offs] |
| 101 // 7: <- return address | 118 // 7: 4d 8b 5c 24 07 movq TMP, [CR + insns_offs] |
| 119 // 12: 49 83 c3 1f addq TMP, entry_offs | |
| 120 // 16: 41 ff d3 callq TMP | |
| 121 // 19: <- return address | |
| 102 class PoolPointerCall : public ValueObject { | 122 class PoolPointerCall : public ValueObject { |
| 103 public: | 123 public: |
| 104 explicit PoolPointerCall(uword return_address, const Code& code) | 124 explicit PoolPointerCall(uword return_address, const Code& code) |
| 105 : start_(return_address - kCallPatternSize), | 125 : start_(return_address - kCallPatternSize), |
| 106 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { | 126 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
| 107 ASSERT(IsValid(return_address)); | 127 ASSERT(IsValid()); |
| 108 } | 128 } |
| 109 | 129 |
| 110 static const int kCallPatternSize = 7; | 130 static const int kCallPatternSize = 19; |
| 111 | 131 |
| 112 static bool IsValid(uword return_address) { | 132 bool IsValid() const { |
| 113 uint8_t* code_bytes = | 133 static int16_t pattern[kCallPatternSize] = { |
| 114 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 134 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs] |
| 115 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && | 135 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs] |
| 116 (code_bytes[2] == 0x97); | 136 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs |
| 137 0x41, 0xff, 0xd3 // callq TMP | |
| 138 }; | |
| 139 return MatchesPattern(start_, pattern, kCallPatternSize); | |
| 117 } | 140 } |
| 118 | 141 |
| 119 intptr_t pp_index() const { | 142 intptr_t pp_index() const { |
| 120 return InstructionPattern::IndexFromPPLoad(start_ + 3); | 143 return InstructionPattern::IndexFromPPLoad(start_ + 3); |
| 121 } | 144 } |
| 122 | 145 |
| 123 uword Target() const { | 146 RawCode* Target() const { |
| 124 return object_pool_.RawValueAt(pp_index()); | 147 Code& code = Code::Handle(); |
| 148 code ^= object_pool_.ObjectAt(pp_index()); | |
| 149 return code.raw(); | |
| 125 } | 150 } |
| 126 | 151 |
| 127 void SetTarget(uword target) const { | 152 void SetTarget(const Code& target) const { |
| 128 object_pool_.SetRawValueAt(pp_index(), target); | 153 object_pool_.SetObjectAt(pp_index(), target); |
| 129 // No need to flush the instruction cache, since the code is not modified. | 154 // No need to flush the instruction cache, since the code is not modified. |
| 130 } | 155 } |
| 131 | 156 |
| 132 protected: | 157 protected: |
| 133 uword start_; | 158 uword start_; |
| 134 const ObjectPool& object_pool_; | 159 const ObjectPool& object_pool_; |
| 135 | 160 |
| 136 private: | 161 private: |
| 137 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); | 162 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); |
| 138 }; | 163 }; |
| 139 | 164 |
| 140 | 165 |
| 141 uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 166 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, |
| 142 const Code& code) { | 167 const Code& code) { |
| 143 ASSERT(code.ContainsInstructionAt(return_address)); | 168 ASSERT(code.ContainsInstructionAt(return_address)); |
| 144 PoolPointerCall call(return_address, code); | 169 PoolPointerCall call(return_address, code); |
| 145 return call.Target(); | 170 return call.Target(); |
| 146 } | 171 } |
| 147 | 172 |
| 148 | 173 |
| 149 void CodePatcher::PatchStaticCallAt(uword return_address, | 174 void CodePatcher::PatchStaticCallAt(uword return_address, |
| 150 const Code& code, | 175 const Code& code, |
| 151 uword new_target) { | 176 const Code& new_target) { |
| 152 PatchPoolPointerCallAt(return_address, code, new_target); | 177 PatchPoolPointerCallAt(return_address, code, new_target); |
| 153 } | 178 } |
| 154 | 179 |
| 155 | 180 |
| 156 void CodePatcher::PatchPoolPointerCallAt(uword return_address, | 181 void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
| 157 const Code& code, | 182 const Code& code, |
| 158 uword new_target) { | 183 const Code& new_target) { |
| 159 ASSERT(code.ContainsInstructionAt(return_address)); | 184 ASSERT(code.ContainsInstructionAt(return_address)); |
| 160 PoolPointerCall call(return_address, code); | 185 PoolPointerCall call(return_address, code); |
| 161 call.SetTarget(new_target); | 186 call.SetTarget(new_target); |
| 162 } | 187 } |
| 163 | 188 |
| 164 | 189 |
| 165 void CodePatcher::PatchInstanceCallAt(uword return_address, | 190 void CodePatcher::PatchInstanceCallAt(uword return_address, |
| 166 const Code& code, | 191 const Code& code, |
| 167 uword new_target) { | 192 const Code& new_target) { |
| 168 ASSERT(code.ContainsInstructionAt(return_address)); | 193 ASSERT(code.ContainsInstructionAt(return_address)); |
| 169 InstanceCall call(return_address, code); | 194 InstanceCall call(return_address, code); |
| 170 call.set_target(new_target); | 195 call.set_target(new_target); |
| 171 } | 196 } |
| 172 | 197 |
| 173 | 198 |
| 174 uword CodePatcher::GetInstanceCallAt(uword return_address, | 199 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, |
| 175 const Code& code, | 200 const Code& code, |
| 176 ICData* ic_data) { | 201 ICData* ic_data) { |
| 177 ASSERT(code.ContainsInstructionAt(return_address)); | 202 ASSERT(code.ContainsInstructionAt(return_address)); |
| 178 InstanceCall call(return_address, code); | 203 InstanceCall call(return_address, code); |
| 179 if (ic_data != NULL) { | 204 if (ic_data != NULL) { |
| 180 *ic_data ^= call.ic_data(); | 205 *ic_data ^= call.ic_data(); |
| 181 } | 206 } |
| 182 return call.target(); | 207 return call.target(); |
| 183 } | 208 } |
| 184 | 209 |
| 185 | 210 |
| 186 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 211 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 | 263 |
| 239 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { | 264 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
| 240 ASSERT(code.ContainsInstructionAt(pc)); | 265 ASSERT(code.ContainsInstructionAt(pc)); |
| 241 EdgeCounter counter(pc, code); | 266 EdgeCounter counter(pc, code); |
| 242 return counter.edge_counter(); | 267 return counter.edge_counter(); |
| 243 } | 268 } |
| 244 | 269 |
| 245 } // namespace dart | 270 } // namespace dart |
| 246 | 271 |
| 247 #endif // defined TARGET_ARCH_X64 | 272 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |