OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 const uint16_t offset_high = Utils::High16Bits(offset); | 267 const uint16_t offset_high = Utils::High16Bits(offset); |
268 movz(dst, offset_low, 0); | 268 movz(dst, offset_low, 0); |
269 if (offset_high != 0) { | 269 if (offset_high != 0) { |
270 movk(dst, offset_high, 1); | 270 movk(dst, offset_high, 1); |
271 } | 271 } |
272 ldr(dst, Address(pp, dst)); | 272 ldr(dst, Address(pp, dst)); |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 | 276 |
| 277 intptr_t Assembler::FindExternalLabel(const ExternalLabel* label, |
| 278 Patchability patchable) { |
| 279 // The object pool cannot be used in the vm isolate. |
| 280 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 281 ASSERT(!object_pool_.IsNull()); |
| 282 const uword address = label->address(); |
| 283 ASSERT(Utils::IsAligned(address, 4)); |
| 284 // The address is stored in the object array as a RawSmi. |
| 285 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address)); |
| 286 if (patchable == kNotPatchable) { |
| 287 // If the call site is not patchable, we can try to re-use an existing |
| 288 // entry. |
| 289 return FindObject(smi, kNotPatchable); |
| 290 } |
| 291 // If the call is patchable, do not reuse an existing entry since each |
| 292 // reference may be patched independently. |
| 293 object_pool_.Add(smi, Heap::kOld); |
| 294 patchable_pool_entries_.Add(patchable); |
| 295 return object_pool_.Length() - 1; |
| 296 } |
| 297 |
| 298 |
277 intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) { | 299 intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) { |
278 // The object pool cannot be used in the vm isolate. | 300 // The object pool cannot be used in the vm isolate. |
279 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 301 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
280 ASSERT(!object_pool_.IsNull()); | 302 ASSERT(!object_pool_.IsNull()); |
281 | 303 |
282 // If the object is not patchable, check if we've already got it in the | 304 // If the object is not patchable, check if we've already got it in the |
283 // object pool. | 305 // object pool. |
284 if (patchable == kNotPatchable) { | 306 if (patchable == kNotPatchable) { |
285 // Special case for Object::null(), which is always at object_pool_ index 0 | 307 // Special case for Object::null(), which is always at object_pool_ index 0 |
286 // because Lookup() below returns 0 when the object is not mapped in the | 308 // because Lookup() below returns 0 when the object is not mapped in the |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } | 357 } |
336 | 358 |
337 | 359 |
338 bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) { | 360 bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) { |
339 return !Utils::IsInt(32, imm) && | 361 return !Utils::IsInt(32, imm) && |
340 (pp != kNoRegister) && | 362 (pp != kNoRegister) && |
341 (Isolate::Current() != Dart::vm_isolate()); | 363 (Isolate::Current() != Dart::vm_isolate()); |
342 } | 364 } |
343 | 365 |
344 | 366 |
| 367 void Assembler::LoadExternalLabel(Register dst, |
| 368 const ExternalLabel* label, |
| 369 Patchability patchable, |
| 370 Register pp) { |
| 371 const int32_t offset = |
| 372 Array::element_offset(FindExternalLabel(label, patchable)); |
| 373 LoadWordFromPoolOffset(dst, pp, offset); |
| 374 } |
| 375 |
| 376 |
345 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { | 377 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { |
346 if (CanLoadObjectFromPool(object)) { | 378 if (CanLoadObjectFromPool(object)) { |
347 const int32_t offset = | 379 const int32_t offset = |
348 Array::element_offset(FindObject(object, kNotPatchable)); | 380 Array::element_offset(FindObject(object, kNotPatchable)); |
349 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); | 381 LoadWordFromPoolOffset(dst, pp, offset); |
350 } else { | 382 } else { |
351 ASSERT((Isolate::Current() == Dart::vm_isolate()) || | 383 ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
352 object.IsSmi() || | 384 object.IsSmi() || |
353 object.InVMHeap()); | 385 object.InVMHeap()); |
354 LoadImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); | 386 LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); |
355 } | 387 } |
356 } | 388 } |
357 | 389 |
358 | 390 |
| 391 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { |
| 392 if ((pp != kNoRegister) && (Isolate::Current() != Dart::vm_isolate())) { |
| 393 int64_t val_smi_tag = imm & kSmiTagMask; |
| 394 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 395 const int32_t offset = Array::element_offset(FindImmediate(imm)); |
| 396 LoadWordFromPoolOffset(reg, pp, offset); |
| 397 if (val_smi_tag != 0) { |
| 398 // Add back the tag bits. |
| 399 orri(reg, reg, val_smi_tag); |
| 400 } |
| 401 } else { |
| 402 // TODO(zra): Since this sequence only needs to be decodable, it can be |
| 403 // of variable length. |
| 404 LoadPatchableImmediate(reg, imm); |
| 405 } |
| 406 } |
| 407 |
| 408 |
| 409 void Assembler::LoadPatchableImmediate(Register reg, int64_t imm) { |
| 410 const uint32_t w0 = Utils::Low32Bits(imm); |
| 411 const uint32_t w1 = Utils::High32Bits(imm); |
| 412 const uint16_t h0 = Utils::Low16Bits(w0); |
| 413 const uint16_t h1 = Utils::High16Bits(w0); |
| 414 const uint16_t h2 = Utils::Low16Bits(w1); |
| 415 const uint16_t h3 = Utils::High16Bits(w1); |
| 416 movz(reg, h0, 0); |
| 417 movk(reg, h1, 1); |
| 418 movk(reg, h2, 2); |
| 419 movk(reg, h3, 3); |
| 420 } |
| 421 |
| 422 |
359 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { | 423 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { |
360 Comment("LoadImmediate"); | 424 Comment("LoadImmediate"); |
361 if (CanLoadImmediateFromPool(imm, pp)) { | 425 if (CanLoadImmediateFromPool(imm, pp)) { |
362 // It's a 64-bit constant and we're not in the VM isolate, so load from | 426 // It's a 64-bit constant and we're not in the VM isolate, so load from |
363 // object pool. | 427 // object pool. |
364 // Save the bits that must be masked-off for the SmiTag | 428 // Save the bits that must be masked-off for the SmiTag |
365 int64_t val_smi_tag = imm & kSmiTagMask; | 429 int64_t val_smi_tag = imm & kSmiTagMask; |
366 imm &= ~kSmiTagMask; // Mask off the tag bits. | 430 imm &= ~kSmiTagMask; // Mask off the tag bits. |
367 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 431 const int32_t offset = Array::element_offset(FindImmediate(imm)); |
368 LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); | 432 LoadWordFromPoolOffset(reg, pp, offset); |
369 if (val_smi_tag != 0) { | 433 if (val_smi_tag != 0) { |
370 // Add back the tag bits. | 434 // Add back the tag bits. |
371 orri(reg, reg, val_smi_tag); | 435 orri(reg, reg, val_smi_tag); |
372 } | 436 } |
373 } else { | 437 } else { |
374 // 1. Can we use one orri operation? | 438 // 1. Can we use one orri operation? |
375 Operand op; | 439 Operand op; |
376 Operand::OperandType ot; | 440 Operand::OperandType ot; |
377 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); | 441 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); |
378 if (ot == Operand::BitfieldImm) { | 442 if (ot == Operand::BitfieldImm) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 } else { | 503 } else { |
440 movz(reg, h3, 3); | 504 movz(reg, h3, 3); |
441 } | 505 } |
442 } | 506 } |
443 } | 507 } |
444 } | 508 } |
445 | 509 |
446 } // namespace dart | 510 } // namespace dart |
447 | 511 |
448 #endif // defined TARGET_ARCH_ARM64 | 512 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |