Index: runtime/vm/code_patcher_mips.cc |
diff --git a/runtime/vm/code_patcher_mips.cc b/runtime/vm/code_patcher_mips.cc |
index f25b4602ef81f41ca737795854b7d634991490de..7a845961be199ac89b7bdee7c048baf46b78e946 100644 |
--- a/runtime/vm/code_patcher_mips.cc |
+++ b/runtime/vm/code_patcher_mips.cc |
@@ -84,6 +84,47 @@ RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( |
return ic_data.GetTargetAt(0); |
} |
+ |
+// This class pattern matches on a load from the object pool. Loading on |
+// MIPS is complicated because it can take four possible different forms. |
+// We match backwards from the end of the sequence so we can reuse the code |
+// for matching object pool loads at calls. |
+class EdgeCounter : public ValueObject { |
+ public: |
+ EdgeCounter(uword pc, const Code& code) |
+ : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) { |
+ // An IsValid predicate is complicated and duplicates the code in the |
+ // decoding function. Instead we rely on decoding the pattern which |
+ // will assert partial validity. |
+ } |
+ |
+ RawObject* edge_counter() const { |
+ Register ignored; |
+ intptr_t index; |
+ InstructionPattern::DecodeLoadWordFromPool(end_, &ignored, &index); |
+ ASSERT(ignored == T0); |
+ return object_pool_.At(index); |
+ } |
+ |
+ private: |
+ // The object pool load is followed by the fixed-size edge counter |
+ // incrementing code: |
+ // lw r9, 11(r8) |
+ // addiu r9, r9, 2 |
+ // sw r9, 11(r8) |
+ static const intptr_t kAdjust = 3 * Instr::kInstrSize; |
+ |
+ uword end_; |
+ const Array& object_pool_; |
+}; |
+ |
+ |
+RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
+ ASSERT(code.ContainsInstructionAt(pc)); |
+ EdgeCounter counter(pc, code); |
+ return counter.edge_counter(); |
+} |
+ |
} // namespace dart |
#endif // defined TARGET_ARCH_MIPS |