Reuse SIRT for C++ references

Change-Id: I8310e55da42f55f7ec60f6b17face436c77a979f
diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h
index f0b6698..8b98763 100644
--- a/src/stack_indirect_reference_table.h
+++ b/src/stack_indirect_reference_table.h
@@ -23,22 +23,55 @@
 
 class Object;
 
-// Stack allocated indirect reference table, allocated within the bridge frame
-// between managed and native code.
+// Stack allocated indirect reference table. It can allocated within
+// the bridge frame between managed and native code backed by stack
+// storage or manually allocated by SirtRef to hold one reference.
 class StackIndirectReferenceTable {
 public:
+
+  StackIndirectReferenceTable(Object* object) {
+    number_of_references_ = 1;
+    references_[0] = object;
+    Thread::Current()->PushSirt(this);
+  }
+
+  ~StackIndirectReferenceTable() {
+    StackIndirectReferenceTable* sirt = Thread::Current()->PopSirt();
+    CHECK_EQ(this, sirt);
+  }
+
   // Number of references contained within this SIRT
-  size_t NumberOfReferences() {
+  size_t NumberOfReferences() const {
     return number_of_references_;
   }
 
   // Link to previous SIRT or NULL
-  StackIndirectReferenceTable* Link() {
+  StackIndirectReferenceTable* GetLink() const {
     return link_;
   }
 
-  Object** References() {
-    return references_;
+  void SetLink(StackIndirectReferenceTable* sirt) {
+    DCHECK_NE(this, sirt);
+    link_ = sirt;
+  }
+
+  Object* GetReference(size_t i) const {
+    DCHECK_LT(i, number_of_references_);
+    return references_[i];
+  }
+
+  void SetReference(size_t i, Object* object) {
+    DCHECK_LT(i, number_of_references_);
+    references_[i] = object;
+  }
+
+  bool Contains(Object** sirt_entry) const {
+    // A SIRT should always contain something. One created by the
+    // jni_compiler should have a jobject/jclass as a native method is
+    // passed in a this pointer or a class
+    DCHECK_GT(number_of_references_, 0U);
+    return ((&references_[0] <= sirt_entry)
+            && (sirt_entry <= (&references_[number_of_references_ - 1])));
   }
 
   // Offset of length within SIRT, used by generated code
@@ -57,12 +90,34 @@
   size_t number_of_references_;
   StackIndirectReferenceTable* link_;
 
-  // Fake array, really allocated and filled in by jni_compiler.
-  Object* references_[0];
+  // number_of_references_ are available if this is allocated and filled in by jni_compiler.
+  Object* references_[1];
 
   DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
 };
 
+template<class T>
+class SirtRef {
+public:
+  SirtRef(T* object) : sirt_(object) {}
+  ~SirtRef() {}
+
+  T& operator*() const { return *get(); }
+  T* operator->() const { return get(); }
+  T* get() const {
+    return down_cast<T*>(sirt_.GetReference(0));
+  }
+
+  void reset(T* object = NULL) {
+    sirt_.SetReference(0, object);
+  }
+
+private:
+  StackIndirectReferenceTable sirt_;
+
+  DISALLOW_COPY_AND_ASSIGN(SirtRef);
+};
+
 }  // namespace art
 
 #endif  // ART_SRC_STACK_INDIRECT_REFERENCE_TABLE_H_