OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/instructions.h" | 8 #include "vm/instructions.h" |
9 #include "vm/instructions_arm.h" | 9 #include "vm/instructions_arm.h" |
10 | 10 |
11 #include "vm/assembler.h" | 11 #include "vm/assembler.h" |
12 #include "vm/constants_arm.h" | 12 #include "vm/constants_arm.h" |
13 #include "vm/cpu.h" | 13 #include "vm/cpu.h" |
14 #include "vm/object.h" | 14 #include "vm/object.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 CallPattern::CallPattern(uword pc, const Code& code) | 18 CallPattern::CallPattern(uword pc, const Code& code) |
19 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 19 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
20 end_(pc), | 20 end_(pc), |
21 ic_data_load_end_(0), | 21 ic_data_load_end_(0), |
22 target_code_pool_index_(-1), | 22 target_code_pool_index_(-1), |
23 ic_data_(ICData::Handle()) { | 23 ic_data_(ICData::Handle()) { |
24 ASSERT(code.ContainsInstructionAt(pc)); | 24 ASSERT(code.ContainsInstructionAt(pc)); |
25 // Last instruction: blx lr. | 25 // Last instruction: blx lr. |
26 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e); | 26 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e); |
27 | 27 |
28 Register reg; | 28 Register reg; |
29 ic_data_load_end_ = | 29 ic_data_load_end_ = InstructionPattern::DecodeLoadWordFromPool( |
30 InstructionPattern::DecodeLoadWordFromPool(end_ - 2 * Instr::kInstrSize, | 30 end_ - 2 * Instr::kInstrSize, ®, &target_code_pool_index_); |
31 ®, | |
32 &target_code_pool_index_); | |
33 ASSERT(reg == CODE_REG); | 31 ASSERT(reg == CODE_REG); |
34 } | 32 } |
35 | 33 |
36 | 34 |
37 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) | 35 NativeCallPattern::NativeCallPattern(uword pc, const Code& code) |
38 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 36 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
39 end_(pc), | 37 end_(pc), |
40 native_function_pool_index_(-1), | 38 native_function_pool_index_(-1), |
41 target_code_pool_index_(-1) { | 39 target_code_pool_index_(-1) { |
42 ASSERT(code.ContainsInstructionAt(pc)); | 40 ASSERT(code.ContainsInstructionAt(pc)); |
43 // Last instruction: blx lr. | 41 // Last instruction: blx lr. |
44 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e); | 42 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e); |
45 | 43 |
46 Register reg; | 44 Register reg; |
47 uword native_function_load_end = | 45 uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool( |
48 InstructionPattern::DecodeLoadWordFromPool(end_ - 2 * Instr::kInstrSize, | 46 end_ - 2 * Instr::kInstrSize, ®, &target_code_pool_index_); |
49 ®, | |
50 &target_code_pool_index_); | |
51 ASSERT(reg == CODE_REG); | 47 ASSERT(reg == CODE_REG); |
52 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, | 48 InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, ®, |
53 ®, | |
54 &native_function_pool_index_); | 49 &native_function_pool_index_); |
55 ASSERT(reg == R9); | 50 ASSERT(reg == R9); |
56 } | 51 } |
57 | 52 |
58 | 53 |
59 RawCode* NativeCallPattern::target() const { | 54 RawCode* NativeCallPattern::target() const { |
60 return reinterpret_cast<RawCode*>( | 55 return reinterpret_cast<RawCode*>( |
61 object_pool_.ObjectAt(target_code_pool_index_)); | 56 object_pool_.ObjectAt(target_code_pool_index_)); |
62 } | 57 } |
63 | 58 |
64 | 59 |
65 void NativeCallPattern::set_target(const Code& new_target) const { | 60 void NativeCallPattern::set_target(const Code& new_target) const { |
66 object_pool_.SetObjectAt(target_code_pool_index_, new_target); | 61 object_pool_.SetObjectAt(target_code_pool_index_, new_target); |
67 // No need to flush the instruction cache, since the code is not modified. | 62 // No need to flush the instruction cache, since the code is not modified. |
68 } | 63 } |
69 | 64 |
70 | 65 |
71 NativeFunction NativeCallPattern::native_function() const { | 66 NativeFunction NativeCallPattern::native_function() const { |
72 return reinterpret_cast<NativeFunction>( | 67 return reinterpret_cast<NativeFunction>( |
73 object_pool_.RawValueAt(native_function_pool_index_)); | 68 object_pool_.RawValueAt(native_function_pool_index_)); |
74 } | 69 } |
75 | 70 |
76 | 71 |
77 void NativeCallPattern::set_native_function(NativeFunction func) const { | 72 void NativeCallPattern::set_native_function(NativeFunction func) const { |
78 object_pool_.SetRawValueAt(native_function_pool_index_, | 73 object_pool_.SetRawValueAt(native_function_pool_index_, |
79 reinterpret_cast<uword>(func)); | 74 reinterpret_cast<uword>(func)); |
80 } | 75 } |
81 | 76 |
82 | 77 |
83 // Decodes a load sequence ending at 'end' (the last instruction of the load | 78 // Decodes a load sequence ending at 'end' (the last instruction of the load |
84 // sequence is the instruction before the one at end). Returns a pointer to | 79 // sequence is the instruction before the one at end). Returns a pointer to |
85 // the first instruction in the sequence. Returns the register being loaded | 80 // the first instruction in the sequence. Returns the register being loaded |
86 // and the loaded object in the output parameters 'reg' and 'obj' | 81 // and the loaded object in the output parameters 'reg' and 'obj' |
87 // respectively. | 82 // respectively. |
88 uword InstructionPattern::DecodeLoadObject(uword end, | 83 uword InstructionPattern::DecodeLoadObject(uword end, |
89 const ObjectPool& object_pool, | 84 const ObjectPool& object_pool, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo | 144 ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo |
150 imm |= (instr & 0xf0000) >> 4; | 145 imm |= (instr & 0xf0000) >> 4; |
151 imm |= instr & 0xfff; | 146 imm |= instr & 0xfff; |
152 *reg = static_cast<Register>((instr & 0xf000) >> 12); | 147 *reg = static_cast<Register>((instr & 0xf000) >> 12); |
153 *value = imm; | 148 *value = imm; |
154 } | 149 } |
155 return start; | 150 return start; |
156 } | 151 } |
157 | 152 |
158 | 153 |
159 static bool IsLoadWithOffset(int32_t instr, Register base, | 154 static bool IsLoadWithOffset(int32_t instr, |
160 intptr_t* offset, Register* dst) { | 155 Register base, |
| 156 intptr_t* offset, |
| 157 Register* dst) { |
161 if ((instr & 0xffff0000) == (0xe5900000 | (base << 16))) { | 158 if ((instr & 0xffff0000) == (0xe5900000 | (base << 16))) { |
162 // ldr reg, [base, #+offset] | 159 // ldr reg, [base, #+offset] |
163 *offset = instr & 0xfff; | 160 *offset = instr & 0xfff; |
164 *dst = static_cast<Register>((instr & 0xf000) >> 12); | 161 *dst = static_cast<Register>((instr & 0xf000) >> 12); |
165 return true; | 162 return true; |
166 } | 163 } |
167 return false; | 164 return false; |
168 } | 165 } |
169 | 166 |
170 | 167 |
(...skipping 25 matching lines...) Expand all Loading... |
196 ASSERT((instr & 0xffff0000) == (0xe0800000 | (PP << 16))); | 193 ASSERT((instr & 0xffff0000) == (0xe0800000 | (PP << 16))); |
197 // add reg, pp, reg | 194 // add reg, pp, reg |
198 end = DecodeLoadWordImmediate(end, reg, &offset); | 195 end = DecodeLoadWordImmediate(end, reg, &offset); |
199 } | 196 } |
200 } | 197 } |
201 *index = ObjectPool::IndexFromOffset(offset); | 198 *index = ObjectPool::IndexFromOffset(offset); |
202 return start; | 199 return start; |
203 } | 200 } |
204 | 201 |
205 | 202 |
206 bool DecodeLoadObjectFromPoolOrThread(uword pc, | 203 bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { |
207 const Code& code, | |
208 Object* obj) { | |
209 ASSERT(code.ContainsInstructionAt(pc)); | 204 ASSERT(code.ContainsInstructionAt(pc)); |
210 | 205 |
211 int32_t instr = Instr::At(pc)->InstructionBits(); | 206 int32_t instr = Instr::At(pc)->InstructionBits(); |
212 intptr_t offset; | 207 intptr_t offset; |
213 Register dst; | 208 Register dst; |
214 if (IsLoadWithOffset(instr, PP, &offset, &dst)) { | 209 if (IsLoadWithOffset(instr, PP, &offset, &dst)) { |
215 intptr_t index = ObjectPool::IndexFromOffset(offset); | 210 intptr_t index = ObjectPool::IndexFromOffset(offset); |
216 const ObjectPool& pool = ObjectPool::Handle(code.object_pool()); | 211 const ObjectPool& pool = ObjectPool::Handle(code.object_pool()); |
217 if (pool.InfoAt(index) == ObjectPool::kTaggedObject) { | 212 if (pool.InfoAt(index) == ObjectPool::kTaggedObject) { |
218 *obj = pool.ObjectAt(index); | 213 *obj = pool.ObjectAt(index); |
219 return true; | 214 return true; |
220 } | 215 } |
221 } else if (IsLoadWithOffset(instr, THR, &offset, &dst)) { | 216 } else if (IsLoadWithOffset(instr, THR, &offset, &dst)) { |
222 return Thread::ObjectAtOffset(offset, obj); | 217 return Thread::ObjectAtOffset(offset, obj); |
223 } | 218 } |
224 // TODO(rmacnak): Sequence for loads beyond 12 bits. | 219 // TODO(rmacnak): Sequence for loads beyond 12 bits. |
225 | 220 |
226 return false; | 221 return false; |
227 } | 222 } |
228 | 223 |
229 | 224 |
230 RawICData* CallPattern::IcData() { | 225 RawICData* CallPattern::IcData() { |
231 if (ic_data_.IsNull()) { | 226 if (ic_data_.IsNull()) { |
232 Register reg; | 227 Register reg; |
233 InstructionPattern::DecodeLoadObject(ic_data_load_end_, | 228 InstructionPattern::DecodeLoadObject(ic_data_load_end_, object_pool_, ®, |
234 object_pool_, | |
235 ®, | |
236 &ic_data_); | 229 &ic_data_); |
237 ASSERT(reg == R9); | 230 ASSERT(reg == R9); |
238 } | 231 } |
239 return ic_data_.raw(); | 232 return ic_data_.raw(); |
240 } | 233 } |
241 | 234 |
242 | 235 |
243 RawCode* CallPattern::TargetCode() const { | 236 RawCode* CallPattern::TargetCode() const { |
244 return reinterpret_cast<RawCode*>( | 237 return reinterpret_cast<RawCode*>( |
245 object_pool_.ObjectAt(target_code_pool_index_)); | 238 object_pool_.ObjectAt(target_code_pool_index_)); |
246 } | 239 } |
247 | 240 |
248 | 241 |
249 void CallPattern::SetTargetCode(const Code& target_code) const { | 242 void CallPattern::SetTargetCode(const Code& target_code) const { |
250 object_pool_.SetObjectAt(target_code_pool_index_, target_code); | 243 object_pool_.SetObjectAt(target_code_pool_index_, target_code); |
251 } | 244 } |
252 | 245 |
253 | 246 |
254 SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) | 247 SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) |
255 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), | 248 : object_pool_(ObjectPool::Handle(code.GetObjectPool())), |
256 data_pool_index_(-1), | 249 data_pool_index_(-1), |
257 target_pool_index_(-1) { | 250 target_pool_index_(-1) { |
258 ASSERT(code.ContainsInstructionAt(pc)); | 251 ASSERT(code.ContainsInstructionAt(pc)); |
259 // Last instruction: blx lr. | 252 // Last instruction: blx lr. |
260 ASSERT(*(reinterpret_cast<uword*>(pc) - 1) == 0xe12fff3e); | 253 ASSERT(*(reinterpret_cast<uword*>(pc) - 1) == 0xe12fff3e); |
261 | 254 |
262 Register reg; | 255 Register reg; |
263 uword data_load_end = | 256 uword data_load_end = InstructionPattern::DecodeLoadWordFromPool( |
264 InstructionPattern::DecodeLoadWordFromPool(pc - Instr::kInstrSize, | 257 pc - Instr::kInstrSize, ®, &data_pool_index_); |
265 ®, | |
266 &data_pool_index_); | |
267 ASSERT(reg == R9); | 258 ASSERT(reg == R9); |
268 InstructionPattern::DecodeLoadWordFromPool(data_load_end - Instr::kInstrSize, | 259 InstructionPattern::DecodeLoadWordFromPool(data_load_end - Instr::kInstrSize, |
269 ®, | 260 ®, &target_pool_index_); |
270 &target_pool_index_); | |
271 ASSERT(reg == CODE_REG); | 261 ASSERT(reg == CODE_REG); |
272 } | 262 } |
273 | 263 |
274 | 264 |
275 RawObject* SwitchableCallPattern::data() const { | 265 RawObject* SwitchableCallPattern::data() const { |
276 return object_pool_.ObjectAt(data_pool_index_); | 266 return object_pool_.ObjectAt(data_pool_index_); |
277 } | 267 } |
278 | 268 |
279 | 269 |
280 RawCode* SwitchableCallPattern::target() const { | 270 RawCode* SwitchableCallPattern::target() const { |
281 return reinterpret_cast<RawCode*>( | 271 return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(target_pool_index_)); |
282 object_pool_.ObjectAt(target_pool_index_)); | |
283 } | 272 } |
284 | 273 |
285 | 274 |
286 void SwitchableCallPattern::SetData(const Object& data) const { | 275 void SwitchableCallPattern::SetData(const Object& data) const { |
287 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode()); | 276 ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode()); |
288 object_pool_.SetObjectAt(data_pool_index_, data); | 277 object_pool_.SetObjectAt(data_pool_index_, data); |
289 } | 278 } |
290 | 279 |
291 | 280 |
292 void SwitchableCallPattern::SetTarget(const Code& target) const { | 281 void SwitchableCallPattern::SetTarget(const Code& target) const { |
293 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode()); | 282 ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode()); |
294 object_pool_.SetObjectAt(target_pool_index_, target); | 283 object_pool_.SetObjectAt(target_pool_index_, target); |
295 } | 284 } |
296 | 285 |
297 | 286 |
298 ReturnPattern::ReturnPattern(uword pc) | 287 ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {} |
299 : pc_(pc) { | |
300 } | |
301 | 288 |
302 | 289 |
303 bool ReturnPattern::IsValid() const { | 290 bool ReturnPattern::IsValid() const { |
304 Instr* bx_lr = Instr::At(pc_); | 291 Instr* bx_lr = Instr::At(pc_); |
305 const int32_t B4 = 1 << 4; | 292 const int32_t B4 = 1 << 4; |
306 const int32_t B21 = 1 << 21; | 293 const int32_t B21 = 1 << 21; |
307 const int32_t B24 = 1 << 24; | 294 const int32_t B24 = 1 << 24; |
308 int32_t instruction = (static_cast<int32_t>(AL) << kConditionShift) | | 295 int32_t instruction = (static_cast<int32_t>(AL) << kConditionShift) | B24 | |
309 B24 | B21 | (0xfff << 8) | B4 | | 296 B21 | (0xfff << 8) | B4 | |
310 (static_cast<int32_t>(LR) << kRmShift); | 297 (static_cast<int32_t>(LR) << kRmShift); |
311 const ARMVersion version = TargetCPUFeatures::arm_version(); | 298 const ARMVersion version = TargetCPUFeatures::arm_version(); |
312 if ((version == ARMv5TE) || (version == ARMv6)) { | 299 if ((version == ARMv5TE) || (version == ARMv6)) { |
313 return bx_lr->InstructionBits() == instruction; | 300 return bx_lr->InstructionBits() == instruction; |
314 } else { | 301 } else { |
315 ASSERT(version == ARMv7); | 302 ASSERT(version == ARMv7); |
316 return bx_lr->InstructionBits() == instruction; | 303 return bx_lr->InstructionBits() == instruction; |
317 } | 304 } |
318 return false; | 305 return false; |
319 } | 306 } |
320 | 307 |
321 } // namespace dart | 308 } // namespace dart |
322 | 309 |
323 #endif // defined TARGET_ARCH_ARM | 310 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |