summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hiroshi Yamauchi <yamauchi@google.com> 2014-05-15 21:43:59 -0700
committer Hiroshi Yamauchi <yamauchi@google.com> 2014-05-16 13:37:45 -0700
commit92d1a666534aa98b173bb33dc5dba86b2d48aedb (patch)
tree864887bc5e1220152998874d3be861b31a49b0fa
parent3b2bcbf9daf39f4cece7fde1186f3fa494000ed9 (diff)
Visit methods in stack frames during root visits.
This is necessary for a Baker-style read barrier to-space invariant to hold. That is, an object either needs to be marked/forwarded as root or it must be accessed only through a read barrier by mutators. Since stack frames have direct pointers to methods that a mutator can access without a read barrier, stack frame methods have to be visited as root, which makes sense as stack frames are thread roots. This is the case even if methods do not move as they have to be marked 'gray' for the objects pointed to by them, which can move, to be recursively marked/forwarded. This also puts us in the right direction toward moving methods (and fields) in the future. Bug: 12687968 Change-Id: Id32b913c021a140073deea9149a8782e8f308303
-rw-r--r--runtime/stack.h20
-rw-r--r--runtime/thread.cc9
2 files changed, 22 insertions, 7 deletions
diff --git a/runtime/stack.h b/runtime/stack.h
index 963983a7a6..2e32f51343 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -306,6 +306,11 @@ class ShadowFrame {
return method_;
}
+ mirror::ArtMethod** GetMethodAddress() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(method_ != nullptr);
+ return &method_;
+ }
+
mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -389,12 +394,7 @@ class ShadowFrame {
#endif
// Link to previous shadow frame or NULL.
ShadowFrame* link_;
-#if defined(ART_USE_PORTABLE_COMPILER)
- // TODO: make const in the portable case.
mirror::ArtMethod* method_;
-#else
- mirror::ArtMethod* const method_;
-#endif
uint32_t dex_pc_;
uint32_t vregs_[0];
@@ -518,6 +518,16 @@ class StackVisitor {
}
}
+ mirror::ArtMethod** GetMethodAddress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (cur_shadow_frame_ != nullptr) {
+ return cur_shadow_frame_->GetMethodAddress();
+ } else if (cur_quick_frame_ != nullptr) {
+ return cur_quick_frame_;
+ } else {
+ return nullptr;
+ }
+ }
+
bool IsShadowFrame() const {
return cur_shadow_frame_ != nullptr;
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d535118485..085a8e7f37 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1962,7 +1962,10 @@ class ReferenceMapVisitor : public StackVisitor {
}
void VisitShadowFrame(ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = shadow_frame->GetMethod();
+ mirror::ArtMethod** method_addr = shadow_frame->GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
+ DCHECK(m != nullptr);
size_t num_regs = shadow_frame->NumberOfVRegs();
if (m->IsNative() || shadow_frame->HasReferenceArray()) {
// handle scope for JNI or References for interpreter.
@@ -2003,7 +2006,9 @@ class ReferenceMapVisitor : public StackVisitor {
private:
void VisitQuickFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* m = GetMethod();
+ mirror::ArtMethod** method_addr = GetMethodAddress();
+ visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
+ mirror::ArtMethod* m = *method_addr;
// Process register map (which native and runtime methods don't have)
if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) {
const uint8_t* native_gc_map = m->GetNativeGcMap();