Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(744)

Unified Diff: runtime/vm/assembler_arm64.cc

Issue 239303008: Adds object pool, LoadImmediate, and LoadObject to ARM64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
+ } 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 initialized = false;
+ if (h0 != 0) {
+ movz(reg, h0, 0);
+ initialized = true;
+ }
+ if (h1 != 0) {
+ if (initialized) {
+ movk(reg, h1, 1);
+ } else {
+ movz(reg, h1, 1);
+ initialized = true;
+ }
+ }
+ if (h2 != 0) {
+ if (initialized) {
+ movk(reg, h2, 2);
+ } else {
+ movz(reg, h2, 2);
+ initialized = true;
+ }
+ }
+ if (h3 != 0) {
+ if (initialized) {
+ movk(reg, h3, 3);
+ } else {
+ movz(reg, h3, 3);
+ }
+ }
+ }
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_ARM64
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698