Split shadow stack from SIRT.
(cherry picked from commit 4455f868a9a6553827ccbe1d25e29cf528a74422)
Change-Id: I4f467cf5be812c600dc5fdb56a9236fe144bd380
diff --git a/src/asm_support.h b/src/asm_support.h
index d5bc370..d9e57d1 100644
--- a/src/asm_support.h
+++ b/src/asm_support.h
@@ -35,7 +35,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 54c6cbe..b6ca288 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 1b5dea0..f3e1092 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"
@@ -954,6 +955,7 @@
stack_end_(NULL),
native_to_managed_record_(NULL),
top_sirt_(NULL),
+ top_shadow_frame_(NULL),
jni_env_(NULL),
state_(Thread::kNative),
self_(NULL),
@@ -1092,6 +1094,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) {
@@ -1270,6 +1284,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;
@@ -1754,6 +1780,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 8a0c1af..6f91b31 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;
@@ -272,6 +273,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);
@@ -405,6 +408,9 @@
return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_pc_));
}
+ void PushShadowFrame(ShadowFrame* frame);
+ ShadowFrame* PopShadowFrame();
+
void PushSirt(StackIndirectReferenceTable* sirt);
StackIndirectReferenceTable* PopSirt();
@@ -539,6 +545,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_;