Chromium Code Reviews| Index: runtime/vm/assembler_arm64.cc |
| =================================================================== |
| --- runtime/vm/assembler_arm64.cc (revision 35689) |
| +++ runtime/vm/assembler_arm64.cc (working copy) |
| @@ -630,6 +630,18 @@ |
| } |
| +void Assembler::LoadDFromOffset(VRegister dest, Register base, int32_t offset) { |
| + ASSERT(base != TMP2); |
|
regis
2014/05/02 19:59:16
I would move this assert to the else branch.
zra
2014/05/02 20:16:11
Done.
|
| + if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) { |
| + fldrd(dest, Address(base, offset, Address::Offset, kDWord)); |
| + } else { |
| + // Since offset is 32-bits, it won't be loaded from the pool. |
| + AddImmediate(TMP2, base, offset, kNoPP); |
| + fldrd(dest, Address(TMP2)); |
| + } |
| +} |
| + |
| + |
| void Assembler::StoreToOffset( |
| Register src, Register base, int32_t offset, OperandSize sz) { |
| ASSERT(src != TMP2); |
| @@ -644,6 +656,18 @@ |
| } |
| +void Assembler::StoreDToOffset(VRegister src, Register base, int32_t offset) { |
| + ASSERT(base != TMP2); |
|
regis
2014/05/02 19:59:16
ditto
zra
2014/05/02 20:16:11
Done.
|
| + if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) { |
| + fstrd(src, Address(base, offset, Address::Offset, kDWord)); |
| + } else { |
| + // Since offset is 32-bits, it won't be loaded from the pool. |
| + AddImmediate(TMP2, base, offset, kNoPP); |
| + fstrd(src, Address(TMP2)); |
| + } |
| +} |
| + |
| + |
| // Store into object. |
| // Preserves object and value registers. |
| void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| @@ -873,11 +897,22 @@ |
| void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { |
| EnterFrame(0); |
| - // TODO(zra): also save volatile FPU registers. |
| + // Store fpu registers with the lowest register number at the lowest |
| + // address. |
| + for (int i = kNumberOfVRegisters - 1; i >= 0; i--) { |
| + if ((i >= kAbiFirstPreservedFpuReg) && (i <= kAbiLastPreservedFpuReg)) { |
| + // TODO(zra): When SIMD is added, we must also preserve the top |
| + // 64-bits of the callee-saved registers. |
| + continue; |
| + } |
| + // TODO(zra): Save the whole V register. |
| + VRegister reg = static_cast<VRegister>(i); |
| + PushDouble(reg); |
| + } |
| for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
| const Register reg = static_cast<Register>(i); |
| - if ((reg != R16) && (reg != R17)) { |
| + if ((reg != TMP) && (reg != TMP2)) { |
| Push(reg); |
| } |
| } |
| @@ -892,15 +927,27 @@ |
| // We need to restore it before restoring registers. |
| // TODO(zra): Also include FPU regs in this count once they are added. |
| const intptr_t kPushedRegistersSize = |
| - kDartVolatileCpuRegCount * kWordSize; |
| + kDartVolatileCpuRegCount * kWordSize + |
| + kDartVolatileFpuRegCount * kWordSize; |
| AddImmediate(SP, FP, -kPushedRegistersSize, PP); |
| for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) { |
| const Register reg = static_cast<Register>(i); |
| - if ((reg != R16) && (reg != R17)) { |
| + if ((reg != TMP) && (reg != TMP2)) { |
| Pop(reg); |
| } |
| } |
| + for (int i = 0; i < kNumberOfVRegisters; i++) { |
| + if ((i >= kAbiFirstPreservedFpuReg) && (i <= kAbiLastPreservedFpuReg)) { |
| + // TODO(zra): When SIMD is added, we must also restore the top |
| + // 64-bits of the callee-saved registers. |
| + continue; |
| + } |
| + // TODO(zra): Restore the whole V register. |
| + VRegister reg = static_cast<VRegister>(i); |
| + PopDouble(reg); |
| + } |
| + |
| Pop(FP); |
| Pop(LR); |
| } |
| @@ -1017,6 +1064,48 @@ |
| } |
| } |
| + |
| +void Assembler::TryAllocate(const Class& cls, |
| + Label* failure, |
| + Register instance_reg, |
| + Register temp_reg, |
| + Register pp) { |
| + ASSERT(failure != NULL); |
| + if (FLAG_inline_alloc) { |
| + Heap* heap = Isolate::Current()->heap(); |
| + const intptr_t instance_size = cls.instance_size(); |
| + LoadImmediate(instance_reg, heap->TopAddress(), pp); |
| + ldr(instance_reg, Address(instance_reg)); |
| + AddImmediate(instance_reg, instance_reg, instance_size, pp); |
| + |
| + // instance_reg: potential next object start. |
| + LoadImmediate(TMP, heap->EndAddress(), pp); |
| + ldr(TMP, Address(TMP)); |
| + CompareRegisters(TMP, instance_reg); |
| + // fail if heap end unsigned less than or equal to instance_reg. |
| + b(failure, LS); |
| + |
| + // Successfully allocated the object, now update top to point to |
| + // next object start and store the class in the class field of object. |
| + LoadImmediate(TMP, heap->TopAddress(), pp); |
| + str(instance_reg, Address(TMP)); |
| + |
| + ASSERT(instance_size >= kHeapObjectTag); |
| + AddImmediate( |
| + instance_reg, instance_reg, -instance_size + kHeapObjectTag, pp); |
| + UpdateAllocationStats(cls.id(), temp_reg, pp); |
| + |
| + 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()); |
| + } else { |
| + b(failure); |
| + } |
| +} |
| + |
| } // namespace dart |
| #endif // defined TARGET_ARCH_ARM64 |