| Index: runtime/vm/assembler_arm64.cc
|
| ===================================================================
|
| --- runtime/vm/assembler_arm64.cc (revision 35127)
|
| +++ runtime/vm/assembler_arm64.cc (working copy)
|
| @@ -274,6 +274,28 @@
|
| }
|
|
|
|
|
| +intptr_t Assembler::FindExternalLabel(const ExternalLabel* label,
|
| + Patchability patchable) {
|
| + // The object pool cannot be used in the vm isolate.
|
| + ASSERT(Isolate::Current() != Dart::vm_isolate());
|
| + ASSERT(!object_pool_.IsNull());
|
| + const uword address = label->address();
|
| + ASSERT(Utils::IsAligned(address, 4));
|
| + // The address is stored in the object array as a RawSmi.
|
| + const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address));
|
| + if (patchable == kNotPatchable) {
|
| + // If the call site is not patchable, we can try to re-use an existing
|
| + // entry.
|
| + return FindObject(smi, kNotPatchable);
|
| + }
|
| + // If the call is patchable, do not reuse an existing entry since each
|
| + // reference may be patched independently.
|
| + object_pool_.Add(smi, Heap::kOld);
|
| + patchable_pool_entries_.Add(patchable);
|
| + return object_pool_.Length() - 1;
|
| +}
|
| +
|
| +
|
| intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) {
|
| // The object pool cannot be used in the vm isolate.
|
| ASSERT(Isolate::Current() != Dart::vm_isolate());
|
| @@ -342,20 +364,62 @@
|
| }
|
|
|
|
|
| +void Assembler::LoadExternalLabel(Register dst,
|
| + const ExternalLabel* label,
|
| + Patchability patchable,
|
| + Register pp) {
|
| + const int32_t offset =
|
| + Array::element_offset(FindExternalLabel(label, patchable));
|
| + LoadWordFromPoolOffset(dst, pp, offset);
|
| +}
|
| +
|
| +
|
| void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
|
| if (CanLoadObjectFromPool(object)) {
|
| const int32_t offset =
|
| Array::element_offset(FindObject(object, kNotPatchable));
|
| - LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
|
| + LoadWordFromPoolOffset(dst, pp, offset);
|
| } else {
|
| ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
|
| object.IsSmi() ||
|
| object.InVMHeap());
|
| - LoadImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
|
| + LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
|
| }
|
| }
|
|
|
|
|
| +void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) {
|
| + if ((pp != kNoRegister) && (Isolate::Current() != Dart::vm_isolate())) {
|
| + int64_t val_smi_tag = imm & kSmiTagMask;
|
| + imm &= ~kSmiTagMask; // Mask off the tag bits.
|
| + const int32_t offset = Array::element_offset(FindImmediate(imm));
|
| + LoadWordFromPoolOffset(reg, pp, offset);
|
| + if (val_smi_tag != 0) {
|
| + // Add back the tag bits.
|
| + orri(reg, reg, val_smi_tag);
|
| + }
|
| + } else {
|
| + // TODO(zra): Since this sequence only needs to be decodable, it can be
|
| + // of variable length.
|
| + LoadPatchableImmediate(reg, imm);
|
| + }
|
| +}
|
| +
|
| +
|
| +void Assembler::LoadPatchableImmediate(Register reg, int64_t imm) {
|
| + const uint32_t w0 = Utils::Low32Bits(imm);
|
| + const uint32_t w1 = Utils::High32Bits(imm);
|
| + const uint16_t h0 = Utils::Low16Bits(w0);
|
| + const uint16_t h1 = Utils::High16Bits(w0);
|
| + const uint16_t h2 = Utils::Low16Bits(w1);
|
| + const uint16_t h3 = Utils::High16Bits(w1);
|
| + movz(reg, h0, 0);
|
| + movk(reg, h1, 1);
|
| + movk(reg, h2, 2);
|
| + movk(reg, h3, 3);
|
| +}
|
| +
|
| +
|
| void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) {
|
| Comment("LoadImmediate");
|
| if (CanLoadImmediateFromPool(imm, pp)) {
|
| @@ -365,7 +429,7 @@
|
| int64_t val_smi_tag = imm & kSmiTagMask;
|
| imm &= ~kSmiTagMask; // Mask off the tag bits.
|
| const int32_t offset = Array::element_offset(FindImmediate(imm));
|
| - LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag);
|
| + LoadWordFromPoolOffset(reg, pp, offset);
|
| if (val_smi_tag != 0) {
|
| // Add back the tag bits.
|
| orri(reg, reg, val_smi_tag);
|
|
|