Index: runtime/vm/instructions_mips.cc |
=================================================================== |
--- runtime/vm/instructions_mips.cc (revision 20729) |
+++ runtime/vm/instructions_mips.cc (working copy) |
@@ -15,16 +15,16 @@ |
: end_(reinterpret_cast<uword*>(pc)), |
target_address_pool_index_(-1), |
args_desc_load_end_(-1), |
- args_desc_pool_index_(-1), |
+ args_desc_(Array::Handle()), |
ic_data_load_end_(-1), |
- ic_data_pool_index_(-1), |
+ ic_data_(ICData::Handle()), |
object_pool_(Array::Handle(code.ObjectPool())) { |
ASSERT(code.ContainsInstructionAt(pc)); |
ASSERT(Back(2) == 0x0020f809); // Last instruction: jalr RA, TMP(=R1) |
Register reg; |
// First end is 0 so that we begin from the delay slot of the jalr. |
- args_desc_load_end_ = |
- DecodeLoadWordFromPool(2, ®, &target_address_pool_index_); |
+ ic_data_load_end_ = |
+ DecodeLoadWordFromPool(2, ®, &target_address_pool_index_); |
ASSERT(reg == TMP); |
} |
@@ -35,6 +35,54 @@ |
} |
+// Decodes a load sequence ending at end. Returns the register being loaded and |
+// the loaded object. |
+// Returns the location of the load sequence, counting the number of |
+// instructions back from the end of the call pattern. |
+int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) { |
+ ASSERT(end > 0); |
+ uword i = Back(end + 1); |
+ Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); |
+ if (instr->OpcodeField() == LW) { |
+ int index = 0; |
+ end = DecodeLoadWordFromPool(end, reg, &index); |
+ *obj = object_pool_.At(index); |
+ } else { |
+ int value = 0; |
+ end = DecodeLoadWordImmediate(end, reg, &value); |
+ *obj = reinterpret_cast<RawObject*>(value); |
+ } |
+ return end; |
+} |
+ |
+ |
+// Decodes a load sequence ending at end. Returns the register being loaded and |
+// the loaded immediate value. |
+// Returns the location of the load sequence, counting the number of |
+// instructions back from the end of the call pattern. |
+int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) { |
+ ASSERT(end > 0); |
+ int imm = 0; |
+ uword i = Back(++end); |
+ Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); |
+ ASSERT(instr->OpcodeField() == ORI); |
+ imm = instr->UImmField(); |
+ *reg = instr->RtField(); |
+ |
+ i = Back(++end); |
+ instr = Instr::At(reinterpret_cast<uword>(&i)); |
+ ASSERT(instr->OpcodeField() == LUI); |
+ ASSERT(instr->RtField() == *reg); |
+ imm |= instr->UImmField(); |
+ *value = imm; |
+ return end; |
+} |
+ |
+ |
+// 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 i = Back(++end); |
@@ -58,6 +106,7 @@ |
i = Back(++end); |
instr = Instr::At(reinterpret_cast<uword>(&i)); |
+ ASSERT(instr->OpcodeField() == LUI); |
ASSERT(instr->RtField() == *reg); |
// Offset is signed, so add the upper 16 bits. |
offset += (instr->UImmField() << 16); |
@@ -70,14 +119,23 @@ |
RawICData* CallPattern::IcData() { |
- UNIMPLEMENTED(); |
- return NULL; |
+ if (ic_data_.IsNull()) { |
+ Register reg; |
+ args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, ®, &ic_data_); |
+ ASSERT(reg == S5); |
+ } |
+ return ic_data_.raw(); |
} |
RawArray* CallPattern::ArgumentsDescriptor() { |
- UNIMPLEMENTED(); |
- return NULL; |
+ if (args_desc_.IsNull()) { |
+ IcData(); // Loading of the ic_data must be decoded first, if not already. |
+ Register reg; |
+ DecodeLoadObject(args_desc_load_end_, ®, &args_desc_); |
+ ASSERT(reg == S4); |
+ } |
+ return args_desc_.raw(); |
} |