Chromium Code Reviews| Index: runtime/vm/assembler_arm.cc |
| =================================================================== |
| --- runtime/vm/assembler_arm.cc (revision 18162) |
| +++ runtime/vm/assembler_arm.cc (working copy) |
| @@ -72,7 +72,7 @@ |
| const uint32_t offset_mask = (1 << 12) - 1; |
| uint32_t offset = encoding_ & offset_mask; |
| ASSERT(offset < (1 << 10)); // In the range 0 to +1020. |
| - ASSERT(Utils::Utils::IsAligned(offset, 2)); // Multiple of 4. |
| + ASSERT(Utils::IsAligned(offset, 4)); // Multiple of 4. |
| int mode = encoding_ & ((8|4|1) << 21); |
| ASSERT((mode == Offset) || (mode == NegOffset)); |
| uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2); |
| @@ -83,6 +83,17 @@ |
| } |
| +void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { |
| + ASSERT(Utils::IsAligned(data, 4)); |
| + ASSERT(Utils::IsAligned(length, 4)); |
| + const uword end = data + length; |
| + while (data < end) { |
| + *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; |
| + data += 4; |
| + } |
| +} |
| + |
| + |
| void Assembler::Emit(int32_t value) { |
| AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| buffer_.Emit<int32_t>(value); |
| @@ -1020,7 +1031,18 @@ |
| void Assembler::LoadObject(Register rd, const Object& object) { |
| - UNIMPLEMENTED(); |
| + // TODO(regis): If the object is never relocated (null, true, false, ...), |
| + // load as immediate. |
| + int32_t offset = AddObject(object); |
| + ASSERT(Utils::IsAligned(offset, 4) && (offset >= 0)); |
| + if (Address::CanHoldLoadOffset(kLoadWord, offset)) { |
| + ldr(rd, Address(CP, offset)); |
| + } else { |
| + int32_t offset12_hi = offset & ~kOffset12Mask; // signed |
| + uint32_t offset12_lo = offset & kOffset12Mask; // unsigned |
| + AddConstant(rd, CP, offset12_hi); |
| + ldr(rd, Address(rd, offset12_lo)); |
| + } |
| } |
| @@ -1139,22 +1161,28 @@ |
| void Assembler::Branch(const ExternalLabel* label) { |
| - // TODO(regis): Revisit this code sequence. |
| LoadImmediate(IP, label->address()); // Target address is never patched. |
| mov(PC, ShifterOperand(IP)); |
| } |
| void Assembler::BranchLink(const ExternalLabel* label) { |
| - // TODO(regis): Revisit this code sequence. |
| - // Make sure that CodePatcher is able to patch this code sequence. |
| + // TODO(regis): Make sure that CodePatcher is able to patch the label referred |
| + // to by this code sequence. |
| // For added code robustness, use 'blx lr' in a patchable sequence and |
| // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). |
| - ldr(LR, Address(PC)); |
| - Label skip; |
| - b(&skip); |
| - Emit(label->address()); // May get patched. |
| - Bind(&skip); |
| + int32_t offset = AddExternalLabel(label); |
| + ASSERT(Utils::IsAligned(offset, 4) && (offset >= 0)); |
| + if (Address::CanHoldLoadOffset(kLoadWord, offset)) { |
| + ldr(LR, Address(CP, offset)); |
| + } else { |
| + int32_t offset12_hi = offset & ~kOffset12Mask; // signed |
| + uint32_t offset12_lo = offset & kOffset12Mask; // unsigned |
| + // TODO(regis): Using AddConstant may generate too many sequences to be |
| + // easily decoded by CodePatcher. If so, use a simpler fixed sequence. |
| + AddConstant(LR, CP, offset12_hi); |
|
Ivan Posva
2013/02/06 23:33:50
As discussed, please do not use macros here as the
regis
2013/02/07 00:53:24
Done.
|
| + ldr(LR, Address(LR, offset12_lo)); |
| + } |
| blx(LR); // Use blx instruction so that the return branch prediction works. |
| } |
| @@ -1494,6 +1522,32 @@ |
| return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); |
| } |
| + |
| +int32_t Assembler::AddObject(const Object& obj) { |
| + for (int i = 0; i < objects_.Length(); i++) { |
|
Ivan Posva
2013/02/06 23:33:50
As discussed we should just return the offset here
regis
2013/02/07 00:53:24
Done.
|
| + if (objects_.At(i) == obj.raw()) { |
| + // TODO(regis): Skip over header. |
| + return /*kCodeObjectsHeaderSize +*/ 4*i; |
| + } |
| + } |
| + objects_.Add(obj); |
| + // TODO(regis): Skip over header. |
| + return /*kCodeObjectsHeaderSize +*/ 4*(objects_.Length() - 1); |
| +} |
| + |
| + |
| +int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { |
| + 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(Smi::New(address >> kSmiTagShift)); |
| + // Do not reuse an existing entry, since each reference may be patched |
| + // independently. |
| + objects_.Add(smi); |
| + // TODO(regis): Skip over header. |
| + return /*kCodeObjectsHeaderSize +*/ 4*(objects_.Length() - 1); |
|
Ivan Posva
2013/02/06 23:33:50
ditto.
regis
2013/02/07 00:53:24
Done.
|
| +} |
| + |
| } // namespace dart |
| #endif // defined TARGET_ARCH_ARM |