| 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" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); | 95 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 | 98 |
| 99 // The expected pattern of a call where the target is loaded from | 99 // The expected pattern of a call where the target is loaded from |
| 100 // the object pool: | 100 // the object pool: |
| 101 // 0: 41 ff 97 imm32 call [PP + off] | 101 // 0: 41 ff 97 imm32 call [PP + off] |
| 102 // 7: <- return address | 102 // 7: <- return address |
| 103 class PoolPointerCall : public ValueObject { | 103 class PoolPointerCall : public ValueObject { |
| 104 public: | 104 public: |
| 105 explicit PoolPointerCall(uword return_address) | 105 explicit PoolPointerCall(uword return_address, const Code& code) |
| 106 : start_(return_address - kCallPatternSize) { | 106 : start_(return_address - kCallPatternSize), |
| 107 object_pool_(Array::Handle(code.ObjectPool())) { |
| 107 ASSERT(IsValid(return_address)); | 108 ASSERT(IsValid(return_address)); |
| 108 } | 109 } |
| 109 | 110 |
| 110 static const int kCallPatternSize = 7; | 111 static const int kCallPatternSize = 7; |
| 111 | 112 |
| 112 static bool IsValid(uword return_address) { | 113 static bool IsValid(uword return_address) { |
| 113 uint8_t* code_bytes = | 114 uint8_t* code_bytes = |
| 114 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 115 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); |
| 115 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && | 116 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && |
| 116 (code_bytes[2] == 0x97); | 117 (code_bytes[2] == 0x97); |
| 117 } | 118 } |
| 118 | 119 |
| 119 int32_t pp_offset() const { | 120 intptr_t pp_index() const { |
| 120 return *reinterpret_cast<int32_t*>(start_ + 3); | 121 return InstructionPattern::IndexFromPPLoad(start_ + 3); |
| 121 } | 122 } |
| 122 | 123 |
| 123 void set_pp_offset(int32_t offset) const { | 124 uword Target() const { |
| 124 *reinterpret_cast<int32_t*>(start_ + 3) = offset; | 125 return reinterpret_cast<uword>(object_pool_.At(pp_index())); |
| 125 CPU::FlushICache(start_, kCallPatternSize); | 126 } |
| 127 |
| 128 void SetTarget(uword target) const { |
| 129 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target)); |
| 130 object_pool_.SetAt(pp_index(), smi); |
| 131 // No need to flush the instruction cache, since the code is not modified. |
| 126 } | 132 } |
| 127 | 133 |
| 128 protected: | 134 protected: |
| 129 uword start_; | 135 uword start_; |
| 136 const Array& object_pool_; |
| 130 | 137 |
| 131 private: | 138 private: |
| 132 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); | 139 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); |
| 133 }; | 140 }; |
| 134 | 141 |
| 135 | 142 |
| 136 // The expected pattern of a dart static call: | |
| 137 // 0: 41 ff 97 imm32 call [PP + off] | |
| 138 // 7: <- return address | |
| 139 class StaticCall : public PoolPointerCall { | |
| 140 public: | |
| 141 StaticCall(uword return_address, const Code& code) | |
| 142 : PoolPointerCall(return_address), | |
| 143 object_pool_(Array::Handle(code.ObjectPool())) { | |
| 144 ASSERT(IsValid(return_address)); | |
| 145 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize); | |
| 146 } | |
| 147 | |
| 148 uword target() const { | |
| 149 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); | |
| 150 return reinterpret_cast<uword>(object_pool_.At(index)); | |
| 151 } | |
| 152 | |
| 153 void set_target(uword target) const { | |
| 154 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); | |
| 155 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target)); | |
| 156 object_pool_.SetAt(index, smi); | |
| 157 // No need to flush the instruction cache, since the code is not modified. | |
| 158 } | |
| 159 | |
| 160 private: | |
| 161 const Array& object_pool_; | |
| 162 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); | |
| 163 }; | |
| 164 | |
| 165 | |
| 166 uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 143 uword CodePatcher::GetStaticCallTargetAt(uword return_address, |
| 167 const Code& code) { | 144 const Code& code) { |
| 168 ASSERT(code.ContainsInstructionAt(return_address)); | 145 ASSERT(code.ContainsInstructionAt(return_address)); |
| 169 StaticCall call(return_address, code); | 146 PoolPointerCall call(return_address, code); |
| 170 return call.target(); | 147 return call.Target(); |
| 171 } | 148 } |
| 172 | 149 |
| 173 | 150 |
| 174 void CodePatcher::PatchStaticCallAt(uword return_address, | 151 void CodePatcher::PatchStaticCallAt(uword return_address, |
| 175 const Code& code, | 152 const Code& code, |
| 176 uword new_target) { | 153 uword new_target) { |
| 177 ASSERT(code.ContainsInstructionAt(return_address)); | 154 PatchPoolPointerCallAt(return_address, code, new_target); |
| 178 StaticCall call(return_address, code); | |
| 179 call.set_target(new_target); | |
| 180 } | 155 } |
| 181 | 156 |
| 182 | 157 |
| 183 int32_t CodePatcher::GetPoolOffsetAt(uword return_address) { | 158 void CodePatcher::PatchPoolPointerCallAt(uword return_address, |
| 184 PoolPointerCall call(return_address); | 159 const Code& code, |
| 185 return call.pp_offset(); | 160 uword new_target) { |
| 161 ASSERT(code.ContainsInstructionAt(return_address)); |
| 162 PoolPointerCall call(return_address, code); |
| 163 call.SetTarget(new_target); |
| 186 } | 164 } |
| 187 | 165 |
| 188 | 166 |
| 189 void CodePatcher::SetPoolOffsetAt(uword return_address, int32_t offset) { | |
| 190 PoolPointerCall call(return_address); | |
| 191 call.set_pp_offset(offset); | |
| 192 } | |
| 193 | |
| 194 | |
| 195 void CodePatcher::PatchInstanceCallAt(uword return_address, | 167 void CodePatcher::PatchInstanceCallAt(uword return_address, |
| 196 const Code& code, | 168 const Code& code, |
| 197 uword new_target) { | 169 uword new_target) { |
| 198 ASSERT(code.ContainsInstructionAt(return_address)); | 170 ASSERT(code.ContainsInstructionAt(return_address)); |
| 199 InstanceCall call(return_address, code); | 171 InstanceCall call(return_address, code); |
| 200 call.set_target(new_target); | 172 call.set_target(new_target); |
| 201 } | 173 } |
| 202 | 174 |
| 203 | 175 |
| 204 uword CodePatcher::GetInstanceCallAt(uword return_address, | 176 uword CodePatcher::GetInstanceCallAt(uword return_address, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 | 240 |
| 269 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { | 241 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
| 270 ASSERT(code.ContainsInstructionAt(pc)); | 242 ASSERT(code.ContainsInstructionAt(pc)); |
| 271 EdgeCounter counter(pc, code); | 243 EdgeCounter counter(pc, code); |
| 272 return counter.edge_counter(); | 244 return counter.edge_counter(); |
| 273 } | 245 } |
| 274 | 246 |
| 275 } // namespace dart | 247 } // namespace dart |
| 276 | 248 |
| 277 #endif // defined TARGET_ARCH_X64 | 249 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |