Chromium Code Reviews| Index: runtime/vm/instructions_arm.cc |
| =================================================================== |
| --- runtime/vm/instructions_arm.cc (revision 19822) |
| +++ runtime/vm/instructions_arm.cc (working copy) |
| @@ -14,8 +14,18 @@ |
| 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(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 +34,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] |
|
zra
2013/03/11 22:36:08
Would it be too heavyweight here to use the Instr
regis
2013/03/11 23:16:30
I thought of using class Instr and tried, but the
|
| 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 +121,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. |
| } |