| 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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
| 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 17 matching lines...) Expand all Loading... |
| 28 Assembler::Assembler(bool use_far_branches) | 28 Assembler::Assembler(bool use_far_branches) |
| 29 : buffer_(), | 29 : buffer_(), |
| 30 prologue_offset_(-1), | 30 prologue_offset_(-1), |
| 31 use_far_branches_(use_far_branches), | 31 use_far_branches_(use_far_branches), |
| 32 comments_(), | 32 comments_(), |
| 33 allow_constant_pool_(true) { | 33 allow_constant_pool_(true) { |
| 34 if (Isolate::Current() != Dart::vm_isolate()) { | 34 if (Isolate::Current() != Dart::vm_isolate()) { |
| 35 // These objects and labels need to be accessible through every pool-pointer | 35 // These objects and labels need to be accessible through every pool-pointer |
| 36 // at the same index. | 36 // at the same index. |
| 37 intptr_t index = | 37 intptr_t index = |
| 38 object_pool_.AddObject(Object::null_object(), kNotPatchable); | 38 object_pool_wrapper_.AddObject(Object::null_object()); |
| 39 ASSERT(index == 0); | 39 ASSERT(index == 0); |
| 40 | 40 |
| 41 index = object_pool_.AddObject(Bool::True(), kNotPatchable); | 41 index = object_pool_wrapper_.AddObject(Bool::True()); |
| 42 ASSERT(index == 1); | 42 ASSERT(index == 1); |
| 43 | 43 |
| 44 index = object_pool_.AddObject(Bool::False(), kNotPatchable); | 44 index = object_pool_wrapper_.AddObject(Bool::False()); |
| 45 ASSERT(index == 2); | 45 ASSERT(index == 2); |
| 46 | 46 |
| 47 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); | 47 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); |
| 48 StubCode* stub_code = Isolate::Current()->stub_code(); | 48 StubCode* stub_code = Isolate::Current()->stub_code(); |
| 49 if (stub_code->UpdateStoreBuffer_entry() != NULL) { | 49 if (stub_code->UpdateStoreBuffer_entry() != NULL) { |
| 50 object_pool_.AddExternalLabel( | 50 object_pool_wrapper_.AddExternalLabel( |
| 51 &stub_code->UpdateStoreBufferLabel(), kNotPatchable); | 51 &stub_code->UpdateStoreBufferLabel(), kNotPatchable); |
| 52 } else { | 52 } else { |
| 53 object_pool_.AddObject(vacant, kNotPatchable); | 53 object_pool_wrapper_.AddObject(vacant); |
| 54 } | 54 } |
| 55 | 55 |
| 56 if (stub_code->CallToRuntime_entry() != NULL) { | 56 if (stub_code->CallToRuntime_entry() != NULL) { |
| 57 object_pool_.AddExternalLabel( | 57 object_pool_wrapper_.AddExternalLabel( |
| 58 &stub_code->CallToRuntimeLabel(), kNotPatchable); | 58 &stub_code->CallToRuntimeLabel(), kNotPatchable); |
| 59 } else { | 59 } else { |
| 60 object_pool_.AddObject(vacant, kNotPatchable); | 60 object_pool_wrapper_.AddObject(vacant); |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 | 64 |
| 65 | 65 |
| 66 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 66 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
| 67 ASSERT(Utils::IsAligned(data, 4)); | 67 ASSERT(Utils::IsAligned(data, 4)); |
| 68 ASSERT(Utils::IsAligned(length, 4)); | 68 ASSERT(Utils::IsAligned(length, 4)); |
| 69 const uword end = data + length; | 69 const uword end = data + length; |
| 70 while (data < end) { | 70 while (data < end) { |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 Operand::CanHold(upper20, kXRegSizeInBits, &op); | 383 Operand::CanHold(upper20, kXRegSizeInBits, &op); |
| 384 ASSERT(ot == Operand::Immediate); | 384 ASSERT(ot == Operand::Immediate); |
| 385 ASSERT(Address::CanHoldOffset(lower12)); | 385 ASSERT(Address::CanHoldOffset(lower12)); |
| 386 add(dst, pp, op); | 386 add(dst, pp, op); |
| 387 ldr(dst, Address(dst, lower12)); | 387 ldr(dst, Address(dst, lower12)); |
| 388 } | 388 } |
| 389 | 389 |
| 390 | 390 |
| 391 intptr_t Assembler::FindImmediate(int64_t imm) { | 391 intptr_t Assembler::FindImmediate(int64_t imm) { |
| 392 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 392 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 393 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); | 393 return object_pool_wrapper_.FindImmediate(imm); |
| 394 return object_pool_.FindObject(smi, kNotPatchable); | |
| 395 } | 394 } |
| 396 | 395 |
| 397 | 396 |
| 398 // A set of VM objects that are present in every constant pool. | 397 // A set of VM objects that are present in every constant pool. |
| 399 static bool IsAlwaysInConstantPool(const Object& object) { | 398 static bool IsAlwaysInConstantPool(const Object& object) { |
| 400 // TODO(zra): Evaluate putting all VM heap objects into the pool. | 399 // TODO(zra): Evaluate putting all VM heap objects into the pool. |
| 401 return (object.raw() == Object::null()) | 400 return (object.raw() == Object::null()) |
| 402 || (object.raw() == Bool::True().raw()) | 401 || (object.raw() == Bool::True().raw()) |
| 403 || (object.raw() == Bool::False().raw()); | 402 || (object.raw() == Bool::False().raw()); |
| 404 } | 403 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 434 (Isolate::Current() != Dart::vm_isolate()); | 433 (Isolate::Current() != Dart::vm_isolate()); |
| 435 } | 434 } |
| 436 | 435 |
| 437 | 436 |
| 438 void Assembler::LoadExternalLabel(Register dst, | 437 void Assembler::LoadExternalLabel(Register dst, |
| 439 const ExternalLabel* label, | 438 const ExternalLabel* label, |
| 440 Patchability patchable, | 439 Patchability patchable, |
| 441 Register pp) { | 440 Register pp) { |
| 442 const int64_t target = static_cast<int64_t>(label->address()); | 441 const int64_t target = static_cast<int64_t>(label->address()); |
| 443 if (CanLoadImmediateFromPool(target, pp)) { | 442 if (CanLoadImmediateFromPool(target, pp)) { |
| 444 const int32_t offset = | 443 const int32_t offset = ObjectPool::element_offset( |
| 445 Array::element_offset(object_pool_.FindExternalLabel(label, patchable)); | 444 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
| 446 LoadWordFromPoolOffset(dst, pp, offset); | 445 LoadWordFromPoolOffset(dst, pp, offset); |
| 447 } else { | 446 } else { |
| 448 LoadImmediate(dst, target, kNoPP); | 447 LoadImmediate(dst, target, kNoPP); |
| 449 } | 448 } |
| 450 } | 449 } |
| 451 | 450 |
| 452 | 451 |
| 453 void Assembler::LoadExternalLabelFixed(Register dst, | 452 void Assembler::LoadExternalLabelFixed(Register dst, |
| 454 const ExternalLabel* label, | 453 const ExternalLabel* label, |
| 455 Patchability patchable, | 454 Patchability patchable, |
| 456 Register pp) { | 455 Register pp) { |
| 457 const int32_t offset = | 456 const int32_t offset = ObjectPool::element_offset( |
| 458 Array::element_offset(object_pool_.FindExternalLabel(label, patchable)); | 457 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
| 459 LoadWordFromPoolOffsetFixed(dst, pp, offset); | 458 LoadWordFromPoolOffsetFixed(dst, pp, offset); |
| 460 } | 459 } |
| 461 | 460 |
| 462 | 461 |
| 463 void Assembler::LoadIsolate(Register dst, Register pp) { | 462 void Assembler::LoadIsolate(Register dst, Register pp) { |
| 464 ldr(dst, Address(THR, Thread::isolate_offset())); | 463 ldr(dst, Address(THR, Thread::isolate_offset())); |
| 465 } | 464 } |
| 466 | 465 |
| 467 | 466 |
| 468 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { | 467 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { |
| 469 if (CanLoadObjectFromPool(object)) { | 468 if (CanLoadObjectFromPool(object)) { |
| 470 const int32_t offset = | 469 const int32_t offset = |
| 471 Array::element_offset(object_pool_.FindObject(object, kNotPatchable)); | 470 ObjectPool::element_offset(object_pool_wrapper_.FindObject(object)); |
| 472 LoadWordFromPoolOffset(dst, pp, offset); | 471 LoadWordFromPoolOffset(dst, pp, offset); |
| 473 } else { | 472 } else { |
| 474 ASSERT((Isolate::Current() == Dart::vm_isolate()) || | 473 ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
| 475 object.IsSmi() || | 474 object.IsSmi() || |
| 476 object.InVMHeap()); | 475 object.InVMHeap()); |
| 477 LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); | 476 LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); |
| 478 } | 477 } |
| 479 } | 478 } |
| 480 | 479 |
| 481 | 480 |
| 482 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { | 481 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { |
| 483 if (CanLoadObjectFromPool(object)) { | 482 if (CanLoadObjectFromPool(object)) { |
| 484 LoadObject(TMP, object, pp); | 483 LoadObject(TMP, object, pp); |
| 485 CompareRegisters(reg, TMP); | 484 CompareRegisters(reg, TMP); |
| 486 } else { | 485 } else { |
| 487 CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()), pp); | 486 CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()), pp); |
| 488 } | 487 } |
| 489 } | 488 } |
| 490 | 489 |
| 491 | 490 |
| 492 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { | 491 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { |
| 493 if ((pp != kNoPP) && | 492 if ((pp != kNoPP) && |
| 494 (Isolate::Current() != Dart::vm_isolate()) && | 493 (Isolate::Current() != Dart::vm_isolate()) && |
| 495 allow_constant_pool()) { | 494 allow_constant_pool()) { |
| 496 int64_t val_smi_tag = imm & kSmiTagMask; | 495 int64_t val_smi_tag = imm & kSmiTagMask; |
| 497 imm &= ~kSmiTagMask; // Mask off the tag bits. | 496 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 498 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 497 const int32_t offset = ObjectPool::element_offset(FindImmediate(imm)); |
| 499 LoadWordFromPoolOffset(reg, pp, offset); | 498 LoadWordFromPoolOffset(reg, pp, offset); |
| 500 if (val_smi_tag != 0) { | 499 if (val_smi_tag != 0) { |
| 501 // Add back the tag bits. | 500 // Add back the tag bits. |
| 502 orri(reg, reg, Immediate(val_smi_tag)); | 501 orri(reg, reg, Immediate(val_smi_tag)); |
| 503 } | 502 } |
| 504 } else { | 503 } else { |
| 505 // TODO(zra): Since this sequence only needs to be decodable, it can be | 504 // TODO(zra): Since this sequence only needs to be decodable, it can be |
| 506 // of variable length. | 505 // of variable length. |
| 507 LoadImmediateFixed(reg, imm); | 506 LoadImmediateFixed(reg, imm); |
| 508 } | 507 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 524 | 523 |
| 525 | 524 |
| 526 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { | 525 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { |
| 527 Comment("LoadImmediate"); | 526 Comment("LoadImmediate"); |
| 528 if (CanLoadImmediateFromPool(imm, pp)) { | 527 if (CanLoadImmediateFromPool(imm, pp)) { |
| 529 // It's a 64-bit constant and we're not in the VM isolate, so load from | 528 // It's a 64-bit constant and we're not in the VM isolate, so load from |
| 530 // object pool. | 529 // object pool. |
| 531 // Save the bits that must be masked-off for the SmiTag | 530 // Save the bits that must be masked-off for the SmiTag |
| 532 int64_t val_smi_tag = imm & kSmiTagMask; | 531 int64_t val_smi_tag = imm & kSmiTagMask; |
| 533 imm &= ~kSmiTagMask; // Mask off the tag bits. | 532 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 534 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 533 const int32_t offset = ObjectPool::element_offset(FindImmediate(imm)); |
| 535 LoadWordFromPoolOffset(reg, pp, offset); | 534 LoadWordFromPoolOffset(reg, pp, offset); |
| 536 if (val_smi_tag != 0) { | 535 if (val_smi_tag != 0) { |
| 537 // Add back the tag bits. | 536 // Add back the tag bits. |
| 538 orri(reg, reg, Immediate(val_smi_tag)); | 537 orri(reg, reg, Immediate(val_smi_tag)); |
| 539 } | 538 } |
| 540 } else { | 539 } else { |
| 541 // 0. Is it 0? | 540 // 0. Is it 0? |
| 542 if (imm == 0) { | 541 if (imm == 0) { |
| 543 movz(reg, Immediate(0), 0); | 542 movz(reg, Immediate(0), 0); |
| 544 return; | 543 return; |
| (...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 add(base, array, Operand(index, LSL, shift)); | 1461 add(base, array, Operand(index, LSL, shift)); |
| 1463 } | 1462 } |
| 1464 const OperandSize size = Address::OperandSizeFor(cid); | 1463 const OperandSize size = Address::OperandSizeFor(cid); |
| 1465 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); | 1464 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); |
| 1466 return Address(base, offset, Address::Offset, size); | 1465 return Address(base, offset, Address::Offset, size); |
| 1467 } | 1466 } |
| 1468 | 1467 |
| 1469 } // namespace dart | 1468 } // namespace dart |
| 1470 | 1469 |
| 1471 #endif // defined TARGET_ARCH_ARM64 | 1470 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |