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 |