Split shadow stack from SIRT.

Change-Id: I4c1712c34bb12187c54385fbe4d23da08ef66277
diff --git a/src/asm_support.h b/src/asm_support.h
index 6ba23bc..bcad9ad 100644
--- a/src/asm_support.h
+++ b/src/asm_support.h
@@ -30,7 +30,7 @@
 
 #elif defined(__i386__)
 // Offset of field Thread::self_ verified in InitCpu
-#define THREAD_SELF_OFFSET 108
+#define THREAD_SELF_OFFSET 112
 #endif
 
 #endif  // ART_SRC_ASM_SUPPORT_H_
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 013a530..f09d6c1 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -6,6 +6,7 @@
 #include "object_utils.h"
 #include "runtime_support_common.h"
 #include "runtime_support_llvm.h"
+#include "shadow_frame.h"
 #include "thread.h"
 #include "thread_list.h"
 
@@ -49,14 +50,12 @@
 
 void art_push_shadow_frame_from_code(void* new_shadow_frame) {
   Thread* thread = Thread::Current();
-  thread->PushSirt(
-      static_cast<StackIndirectReferenceTable*>(new_shadow_frame)
-                   );
+  thread->PushShadowFrame(static_cast<ShadowFrame*>(new_shadow_frame));
 }
 
 void art_pop_shadow_frame_from_code() {
   Thread* thread = Thread::Current();
-  thread->PopSirt();
+  thread->PopShadowFrame();
 }
 
 
diff --git a/src/shadow_frame.h b/src/shadow_frame.h
new file mode 100644
index 0000000..533d924
--- /dev/null
+++ b/src/shadow_frame.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_SHADOW_FRAME_H_
+#define ART_SRC_SHADOW_FRAME_H_
+
+#include "logging.h"
+#include "macros.h"
+
+namespace art {
+
+class Object;
+
+class ShadowFrame {
+ public:
+  // Number of references contained within this shadow frame
+  uint32_t NumberOfReferences() const {
+    return number_of_references_;
+  }
+
+  // Link to previous shadow frame or NULL
+  ShadowFrame* GetLink() const {
+    return link_;
+  }
+
+  void SetLink(ShadowFrame* frame) {
+    DCHECK_NE(this, frame);
+    link_ = frame;
+  }
+
+  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;
+  }
+
+ private:
+  // ShadowFrame should be allocated by the generated code directly.
+  // We should not create new shadow stack in the runtime support function.
+  ~ShadowFrame() {}
+
+  uint32_t number_of_references_;
+  ShadowFrame* link_;
+  Object* method_;
+  uint32_t line_num_;
+  Object* references_[];
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame);
+};
+
+}  // namespace art
+
+#endif  // ART_SRC_SHADOW_FRAME_H_
diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h
index 5c6bc0a..5f37294 100644
--- a/src/stack_indirect_reference_table.h
+++ b/src/stack_indirect_reference_table.h
@@ -90,10 +90,6 @@
 
   size_t number_of_references_;
   StackIndirectReferenceTable* link_;
-#if defined(ART_USE_LLVM_COMPILER)
-  Object* method_;
-  uint32_t line_num_;
-#endif
 
   // number_of_references_ are available if this is allocated and filled in by jni_compiler.
   Object* references_[1];
diff --git a/src/thread.cc b/src/thread.cc
index b511aa7..3ca0d04 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -43,6 +43,7 @@
 #include "runtime_support.h"
 #include "ScopedLocalRef.h"
 #include "scoped_jni_thread_state.h"
+#include "shadow_frame.h"
 #include "space.h"
 #include "stack.h"
 #include "stack_indirect_reference_table.h"
@@ -868,6 +869,7 @@
       stack_end_(NULL),
       native_to_managed_record_(NULL),
       top_sirt_(NULL),
+      top_shadow_frame_(NULL),
       jni_env_(NULL),
       state_(Thread::kNative),
       self_(NULL),
@@ -1003,6 +1005,18 @@
   }
 }
 
+void Thread::ShadowFrameVisitRoots(Heap::RootVisitor* visitor, void* arg) {
+  for (ShadowFrame* cur = top_shadow_frame_; cur; cur = cur->GetLink()) {
+    size_t num_refs = cur->NumberOfReferences();
+    for (size_t j = 0; j < num_refs; j++) {
+      Object* object = cur->GetReference(j);
+      if (object != NULL) {
+        visitor(object, arg);
+      }
+    }
+  }
+}
+
 Object* Thread::DecodeJObject(jobject obj) {
   DCHECK(CanAccessDirectReferences());
   if (obj == NULL) {
@@ -1181,6 +1195,18 @@
   return pc;
 }
 
+void Thread::PushShadowFrame(ShadowFrame* frame) {
+  frame->SetLink(top_shadow_frame_);
+  top_shadow_frame_ = frame;
+}
+
+ShadowFrame* Thread::PopShadowFrame() {
+  CHECK(top_shadow_frame_ != NULL);
+  ShadowFrame* frame = top_shadow_frame_;
+  top_shadow_frame_ = frame->GetLink();
+  return frame;
+}
+
 void Thread::PushSirt(StackIndirectReferenceTable* sirt) {
   sirt->SetLink(top_sirt_);
   top_sirt_ = sirt;
@@ -1665,6 +1691,7 @@
   jni_env_->monitors.VisitRoots(visitor, arg);
 
   SirtVisitRoots(visitor, arg);
+  ShadowFrameVisitRoots(visitor, arg);
 
   // Cheat and steal the long jump context. Assume that we are not doing a GC during exception
   // delivery.
diff --git a/src/thread.h b/src/thread.h
index 51385f9..bbf7730 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -50,6 +50,7 @@
 class Monitor;
 class Object;
 class Runtime;
+class ShadowFrame;
 class StackIndirectReferenceTable;
 class StackTraceElement;
 class StaticStorageBase;
@@ -266,6 +267,8 @@
 
   void SirtVisitRoots(Heap::RootVisitor* visitor, void* arg);
 
+  void ShadowFrameVisitRoots(Heap::RootVisitor* visitor, void* arg);
+
   // Convert a jobject into a Object*
   Object* DecodeJObject(jobject obj);
 
@@ -393,6 +396,9 @@
     return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_pc_));
   }
 
+  void PushShadowFrame(ShadowFrame* frame);
+  ShadowFrame* PopShadowFrame();
+
   void PushSirt(StackIndirectReferenceTable* sirt);
   StackIndirectReferenceTable* PopSirt();
 
@@ -524,6 +530,10 @@
   // Top of linked list of stack indirect reference tables or NULL for none
   StackIndirectReferenceTable* top_sirt_;
 
+  // Top of linked list of shadow stack or NULL for none
+  // Some backend may require shadow frame to ease the GC work.
+  ShadowFrame* top_shadow_frame_;
+
   // Every thread may have an associated JNI environment
   JNIEnvExt* jni_env_;