| Index: runtime/vm/instructions_arm.cc
|
| ===================================================================
|
| --- runtime/vm/instructions_arm.cc (revision 19826)
|
| +++ runtime/vm/instructions_arm.cc (working copy)
|
| @@ -14,8 +14,19 @@
|
|
|
| CallPattern::CallPattern(uword pc, const Code& code)
|
| : end_(reinterpret_cast<uword*>(pc)),
|
| - pool_index_(DecodePoolIndex()),
|
| - object_pool_(Array::Handle(code.ObjectPool())) { }
|
| + target_address_pool_index_(-1),
|
| + args_desc_load_end_(-1),
|
| + args_desc_pool_index_(-1),
|
| + ic_data_load_end_(-1),
|
| + ic_data_pool_index_(-1),
|
| + object_pool_(Array::Handle(code.ObjectPool())) {
|
| + ASSERT(code.ContainsInstructionAt(pc));
|
| + ASSERT(Back(1) == 0xe12fff3e); // Last instruction: blx lr
|
| + Register reg;
|
| + args_desc_load_end_ =
|
| + DecodeLoadWordFromPool(1, ®, &target_address_pool_index_);
|
| + ASSERT(reg == LR);
|
| +}
|
|
|
|
|
| uword CallPattern::Back(int n) const {
|
| @@ -24,43 +35,83 @@
|
| }
|
|
|
|
|
| -int CallPattern::DecodePoolIndex() {
|
| - ASSERT(Back(1) == 0xe12fff3e); // Last instruction: blx lr
|
| - // Decode the second to last instruction.
|
| - uword instr = Back(2);
|
| +// Decodes a load sequence ending at end. Returns the register being loaded and
|
| +// the index in the pool being read from.
|
| +// Returns the location of the load sequence, counting the number of
|
| +// instructions back from the end of the call pattern.
|
| +int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) {
|
| + ASSERT(end > 0);
|
| + uword instr = Back(++end);
|
| int offset = 0;
|
| - if ((instr & 0xfffff000) == 0xe59ae000) { // ldr lr, [pp, #+offset]
|
| + if ((instr & 0xffff0000) == 0xe59a0000) { // ldr reg, [pp, #+offset]
|
| offset = instr & 0xfff;
|
| + *reg = static_cast<Register>((instr & 0xf000) >> 12);
|
| } else {
|
| - ASSERT((instr & 0xfffff000) == 0xe59ee000); // ldr lr, [lr, #+offset]
|
| + ASSERT((instr & 0xfff00000) == 0xe5900000); // ldr reg, [reg, #+offset]
|
| offset = instr & 0xfff;
|
| - instr = Back(3);
|
| - if ((instr & 0xfffff000) == 0xe28ae000) { // add lr, pp, shifter_op
|
| + instr = Back(++end);
|
| + if ((instr & 0xffff0000) == 0xe28a0000) { // add reg, pp, shifter_op
|
| const int rot = (instr & 0xf00) * 2;
|
| const int imm8 = instr & 0xff;
|
| offset |= (imm8 >> rot) | (imm8 << (32 - rot));
|
| + *reg = static_cast<Register>((instr & 0xf000) >> 12);
|
| } else {
|
| - ASSERT(instr == 0xe08ae00e); // add lr, pp, lr
|
| - instr = Back(4);
|
| - if ((instr & 0xfff0f000) == 0xe340e000) { // movt lr, offset_hi
|
| + ASSERT((instr & 0xffff0000) == 0xe08a0000); // add reg, pp, reg
|
| + instr = Back(++end);
|
| + if ((instr & 0xfff00000) == 0xe3400000) { // movt reg, offset_hi
|
| offset |= (instr & 0xf0000) << 12;
|
| offset |= (instr & 0xfff) << 16;
|
| - instr = Back(5);
|
| + instr = Back(++end);
|
| }
|
| - ASSERT((instr & 0xfff0f000) == 0xe300e000); // movw lr, offset_lo
|
| + ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, offset_lo
|
| ASSERT((offset & 0xffff) == 0);
|
| offset |= (instr & 0xf0000) >> 4;
|
| offset |= instr & 0xfff;
|
| + *reg = static_cast<Register>((instr & 0xf000) >> 12);
|
| }
|
| }
|
| offset += kHeapObjectTag;
|
| ASSERT(Utils::IsAligned(offset, 4));
|
| - return (offset - Array::data_offset())/4;
|
| + *index = (offset - Array::data_offset())/4;
|
| + return end;
|
| }
|
|
|
|
|
| +RawICData* CallPattern::IcData() {
|
| + if (ic_data_pool_index_ < 0) {
|
| + Register reg;
|
| + // Loading of the argument descriptor must be decoded first, if not already.
|
| + if (args_desc_pool_index_ < 0) {
|
| + ic_data_load_end_ = DecodeLoadWordFromPool(
|
| + args_desc_load_end_, ®, &args_desc_pool_index_);
|
| + ASSERT(reg == R4);
|
| + }
|
| + DecodeLoadWordFromPool(ic_data_load_end_, ®, &ic_data_pool_index_);
|
| + ASSERT(reg == R5);
|
| + }
|
| + ICData& ic_data = ICData::Handle();
|
| + ic_data ^= object_pool_.At(ic_data_pool_index_);
|
| + return ic_data.raw();
|
| +}
|
| +
|
| +
|
| +RawArray* CallPattern::ArgumentsDescriptor() {
|
| + if (args_desc_pool_index_ < 0) {
|
| + Register reg;
|
| + ic_data_load_end_ = DecodeLoadWordFromPool(
|
| + args_desc_load_end_, ®, &args_desc_pool_index_);
|
| + ASSERT(reg == R4);
|
| + }
|
| + Array& args_desc = Array::Handle();
|
| + args_desc ^= object_pool_.At(args_desc_pool_index_);
|
| + return args_desc.raw();
|
| +}
|
| +
|
| +
|
| uword CallPattern::TargetAddress() const {
|
| - const Object& target_address = Object::Handle(object_pool_.At(pool_index_));
|
| + ASSERT(target_address_pool_index_ >= 0);
|
| + const Object& target_address =
|
| + Object::Handle(object_pool_.At(target_address_pool_index_));
|
| ASSERT(target_address.IsSmi());
|
| // The address is stored in the object array as a RawSmi.
|
| return reinterpret_cast<uword>(target_address.raw());
|
| @@ -71,7 +122,7 @@
|
| ASSERT(Utils::IsAligned(target_address, 4));
|
| // The address is stored in the object array as a RawSmi.
|
| const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
|
| - object_pool_.SetAt(pool_index_, smi);
|
| + object_pool_.SetAt(target_address_pool_index_, smi);
|
| // No need to flush the instruction cache, since the code is not modified.
|
| }
|
|
|
|
|