| Index: runtime/vm/assembler_arm64.cc
|
| diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
|
| index 4fb6be32b9f143c9905f128f12435026a1459d73..2422cb4572d61b39245097c4ae2ea05d8249bd76 100644
|
| --- a/runtime/vm/assembler_arm64.cc
|
| +++ b/runtime/vm/assembler_arm64.cc
|
| @@ -30,7 +30,7 @@ Assembler::Assembler(bool use_far_branches)
|
| prologue_offset_(-1),
|
| use_far_branches_(use_far_branches),
|
| comments_(),
|
| - constant_pool_allowed_(true) {
|
| + constant_pool_allowed_(false) {
|
| }
|
|
|
|
|
| @@ -302,12 +302,12 @@ bool Operand::IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op) {
|
| }
|
|
|
|
|
| -void Assembler::LoadPoolPointer(Register pp) {
|
| +void Assembler::LoadPoolPointer() {
|
| const intptr_t object_pool_pc_dist =
|
| Instructions::HeaderSize() - Instructions::object_pool_offset() +
|
| CodeSize();
|
| // PP <- Read(PC - object_pool_pc_dist).
|
| - ldr(pp, Address::PC(-object_pool_pc_dist));
|
| + ldr(PP, Address::PC(-object_pool_pc_dist));
|
|
|
| // When in the PP register, the pool pointer is untagged. When we
|
| // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP
|
| @@ -315,22 +315,23 @@ void Assembler::LoadPoolPointer(Register pp) {
|
| // object pool only one instruction for the first 4096 entries. Otherwise,
|
| // because the offset wouldn't be aligned, it would be only one instruction
|
| // for the first 64 entries.
|
| - sub(pp, pp, Operand(kHeapObjectTag));
|
| + sub(PP, PP, Operand(kHeapObjectTag));
|
| + set_constant_pool_allowed(true);
|
| }
|
|
|
|
|
| -void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
|
| - uint32_t offset) {
|
| - ASSERT(dst != pp);
|
| +void Assembler::LoadWordFromPoolOffset(Register dst, uint32_t offset) {
|
| + ASSERT(constant_pool_allowed());
|
| + ASSERT(dst != PP);
|
| Operand op;
|
| const uint32_t upper20 = offset & 0xfffff000;
|
| if (Address::CanHoldOffset(offset)) {
|
| - ldr(dst, Address(pp, offset));
|
| + ldr(dst, Address(PP, offset));
|
| } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) ==
|
| Operand::Immediate) {
|
| const uint32_t lower12 = offset & 0x00000fff;
|
| ASSERT(Address::CanHoldOffset(lower12));
|
| - add(dst, pp, op);
|
| + add(dst, PP, op);
|
| ldr(dst, Address(dst, lower12));
|
| } else {
|
| const uint16_t offset_low = Utils::Low16Bits(offset);
|
| @@ -339,14 +340,14 @@ void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
|
| if (offset_high != 0) {
|
| movk(dst, Immediate(offset_high), 1);
|
| }
|
| - ldr(dst, Address(pp, dst));
|
| + ldr(dst, Address(PP, dst));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadWordFromPoolOffsetFixed(Register dst, Register pp,
|
| - uint32_t offset) {
|
| - ASSERT(dst != pp);
|
| +void Assembler::LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset) {
|
| + ASSERT(constant_pool_allowed());
|
| + ASSERT(dst != PP);
|
| Operand op;
|
| const uint32_t upper20 = offset & 0xfffff000;
|
| const uint32_t lower12 = offset & 0x00000fff;
|
| @@ -354,7 +355,7 @@ void Assembler::LoadWordFromPoolOffsetFixed(Register dst, Register pp,
|
| Operand::CanHold(upper20, kXRegSizeInBits, &op);
|
| ASSERT(ot == Operand::Immediate);
|
| ASSERT(Address::CanHoldOffset(lower12));
|
| - add(dst, pp, op);
|
| + add(dst, PP, op);
|
| ldr(dst, Address(dst, lower12));
|
| }
|
|
|
| @@ -383,36 +384,24 @@ bool Assembler::CanLoadFromObjectPool(const Object& object) const {
|
| }
|
|
|
|
|
| -bool Assembler::CanLoadImmediateFromPool(int64_t imm, Register pp) {
|
| - if (!constant_pool_allowed()) {
|
| - return false;
|
| - }
|
| - return !Utils::IsInt(32, imm) && (pp != kNoPP);
|
| -}
|
| -
|
| -
|
| -void Assembler::LoadExternalLabel(Register dst,
|
| - const ExternalLabel* label,
|
| - Patchability patchable,
|
| - Register pp) {
|
| - const int64_t target = static_cast<int64_t>(label->address());
|
| - if (CanLoadImmediateFromPool(target, pp)) {
|
| +void Assembler::LoadExternalLabel(Register dst, const ExternalLabel* label) {
|
| + if (constant_pool_allowed()) {
|
| const int32_t offset = ObjectPool::element_offset(
|
| - object_pool_wrapper_.FindExternalLabel(label, patchable));
|
| - LoadWordFromPoolOffset(dst, pp, offset);
|
| + object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
|
| + LoadWordFromPoolOffset(dst, offset);
|
| } else {
|
| - LoadImmediate(dst, target, kNoPP);
|
| + const int64_t target = static_cast<int64_t>(label->address());
|
| + LoadImmediate(dst, target);
|
| }
|
| }
|
|
|
|
|
| void Assembler::LoadExternalLabelFixed(Register dst,
|
| const ExternalLabel* label,
|
| - Patchability patchable,
|
| - Register pp) {
|
| + Patchability patchable) {
|
| const int32_t offset = ObjectPool::element_offset(
|
| object_pool_wrapper_.FindExternalLabel(label, patchable));
|
| - LoadWordFromPoolOffsetFixed(dst, pp, offset);
|
| + LoadWordFromPoolOffsetFixed(dst, offset);
|
| }
|
|
|
|
|
| @@ -423,7 +412,6 @@ void Assembler::LoadIsolate(Register dst) {
|
|
|
| void Assembler::LoadObjectHelper(Register dst,
|
| const Object& object,
|
| - Register pp,
|
| bool is_unique) {
|
| if (Thread::CanLoadFromThread(object)) {
|
| ldr(dst, Address(THR, Thread::OffsetFromThread(object)));
|
| @@ -431,43 +419,41 @@ void Assembler::LoadObjectHelper(Register dst,
|
| const int32_t offset = ObjectPool::element_offset(
|
| is_unique ? object_pool_wrapper_.AddObject(object)
|
| : object_pool_wrapper_.FindObject(object));
|
| - LoadWordFromPoolOffset(dst, pp, offset);
|
| + LoadWordFromPoolOffset(dst, offset);
|
| } else {
|
| ASSERT(object.IsSmi() || object.InVMHeap());
|
| - LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
|
| + LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
|
| - LoadObjectHelper(dst, object, pp, false);
|
| +void Assembler::LoadObject(Register dst, const Object& object) {
|
| + LoadObjectHelper(dst, object, false);
|
| }
|
|
|
|
|
| -void Assembler::LoadUniqueObject(Register dst,
|
| - const Object& object,
|
| - Register pp) {
|
| - LoadObjectHelper(dst, object, pp, true);
|
| +void Assembler::LoadUniqueObject(Register dst, const Object& object) {
|
| + LoadObjectHelper(dst, object, true);
|
| }
|
|
|
|
|
| -void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
|
| +void Assembler::CompareObject(Register reg, const Object& object) {
|
| if (Thread::CanLoadFromThread(object)) {
|
| ldr(TMP, Address(THR, Thread::OffsetFromThread(object)));
|
| CompareRegisters(reg, TMP);
|
| } else if (CanLoadFromObjectPool(object)) {
|
| - LoadObject(TMP, object, pp);
|
| + LoadObject(TMP, object);
|
| CompareRegisters(reg, TMP);
|
| } else {
|
| - CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()), pp);
|
| + CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) {
|
| - if ((pp != kNoPP) && constant_pool_allowed()) {
|
| +void Assembler::LoadDecodableImmediate(Register reg, int64_t imm) {
|
| + if (constant_pool_allowed()) {
|
| const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
|
| - LoadWordFromPoolOffset(reg, pp, offset);
|
| + LoadWordFromPoolOffset(reg, offset);
|
| } else {
|
| // TODO(zra): Since this sequence only needs to be decodable, it can be
|
| // of variable length.
|
| @@ -490,102 +476,103 @@ void Assembler::LoadImmediateFixed(Register reg, int64_t imm) {
|
| }
|
|
|
|
|
| -void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) {
|
| +void Assembler::LoadImmediate(Register reg, int64_t imm) {
|
| Comment("LoadImmediate");
|
| - if (CanLoadImmediateFromPool(imm, pp)) {
|
| - const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
|
| - LoadWordFromPoolOffset(reg, pp, offset);
|
| - } else {
|
| - // 0. Is it 0?
|
| - if (imm == 0) {
|
| - movz(reg, Immediate(0), 0);
|
| - return;
|
| - }
|
| + // Is it 0?
|
| + if (imm == 0) {
|
| + movz(reg, Immediate(0), 0);
|
| + return;
|
| + }
|
|
|
| - // 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, Immediate(imm));
|
| - return;
|
| - }
|
| + // Can we use one orri operation?
|
| + Operand op;
|
| + Operand::OperandType ot;
|
| + ot = Operand::CanHold(imm, kXRegSizeInBits, &op);
|
| + if (ot == Operand::BitfieldImm) {
|
| + orri(reg, ZR, Immediate(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, Immediate(~h0), 0);
|
| - } else {
|
| - movn(reg, Immediate(~h1), 1);
|
| - movk(reg, Immediate(h0), 0);
|
| - }
|
| - return;
|
| + // We may 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, Immediate(~h0), 0);
|
| + } else {
|
| + movn(reg, Immediate(~h1), 1);
|
| + movk(reg, Immediate(h0), 0);
|
| }
|
| + return;
|
| + }
|
|
|
| - // Special case for h3 == 0xffff
|
| - if (h3 == 0xffff) {
|
| - // We know h2 != 0xffff.
|
| - movn(reg, Immediate(~h2), 2);
|
| - if (h1 != 0xffff) {
|
| - movk(reg, Immediate(h1), 1);
|
| - }
|
| - if (h0 != 0xffff) {
|
| - movk(reg, Immediate(h0), 0);
|
| - }
|
| - return;
|
| + // Special case for h3 == 0xffff
|
| + if (h3 == 0xffff) {
|
| + // We know h2 != 0xffff.
|
| + movn(reg, Immediate(~h2), 2);
|
| + if (h1 != 0xffff) {
|
| + movk(reg, Immediate(h1), 1);
|
| }
|
| + if (h0 != 0xffff) {
|
| + movk(reg, Immediate(h0), 0);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + // Use constant pool if allowed, unless we can load imm with 2 instructions.
|
| + if ((w1 != 0) && constant_pool_allowed()) {
|
| + const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
|
| + LoadWordFromPoolOffset(reg, offset);
|
| + return;
|
| + }
|
|
|
| - bool initialized = false;
|
| - if (h0 != 0) {
|
| - movz(reg, Immediate(h0), 0);
|
| + bool initialized = false;
|
| + if (h0 != 0) {
|
| + movz(reg, Immediate(h0), 0);
|
| + initialized = true;
|
| + }
|
| + if (h1 != 0) {
|
| + if (initialized) {
|
| + movk(reg, Immediate(h1), 1);
|
| + } else {
|
| + movz(reg, Immediate(h1), 1);
|
| initialized = true;
|
| }
|
| - if (h1 != 0) {
|
| - if (initialized) {
|
| - movk(reg, Immediate(h1), 1);
|
| - } else {
|
| - movz(reg, Immediate(h1), 1);
|
| - initialized = true;
|
| - }
|
| - }
|
| - if (h2 != 0) {
|
| - if (initialized) {
|
| - movk(reg, Immediate(h2), 2);
|
| - } else {
|
| - movz(reg, Immediate(h2), 2);
|
| - initialized = true;
|
| - }
|
| + }
|
| + if (h2 != 0) {
|
| + if (initialized) {
|
| + movk(reg, Immediate(h2), 2);
|
| + } else {
|
| + movz(reg, Immediate(h2), 2);
|
| + initialized = true;
|
| }
|
| - if (h3 != 0) {
|
| - if (initialized) {
|
| - movk(reg, Immediate(h3), 3);
|
| - } else {
|
| - movz(reg, Immediate(h3), 3);
|
| - }
|
| + }
|
| + if (h3 != 0) {
|
| + if (initialized) {
|
| + movk(reg, Immediate(h3), 3);
|
| + } else {
|
| + movz(reg, Immediate(h3), 3);
|
| }
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadDImmediate(VRegister vd, double immd, Register pp) {
|
| +void Assembler::LoadDImmediate(VRegister vd, double immd) {
|
| if (!fmovdi(vd, immd)) {
|
| int64_t imm = bit_cast<int64_t, double>(immd);
|
| - LoadImmediate(TMP, imm, pp);
|
| + LoadImmediate(TMP, imm);
|
| fmovdr(vd, TMP);
|
| }
|
| }
|
|
|
|
|
| -void Assembler::AddImmediate(
|
| - Register dest, Register rn, int64_t imm, Register pp) {
|
| +void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
|
| Operand op;
|
| if (imm == 0) {
|
| if (dest != rn) {
|
| @@ -601,14 +588,13 @@ void Assembler::AddImmediate(
|
| } else {
|
| // TODO(zra): Try adding top 12 bits, then bottom 12 bits.
|
| ASSERT(rn != TMP2);
|
| - LoadImmediate(TMP2, imm, pp);
|
| + LoadImmediate(TMP2, imm);
|
| add(dest, rn, Operand(TMP2));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::AddImmediateSetFlags(
|
| - Register dest, Register rn, int64_t imm, Register pp) {
|
| +void Assembler::AddImmediateSetFlags(Register dest, Register rn, int64_t imm) {
|
| Operand op;
|
| if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
|
| // Handles imm == kMinInt64.
|
| @@ -620,14 +606,13 @@ void Assembler::AddImmediateSetFlags(
|
| } else {
|
| // TODO(zra): Try adding top 12 bits, then bottom 12 bits.
|
| ASSERT(rn != TMP2);
|
| - LoadImmediate(TMP2, imm, pp);
|
| + LoadImmediate(TMP2, imm);
|
| adds(dest, rn, Operand(TMP2));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::SubImmediateSetFlags(
|
| - Register dest, Register rn, int64_t imm, Register pp) {
|
| +void Assembler::SubImmediateSetFlags(Register dest, Register rn, int64_t imm) {
|
| Operand op;
|
| if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
|
| // Handles imm == kMinInt64.
|
| @@ -639,60 +624,57 @@ void Assembler::SubImmediateSetFlags(
|
| } else {
|
| // TODO(zra): Try subtracting top 12 bits, then bottom 12 bits.
|
| ASSERT(rn != TMP2);
|
| - LoadImmediate(TMP2, imm, pp);
|
| + LoadImmediate(TMP2, imm);
|
| subs(dest, rn, Operand(TMP2));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::AndImmediate(
|
| - Register rd, Register rn, int64_t imm, Register pp) {
|
| +void Assembler::AndImmediate(Register rd, Register rn, int64_t imm) {
|
| Operand imm_op;
|
| if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
|
| andi(rd, rn, Immediate(imm));
|
| } else {
|
| - LoadImmediate(TMP, imm, pp);
|
| + LoadImmediate(TMP, imm);
|
| and_(rd, rn, Operand(TMP));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::OrImmediate(
|
| - Register rd, Register rn, int64_t imm, Register pp) {
|
| +void Assembler::OrImmediate(Register rd, Register rn, int64_t imm) {
|
| Operand imm_op;
|
| if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
|
| orri(rd, rn, Immediate(imm));
|
| } else {
|
| - LoadImmediate(TMP, imm, pp);
|
| + LoadImmediate(TMP, imm);
|
| orr(rd, rn, Operand(TMP));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::XorImmediate(
|
| - Register rd, Register rn, int64_t imm, Register pp) {
|
| +void Assembler::XorImmediate(Register rd, Register rn, int64_t imm) {
|
| Operand imm_op;
|
| if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
|
| eori(rd, rn, Immediate(imm));
|
| } else {
|
| - LoadImmediate(TMP, imm, pp);
|
| + LoadImmediate(TMP, imm);
|
| eor(rd, rn, Operand(TMP));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::TestImmediate(Register rn, int64_t imm, Register pp) {
|
| +void Assembler::TestImmediate(Register rn, int64_t imm) {
|
| Operand imm_op;
|
| if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) {
|
| tsti(rn, Immediate(imm));
|
| } else {
|
| - LoadImmediate(TMP, imm, pp);
|
| + LoadImmediate(TMP, imm);
|
| tst(rn, Operand(TMP));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::CompareImmediate(Register rn, int64_t imm, Register pp) {
|
| +void Assembler::CompareImmediate(Register rn, int64_t imm) {
|
| Operand op;
|
| if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
|
| cmp(rn, op);
|
| @@ -701,80 +683,76 @@ void Assembler::CompareImmediate(Register rn, int64_t imm, Register pp) {
|
| cmn(rn, op);
|
| } else {
|
| ASSERT(rn != TMP2);
|
| - LoadImmediate(TMP2, imm, pp);
|
| + LoadImmediate(TMP2, imm);
|
| cmp(rn, Operand(TMP2));
|
| }
|
| }
|
|
|
|
|
| void Assembler::LoadFromOffset(
|
| - Register dest, Register base, int32_t offset, Register pp, OperandSize sz) {
|
| + Register dest, Register base, int32_t offset, OperandSize sz) {
|
| if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
|
| ldr(dest, Address(base, offset, Address::Offset, sz), sz);
|
| } else {
|
| ASSERT(base != TMP2);
|
| - AddImmediate(TMP2, base, offset, pp);
|
| + AddImmediate(TMP2, base, offset);
|
| ldr(dest, Address(TMP2), sz);
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadDFromOffset(
|
| - VRegister dest, Register base, int32_t offset, Register pp) {
|
| +void Assembler::LoadDFromOffset(VRegister dest, Register base, int32_t offset) {
|
| if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
|
| fldrd(dest, Address(base, offset, Address::Offset, kDWord));
|
| } else {
|
| ASSERT(base != TMP2);
|
| - AddImmediate(TMP2, base, offset, pp);
|
| + AddImmediate(TMP2, base, offset);
|
| fldrd(dest, Address(TMP2));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadQFromOffset(
|
| - VRegister dest, Register base, int32_t offset, Register pp) {
|
| +void Assembler::LoadQFromOffset(VRegister dest, Register base, int32_t offset) {
|
| if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
|
| fldrq(dest, Address(base, offset, Address::Offset, kQWord));
|
| } else {
|
| ASSERT(base != TMP2);
|
| - AddImmediate(TMP2, base, offset, pp);
|
| + AddImmediate(TMP2, base, offset);
|
| fldrq(dest, Address(TMP2));
|
| }
|
| }
|
|
|
|
|
| void Assembler::StoreToOffset(
|
| - Register src, Register base, int32_t offset, Register pp, OperandSize sz) {
|
| + Register src, Register base, int32_t offset, OperandSize sz) {
|
| ASSERT(base != TMP2);
|
| if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
|
| str(src, Address(base, offset, Address::Offset, sz), sz);
|
| } else {
|
| ASSERT(src != TMP2);
|
| - AddImmediate(TMP2, base, offset, pp);
|
| + AddImmediate(TMP2, base, offset);
|
| str(src, Address(TMP2), sz);
|
| }
|
| }
|
|
|
|
|
| -void Assembler::StoreDToOffset(
|
| - VRegister src, Register base, int32_t offset, Register pp) {
|
| +void Assembler::StoreDToOffset(VRegister src, Register base, int32_t offset) {
|
| if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
|
| fstrd(src, Address(base, offset, Address::Offset, kDWord));
|
| } else {
|
| ASSERT(base != TMP2);
|
| - AddImmediate(TMP2, base, offset, pp);
|
| + AddImmediate(TMP2, base, offset);
|
| fstrd(src, Address(TMP2));
|
| }
|
| }
|
|
|
|
|
| -void Assembler::StoreQToOffset(
|
| - VRegister src, Register base, int32_t offset, Register pp) {
|
| +void Assembler::StoreQToOffset(VRegister src, Register base, int32_t offset) {
|
| if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
|
| fstrq(src, Address(base, offset, Address::Offset, kQWord));
|
| } else {
|
| ASSERT(base != TMP2);
|
| - AddImmediate(TMP2, base, offset, pp);
|
| + AddImmediate(TMP2, base, offset);
|
| fstrq(src, Address(TMP2));
|
| }
|
| }
|
| @@ -848,13 +826,12 @@ void Assembler::StoreIntoObjectFilter(Register object,
|
| void Assembler::StoreIntoObjectOffset(Register object,
|
| int32_t offset,
|
| Register value,
|
| - Register pp,
|
| bool can_value_be_smi) {
|
| if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
|
| StoreIntoObject(
|
| object, FieldAddress(object, offset), value, can_value_be_smi);
|
| } else {
|
| - AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
|
| + AddImmediate(TMP, object, offset - kHeapObjectTag);
|
| StoreIntoObject(object, Address(TMP), value, can_value_be_smi);
|
| }
|
| }
|
| @@ -908,12 +885,11 @@ void Assembler::StoreIntoObjectNoBarrier(Register object,
|
|
|
| void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
|
| int32_t offset,
|
| - Register value,
|
| - Register pp) {
|
| + Register value) {
|
| if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
|
| StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
|
| } else {
|
| - AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
|
| + AddImmediate(TMP, object, offset - kHeapObjectTag);
|
| StoreIntoObjectNoBarrier(object, Address(TMP), value);
|
| }
|
| }
|
| @@ -925,71 +901,69 @@ void Assembler::StoreIntoObjectNoBarrier(Register object,
|
| ASSERT(value.IsSmi() || value.InVMHeap() ||
|
| (value.IsOld() && value.IsNotTemporaryScopedHandle()));
|
| // No store buffer update.
|
| - LoadObject(TMP2, value, PP);
|
| + LoadObject(TMP2, value);
|
| str(TMP2, dest);
|
| }
|
|
|
|
|
| void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
|
| int32_t offset,
|
| - const Object& value,
|
| - Register pp) {
|
| + const Object& value) {
|
| if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
|
| StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
|
| } else {
|
| - AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
|
| + AddImmediate(TMP, object, offset - kHeapObjectTag);
|
| StoreIntoObjectNoBarrier(object, Address(TMP), value);
|
| }
|
| }
|
|
|
|
|
| -void Assembler::LoadClassId(Register result, Register object, Register pp) {
|
| +void Assembler::LoadClassId(Register result, Register object) {
|
| ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32);
|
| ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32);
|
| const intptr_t class_id_offset = Object::tags_offset() +
|
| RawObject::kClassIdTagPos / kBitsPerByte;
|
| - LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, pp,
|
| + LoadFromOffset(result, object, class_id_offset - kHeapObjectTag,
|
| kUnsignedWord);
|
| }
|
|
|
|
|
| -void Assembler::LoadClassById(Register result, Register class_id, Register pp) {
|
| +void Assembler::LoadClassById(Register result, Register class_id) {
|
| ASSERT(result != class_id);
|
| LoadIsolate(result);
|
| const intptr_t offset =
|
| Isolate::class_table_offset() + ClassTable::table_offset();
|
| - LoadFromOffset(result, result, offset, pp);
|
| + LoadFromOffset(result, result, offset);
|
| ldr(result, Address(result, class_id, UXTX, Address::Scaled));
|
| }
|
|
|
|
|
| -void Assembler::LoadClass(Register result, Register object, Register pp) {
|
| +void Assembler::LoadClass(Register result, Register object) {
|
| ASSERT(object != TMP);
|
| - LoadClassId(TMP, object, pp);
|
| - LoadClassById(result, TMP, pp);
|
| + LoadClassId(TMP, object);
|
| + LoadClassById(result, TMP);
|
| }
|
|
|
|
|
| -void Assembler::CompareClassId(
|
| - Register object, intptr_t class_id, Register pp) {
|
| - LoadClassId(TMP, object, pp);
|
| - CompareImmediate(TMP, class_id, pp);
|
| +void Assembler::CompareClassId(Register object, intptr_t class_id) {
|
| + LoadClassId(TMP, object);
|
| + CompareImmediate(TMP, class_id);
|
| }
|
|
|
|
|
| void Assembler::LoadClassIdMayBeSmi(Register result, Register object) {
|
| // Load up a null object. We only need it so we can use LoadClassId on it in
|
| // the case that object is a Smi..
|
| - LoadObject(TMP, Object::null_object(), PP);
|
| + LoadObject(TMP, Object::null_object());
|
| // Check if the object is a Smi.
|
| tsti(object, Immediate(kSmiTagMask));
|
| // If the object *is* a Smi, use the null object instead. o/w leave alone.
|
| csel(TMP, TMP, object, EQ);
|
| // Loads either the cid of the object if it isn't a Smi, or the cid of null
|
| // if it is a Smi, which will be ignored.
|
| - LoadClassId(result, TMP, PP);
|
| + LoadClassId(result, TMP);
|
|
|
| - LoadImmediate(TMP, kSmiCid, PP);
|
| + LoadImmediate(TMP, kSmiCid);
|
| // If object is a Smi, move the Smi cid into result. o/w leave alone.
|
| csel(result, TMP, result, EQ);
|
| }
|
| @@ -1011,22 +985,22 @@ void Assembler::ComputeRange(Register result,
|
| b(¬_smi, NE);
|
|
|
| AsrImmediate(scratch, value, 32);
|
| - LoadImmediate(result, ICData::kUint32RangeBit, PP);
|
| + LoadImmediate(result, ICData::kUint32RangeBit);
|
| cmp(scratch, Operand(1));
|
| b(&done, EQ);
|
|
|
| neg(scratch, scratch);
|
| add(result, scratch, Operand(ICData::kInt32RangeBit));
|
| cmp(scratch, Operand(1));
|
| - LoadImmediate(TMP, ICData::kSignedRangeBit, PP);
|
| + LoadImmediate(TMP, ICData::kSignedRangeBit);
|
| csel(result, result, TMP, LS);
|
| b(&done);
|
|
|
| Bind(¬_smi);
|
| - CompareClassId(value, kMintCid, PP);
|
| + CompareClassId(value, kMintCid);
|
| b(not_mint, NE);
|
|
|
| - LoadImmediate(result, ICData::kInt64RangeBit, PP);
|
| + LoadImmediate(result, ICData::kInt64RangeBit);
|
| Bind(&done);
|
| }
|
|
|
| @@ -1052,7 +1026,7 @@ void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
|
| // Reserve space for arguments and align frame before entering
|
| // the C++ world.
|
| if (frame_space != 0) {
|
| - AddImmediate(SP, SP, -frame_space, kNoPP);
|
| + AddImmediate(SP, SP, -frame_space);
|
| }
|
| if (OS::ActivationFrameAlignment() > 1) {
|
| andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
|
| @@ -1077,37 +1051,40 @@ void Assembler::LeaveFrame() {
|
|
|
|
|
| void Assembler::EnterDartFrame(intptr_t frame_size) {
|
| + ASSERT(!constant_pool_allowed());
|
| // Setup the frame.
|
| adr(TMP, Immediate(-CodeSize())); // TMP gets PC marker.
|
| EnterFrame(0);
|
| TagAndPushPPAndPcMarker(TMP); // Save PP and PC marker.
|
|
|
| // Load the pool pointer.
|
| - LoadPoolPointer(PP);
|
| + LoadPoolPointer();
|
|
|
| // Reserve space.
|
| if (frame_size > 0) {
|
| - AddImmediate(SP, SP, -frame_size, PP);
|
| + AddImmediate(SP, SP, -frame_size);
|
| }
|
| }
|
|
|
|
|
| void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) {
|
| + ASSERT(!constant_pool_allowed());
|
| // Setup the frame.
|
| adr(TMP, Immediate(-CodeSize())); // TMP gets PC marker.
|
| EnterFrame(0);
|
| TagAndPushPPAndPcMarker(TMP); // Save PP and PC marker.
|
|
|
| // Load the pool pointer.
|
| - if (new_pp == kNoPP) {
|
| - LoadPoolPointer(PP);
|
| + if (new_pp == kNoRegister) {
|
| + LoadPoolPointer();
|
| } else {
|
| mov(PP, new_pp);
|
| + set_constant_pool_allowed(true);
|
| }
|
|
|
| // Reserve space.
|
| if (frame_size > 0) {
|
| - AddImmediate(SP, SP, -frame_size, PP);
|
| + AddImmediate(SP, SP, -frame_size);
|
| }
|
| }
|
|
|
| @@ -1118,27 +1095,33 @@ void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) {
|
| // optimized function and there may be extra space for spill slots to
|
| // allocate. We must also set up the pool pointer for the function.
|
| void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) {
|
| + ASSERT(!constant_pool_allowed());
|
| Comment("EnterOsrFrame");
|
| adr(TMP, Immediate(-CodeSize()));
|
|
|
| - StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize, kNoPP);
|
| + StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize);
|
|
|
| // Setup pool pointer for this dart function.
|
| - if (new_pp == kNoPP) {
|
| - LoadPoolPointer(PP);
|
| + if (new_pp == kNoRegister) {
|
| + LoadPoolPointer();
|
| } else {
|
| mov(PP, new_pp);
|
| + set_constant_pool_allowed(true);
|
| }
|
|
|
| if (extra_size > 0) {
|
| - AddImmediate(SP, SP, -extra_size, PP);
|
| + AddImmediate(SP, SP, -extra_size);
|
| }
|
| }
|
|
|
|
|
| void Assembler::LeaveDartFrame() {
|
| + // LeaveDartFrame is called from stubs (pp disallowed) and from Dart code (pp
|
| + // allowed), so there is no point in checking the current value of
|
| + // constant_pool_allowed().
|
| + set_constant_pool_allowed(false);
|
| // Restore and untag PP.
|
| - LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize, kNoPP);
|
| + LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize);
|
| sub(PP, PP, Operand(kHeapObjectTag));
|
| LeaveFrame();
|
| }
|
| @@ -1176,7 +1159,7 @@ void Assembler::LeaveCallRuntimeFrame() {
|
| const intptr_t kPushedRegistersSize =
|
| kDartVolatileCpuRegCount * kWordSize +
|
| kDartVolatileFpuRegCount * kWordSize;
|
| - AddImmediate(SP, FP, -kPushedRegistersSize, PP);
|
| + AddImmediate(SP, FP, -kPushedRegistersSize);
|
| for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) {
|
| const Register reg = static_cast<Register>(i);
|
| Pop(reg);
|
| @@ -1204,23 +1187,24 @@ void Assembler::CallRuntime(const RuntimeEntry& entry,
|
|
|
|
|
| void Assembler::EnterStubFrame() {
|
| + set_constant_pool_allowed(false);
|
| EnterFrame(0);
|
| // Save caller's pool pointer. Push 0 in the saved PC area for stub frames.
|
| TagAndPushPPAndPcMarker(ZR);
|
| - LoadPoolPointer(PP);
|
| + LoadPoolPointer();
|
| }
|
|
|
|
|
| void Assembler::LeaveStubFrame() {
|
| + set_constant_pool_allowed(false);
|
| // Restore and untag PP.
|
| - LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize, kNoPP);
|
| + LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize);
|
| sub(PP, PP, Operand(kHeapObjectTag));
|
| LeaveFrame();
|
| }
|
|
|
|
|
| void Assembler::UpdateAllocationStats(intptr_t cid,
|
| - Register pp,
|
| Heap::Space space,
|
| bool inline_isolate) {
|
| ASSERT(cid > 0);
|
| @@ -1231,28 +1215,27 @@ void Assembler::UpdateAllocationStats(intptr_t cid,
|
| ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
|
| if (cid < kNumPredefinedCids) {
|
| LoadImmediate(
|
| - TMP2, reinterpret_cast<uword>(*table_ptr) + counter_offset, pp);
|
| + TMP2, reinterpret_cast<uword>(*table_ptr) + counter_offset);
|
| } else {
|
| - LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr), pp);
|
| + LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr));
|
| ldr(TMP, Address(TMP2));
|
| - AddImmediate(TMP2, TMP, counter_offset, pp);
|
| + AddImmediate(TMP2, TMP, counter_offset);
|
| }
|
| } else {
|
| LoadIsolate(TMP2);
|
| intptr_t table_offset =
|
| Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
|
| ldr(TMP, Address(TMP2, table_offset));
|
| - AddImmediate(TMP2, TMP, counter_offset, pp);
|
| + AddImmediate(TMP2, TMP, counter_offset);
|
| }
|
| ldr(TMP, Address(TMP2, 0));
|
| - AddImmediate(TMP, TMP, 1, pp);
|
| + AddImmediate(TMP, TMP, 1);
|
| str(TMP, Address(TMP2, 0));
|
| }
|
|
|
|
|
| void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
|
| Register size_reg,
|
| - Register pp,
|
| Heap::Space space,
|
| bool inline_isolate) {
|
| ASSERT(cid > 0);
|
| @@ -1268,21 +1251,21 @@ void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
|
| ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
|
| if (cid < kNumPredefinedCids) {
|
| LoadImmediate(TMP2,
|
| - reinterpret_cast<uword>(*table_ptr) + class_offset, pp);
|
| + reinterpret_cast<uword>(*table_ptr) + class_offset);
|
| } else {
|
| - LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr), pp);
|
| + LoadImmediate(TMP2, reinterpret_cast<uword>(table_ptr));
|
| ldr(TMP, Address(TMP2));
|
| - AddImmediate(TMP2, TMP, class_offset, pp);
|
| + AddImmediate(TMP2, TMP, class_offset);
|
| }
|
| } else {
|
| LoadIsolate(TMP2);
|
| intptr_t table_offset =
|
| Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
|
| ldr(TMP, Address(TMP2, table_offset));
|
| - AddImmediate(TMP2, TMP, class_offset, pp);
|
| + AddImmediate(TMP2, TMP, class_offset);
|
| }
|
| ldr(TMP, Address(TMP2, count_field_offset));
|
| - AddImmediate(TMP, TMP, 1, pp);
|
| + AddImmediate(TMP, TMP, 1);
|
| str(TMP, Address(TMP2, count_field_offset));
|
| ldr(TMP, Address(TMP2, size_field_offset));
|
| add(TMP, TMP, Operand(size_reg));
|
| @@ -1292,7 +1275,6 @@ void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
|
|
|
| void Assembler::MaybeTraceAllocation(intptr_t cid,
|
| Register temp_reg,
|
| - Register pp,
|
| Label* trace,
|
| bool inline_isolate) {
|
| ASSERT(cid > 0);
|
| @@ -1302,18 +1284,18 @@ void Assembler::MaybeTraceAllocation(intptr_t cid,
|
| ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
|
| if (cid < kNumPredefinedCids) {
|
| LoadImmediate(
|
| - temp_reg, reinterpret_cast<uword>(*table_ptr) + state_offset, pp);
|
| + temp_reg, reinterpret_cast<uword>(*table_ptr) + state_offset);
|
| } else {
|
| - LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr), pp);
|
| + LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr));
|
| ldr(temp_reg, Address(temp_reg, 0));
|
| - AddImmediate(temp_reg, temp_reg, state_offset, pp);
|
| + AddImmediate(temp_reg, temp_reg, state_offset);
|
| }
|
| } else {
|
| LoadIsolate(temp_reg);
|
| intptr_t table_offset =
|
| Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
|
| ldr(temp_reg, Address(temp_reg, table_offset));
|
| - AddImmediate(temp_reg, temp_reg, state_offset, pp);
|
| + AddImmediate(temp_reg, temp_reg, state_offset);
|
| }
|
| ldr(temp_reg, Address(temp_reg, 0));
|
| tsti(temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
|
| @@ -1324,22 +1306,21 @@ void Assembler::MaybeTraceAllocation(intptr_t cid,
|
| void Assembler::TryAllocate(const Class& cls,
|
| Label* failure,
|
| Register instance_reg,
|
| - Register temp_reg,
|
| - Register pp) {
|
| + Register temp_reg) {
|
| ASSERT(failure != NULL);
|
| if (FLAG_inline_alloc) {
|
| // If this allocation is traced, program will jump to failure path
|
| // (i.e. the allocation stub) which will allocate the object and trace the
|
| // allocation call site.
|
| - MaybeTraceAllocation(cls.id(), temp_reg, pp, failure);
|
| + MaybeTraceAllocation(cls.id(), temp_reg, failure);
|
| const intptr_t instance_size = cls.instance_size();
|
| Heap* heap = Isolate::Current()->heap();
|
| Heap::Space space = heap->SpaceForAllocation(cls.id());
|
| const uword top_address = heap->TopAddress(space);
|
| - LoadImmediate(temp_reg, top_address, pp);
|
| + LoadImmediate(temp_reg, top_address);
|
| ldr(instance_reg, Address(temp_reg));
|
| // TODO(koda): Protect against unsigned overflow here.
|
| - AddImmediateSetFlags(instance_reg, instance_reg, instance_size, pp);
|
| + AddImmediateSetFlags(instance_reg, instance_reg, instance_size);
|
|
|
| // instance_reg: potential next object start.
|
| const uword end_address = heap->EndAddress(space);
|
| @@ -1356,15 +1337,15 @@ void Assembler::TryAllocate(const Class& cls,
|
|
|
| ASSERT(instance_size >= kHeapObjectTag);
|
| AddImmediate(
|
| - instance_reg, instance_reg, -instance_size + kHeapObjectTag, pp);
|
| - UpdateAllocationStats(cls.id(), pp, space);
|
| + instance_reg, instance_reg, -instance_size + kHeapObjectTag);
|
| + UpdateAllocationStats(cls.id(), space);
|
|
|
| uword tags = 0;
|
| tags = RawObject::SizeTag::update(instance_size, tags);
|
| ASSERT(cls.id() != kIllegalCid);
|
| tags = RawObject::ClassIdTag::update(cls.id(), tags);
|
| - LoadImmediate(TMP, tags, pp);
|
| - StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp);
|
| + LoadImmediate(TMP, tags);
|
| + StoreFieldToOffset(TMP, instance_reg, Object::tags_offset());
|
| } else {
|
| b(failure);
|
| }
|
| @@ -1382,19 +1363,19 @@ void Assembler::TryAllocateArray(intptr_t cid,
|
| // If this allocation is traced, program will jump to failure path
|
| // (i.e. the allocation stub) which will allocate the object and trace the
|
| // allocation call site.
|
| - MaybeTraceAllocation(cid, temp1, PP, failure);
|
| + MaybeTraceAllocation(cid, temp1, failure);
|
| Isolate* isolate = Isolate::Current();
|
| Heap* heap = isolate->heap();
|
| Heap::Space space = heap->SpaceForAllocation(cid);
|
| - LoadImmediate(temp1, heap->TopAddress(space), PP);
|
| + LoadImmediate(temp1, heap->TopAddress(space));
|
| ldr(instance, Address(temp1, 0)); // Potential new object start.
|
| - AddImmediateSetFlags(end_address, instance, instance_size, PP);
|
| + AddImmediateSetFlags(end_address, instance, instance_size);
|
| b(failure, CS); // Fail on unsigned overflow.
|
|
|
| // Check if the allocation fits into the remaining space.
|
| // instance: potential new object start.
|
| // end_address: potential next object start.
|
| - LoadImmediate(temp2, heap->EndAddress(space), PP);
|
| + LoadImmediate(temp2, heap->EndAddress(space));
|
| ldr(temp2, Address(temp2, 0));
|
| cmp(end_address, Operand(temp2));
|
| b(failure, CS);
|
| @@ -1403,15 +1384,15 @@ void Assembler::TryAllocateArray(intptr_t cid,
|
| // next object start and initialize the object.
|
| str(end_address, Address(temp1, 0));
|
| add(instance, instance, Operand(kHeapObjectTag));
|
| - LoadImmediate(temp2, instance_size, PP);
|
| - UpdateAllocationStatsWithSize(cid, temp2, PP, space);
|
| + LoadImmediate(temp2, instance_size);
|
| + UpdateAllocationStatsWithSize(cid, temp2, space);
|
|
|
| // Initialize the tags.
|
| // instance: new object start as a tagged pointer.
|
| uword tags = 0;
|
| tags = RawObject::ClassIdTag::update(cid, tags);
|
| tags = RawObject::SizeTag::update(instance_size, tags);
|
| - LoadImmediate(temp2, tags, PP);
|
| + LoadImmediate(temp2, tags);
|
| str(temp2, FieldAddress(instance, Array::tags_offset())); // Store tags.
|
| } else {
|
| b(failure);
|
|
|