Chromium Code Reviews| Index: runtime/vm/assembler_arm64.cc |
| =================================================================== |
| --- runtime/vm/assembler_arm64.cc (revision 35070) |
| +++ runtime/vm/assembler_arm64.cc (working copy) |
| @@ -24,6 +24,34 @@ |
| DECLARE_FLAG(bool, inline_alloc); |
| +Assembler::Assembler(bool use_far_branches) |
| + : buffer_(), |
| + object_pool_(GrowableObjectArray::Handle()), |
| + patchable_pool_entries_(), |
| + prologue_offset_(-1), |
| + use_far_branches_(use_far_branches), |
| + comments_() { |
| + if (Isolate::Current() != Dart::vm_isolate()) { |
| + object_pool_ = GrowableObjectArray::New(Heap::kOld); |
| + |
| + // These objects and labels need to be accessible through every pool-pointer |
| + // at the same index. |
| + object_pool_.Add(Object::null_object(), Heap::kOld); |
| + patchable_pool_entries_.Add(kNotPatchable); |
| + // Not adding Object::null() to the index table. It is at index 0 in the |
| + // object pool, but the HashMap uses 0 to indicate not found. |
| + |
| + object_pool_.Add(Bool::True(), Heap::kOld); |
| + patchable_pool_entries_.Add(kNotPatchable); |
| + object_pool_index_table_.Insert(ObjIndexPair(Bool::True().raw(), 1)); |
| + |
| + object_pool_.Add(Bool::False(), Heap::kOld); |
| + patchable_pool_entries_.Add(kNotPatchable); |
| + object_pool_index_table_.Insert(ObjIndexPair(Bool::False().raw(), 2)); |
| + } |
| +} |
| + |
| + |
| void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
| ASSERT(Utils::IsAligned(data, 4)); |
| ASSERT(Utils::IsAligned(length, 4)); |
| @@ -126,7 +154,7 @@ |
| // by the corresponding fields in the logical instruction. |
| // If it can't be encoded, the function returns false, and the operand is |
| // undefined. |
| -bool Assembler::IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op) { |
| +bool Operand::IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op) { |
| ASSERT(imm_op != NULL); |
| ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits)); |
| ASSERT((width == kXRegSizeInBits) || (value <= 0xffffffffUL)); |
| @@ -220,6 +248,193 @@ |
| } |
| } |
| + |
| +void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, |
| + uint32_t offset) { |
| + ASSERT(dst != pp); |
| + if (Address::CanHoldOffset(offset)) { |
| + ldr(dst, Address(pp, offset)); |
| + } else { |
| + const uint16_t offset_low = Utils::Low16Bits(offset); |
| + const uint16_t offset_high = Utils::High16Bits(offset); |
| + movz(dst, offset_low, 0); |
| + if (offset_high != 0) { |
| + movk(dst, offset_high, 1); |
| + } |
| + ldr(dst, Address(pp, dst)); |
| + } |
| +} |
| + |
| + |
| +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()); |
| + ASSERT(!object_pool_.IsNull()); |
| + |
| + // If the object is not patchable, check if we've already got it in the |
| + // object pool. |
| + if (patchable == kNotPatchable) { |
| + // Special case for Object::null(), which is always at object_pool_ index 0 |
| + // because Lookup() below returns 0 when the object is not mapped in the |
| + // table. |
| + if (obj.raw() == Object::null()) { |
| + return 0; |
| + } |
| + |
| + intptr_t idx = object_pool_index_table_.Lookup(obj.raw()); |
| + if (idx != 0) { |
| + ASSERT(patchable_pool_entries_[idx] == kNotPatchable); |
| + return idx; |
| + } |
| + } |
| + |
| + object_pool_.Add(obj, Heap::kOld); |
| + patchable_pool_entries_.Add(patchable); |
| + if (patchable == kNotPatchable) { |
| + // The object isn't patchable. Record the index for fast lookup. |
| + object_pool_index_table_.Insert( |
| + ObjIndexPair(obj.raw(), object_pool_.Length() - 1)); |
| + } |
| + return object_pool_.Length() - 1; |
| +} |
| + |
| + |
| +intptr_t Assembler::FindImmediate(int64_t imm) { |
| + ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| + ASSERT(!object_pool_.IsNull()); |
| + const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); |
| + return FindObject(smi, kNotPatchable); |
| +} |
| + |
| + |
| +bool Assembler::CanLoadObjectFromPool(const Object& object) { |
| + // TODO(zra, kmillikin): Also load other large immediates from the object |
| + // pool |
| + if (object.IsSmi()) { |
| + // If the raw smi does not fit into a 32-bit signed int, then we'll keep |
| + // the raw value in the object pool. |
| + return !Utils::IsInt(32, reinterpret_cast<int64_t>(object.raw())); |
| + } |
| + ASSERT(object.IsNotTemporaryScopedHandle()); |
| + ASSERT(object.IsOld()); |
| + return (Isolate::Current() != Dart::vm_isolate()) && |
| + // Not in the VMHeap, OR is one of the VMHeap objects we put in every |
| + // object pool. |
| + // TODO(zra): Evaluate putting all VM heap objects into the pool. |
| + (!object.InVMHeap() || (object.raw() == Object::null()) || |
| + (object.raw() == Bool::True().raw()) || |
| + (object.raw() == Bool::False().raw())); |
| +} |
| + |
| + |
| +bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) { |
| + return !Utils::IsInt(32, imm) && |
| + (pp != kNoRegister) && |
| + (Isolate::Current() != Dart::vm_isolate()); |
| +} |
| + |
| + |
| +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); |
| + } else { |
| + ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
| + object.IsSmi() || |
| + object.InVMHeap()); |
| + LoadImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp); |
| + } |
| +} |
| + |
| + |
| +void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { |
| + Comment("LoadImmediate"); |
| + if (CanLoadImmediateFromPool(imm, pp)) { |
| + // It's a 64-bit constant and we're not in the VM isolate, so load from |
| + // object pool. |
| + // Save the bits that must be masked-off for the SmiTag |
| + 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); |
| + if (val_smi_tag != 0) { |
| + // Add back the tag bits. |
| + orri(reg, reg, val_smi_tag); |
| + } |
| + } else { |
| + // 1. Can we use one orri operation? |
| + Operand op; |
| + Operand::OperandType ot; |
| + ot = Operand::CanHold(imm, kXRegSizeInBits, &op); |
| + if (ot == Operand::BitfieldImm) { |
| + orri(reg, ZR, imm); |
| + return; |
| + } |
| + |
| + // 2. Fall back on movz, movk, movn. |
| + 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); |
| + |
| + // Special case for w1 == 0xffffffff |
| + if (w1 == 0xffffffff) { |
| + if (h1 == 0xffff) { |
| + movn(reg, ~h0, 0); |
|
regis
2014/04/15 23:37:04
OK, I see now why you changed the formal type to u
|
| + } else { |
| + movn(reg, ~h1, 1); |
| + movk(reg, h0, 0); |
| + } |
| + return; |
| + } |
| + |
| + // Special case for h3 == 0xffff |
| + if (h3 == 0xffff) { |
| + // We know h2 != 0xffff. |
| + movn(reg, ~h2, 2); |
| + if (h1 != 0xffff) { |
| + movk(reg, h1, 1); |
| + } |
| + if (h0 != 0xffff) { |
| + movk(reg, h0, 0); |
| + } |
| + return; |
| + } |
| + |
| + bool initizlized = false; |
|
regis
2014/04/15 23:37:04
initialized, here and 6 mores times below. Getting
zra
2014/04/16 15:48:16
The z and a are close together =)
|
| + if (h0 != 0) { |
| + movz(reg, h0, 0); |
| + initizlized = true; |
| + } |
| + if (h1 != 0) { |
| + if (initizlized) { |
| + movk(reg, h1, 1); |
| + } else { |
| + movz(reg, h1, 1); |
| + initizlized = true; |
| + } |
| + } |
| + if (h2 != 0) { |
| + if (initizlized) { |
| + movk(reg, h2, 2); |
| + } else { |
| + movz(reg, h2, 2); |
| + initizlized = true; |
| + } |
| + } |
| + if (h3 != 0) { |
| + if (initizlized) { |
| + movk(reg, h3, 3); |
| + } else { |
| + movz(reg, h3, 3); |
| + } |
| + } |
| + } |
| +} |
| + |
| } // namespace dart |
| #endif // defined TARGET_ARCH_ARM64 |