Change root visitor to use Object**.
Simplifies code and improves the performance of root visiting since
we usually don't need to check to see if the object moved.
Change-Id: Iba998f5a15ae1fa1b53ca5226dd2168a411196cf
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 5728391..16655fb 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1004,19 +1004,18 @@
}
}
-static mirror::Object* MonitorExitVisitor(mirror::Object* object, void* arg, uint32_t /*thread_id*/,
- RootType /*root_type*/)
+static void MonitorExitVisitor(mirror::Object** object, void* arg, uint32_t /*thread_id*/,
+ RootType /*root_type*/)
NO_THREAD_SAFETY_ANALYSIS {
Thread* self = reinterpret_cast<Thread*>(arg);
- mirror::Object* entered_monitor = object;
+ mirror::Object* entered_monitor = *object;
if (self->HoldsLock(entered_monitor)) {
LOG(WARNING) << "Calling MonitorExit on object "
- << object << " (" << PrettyTypeOf(object) << ")"
+ << object << " (" << PrettyTypeOf(entered_monitor) << ")"
<< " left locked by native thread "
<< *Thread::Current() << " which is detaching";
entered_monitor->MonitorExit(self);
}
- return object;
}
void Thread::Destroy() {
@@ -1167,10 +1166,10 @@
for (size_t j = 0; j < num_refs; ++j) {
mirror::Object* object = cur->GetReference(j);
if (object != nullptr) {
- mirror::Object* new_obj = visitor(object, arg, thread_id, kRootNativeStack);
- DCHECK(new_obj != nullptr);
- if (new_obj != object) {
- cur->SetReference(j, new_obj);
+ mirror::Object* old_obj = object;
+ visitor(&object, arg, thread_id, kRootNativeStack);
+ if (old_obj != object) {
+ cur->SetReference(j, object);
}
}
}
@@ -1888,7 +1887,8 @@
for (size_t reg = 0; reg < num_regs; ++reg) {
mirror::Object* ref = shadow_frame->GetVRegReference(reg);
if (ref != nullptr) {
- mirror::Object* new_ref = visitor_(ref, reg, this);
+ mirror::Object* new_ref = ref;
+ visitor_(&new_ref, reg, this);
if (new_ref != ref) {
shadow_frame->SetVRegReference(reg, new_ref);
}
@@ -1908,7 +1908,8 @@
if (TestBitmap(reg, reg_bitmap)) {
mirror::Object* ref = shadow_frame->GetVRegReference(reg);
if (ref != nullptr) {
- mirror::Object* new_ref = visitor_(ref, reg, this);
+ mirror::Object* new_ref = ref;
+ visitor_(&new_ref, reg, this);
if (new_ref != ref) {
shadow_frame->SetVRegReference(reg, new_ref);
}
@@ -1944,21 +1945,22 @@
uint32_t vmap_offset;
if (vmap_table.IsInContext(reg, kReferenceVReg, &vmap_offset)) {
int vmap_reg = vmap_table.ComputeRegister(core_spills, vmap_offset, kReferenceVReg);
- mirror::Object* ref = reinterpret_cast<mirror::Object*>(GetGPR(vmap_reg));
- if (ref != nullptr) {
- mirror::Object* new_ref = visitor_(ref, reg, this);
- if (ref != new_ref) {
- SetGPR(vmap_reg, reinterpret_cast<uintptr_t>(new_ref));
- }
+ // This is sound as spilled GPRs will be word sized (ie 32 or 64bit).
+ mirror::Object** ref_addr = reinterpret_cast<mirror::Object**>(GetGPRAddress(vmap_reg));
+ if (*ref_addr != nullptr) {
+ visitor_(ref_addr, reg, this);
}
} else {
- uintptr_t* reg_addr = reinterpret_cast<uintptr_t*>(
- GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size, reg));
- mirror::Object* ref = reinterpret_cast<mirror::Object*>(*reg_addr);
+ StackReference<mirror::Object>* ref_addr =
+ reinterpret_cast<StackReference<mirror::Object>*>(
+ GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size,
+ reg));
+ mirror::Object* ref = ref_addr->AsMirrorPtr();
if (ref != nullptr) {
- mirror::Object* new_ref = visitor_(ref, reg, this);
+ mirror::Object* new_ref = ref;
+ visitor_(&new_ref, reg, this);
if (ref != new_ref) {
- *reg_addr = reinterpret_cast<uintptr_t>(new_ref);
+ ref_addr->Assign(new_ref);
}
}
}
@@ -1971,8 +1973,8 @@
}
private:
- static bool TestBitmap(int reg, const uint8_t* reg_vector) {
- return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
+ static bool TestBitmap(size_t reg, const uint8_t* reg_vector) {
+ return ((reg_vector[reg / kBitsPerByte] >> (reg % kBitsPerByte)) & 0x01) != 0;
}
// Visitor for when we visit a root.
@@ -1987,8 +1989,8 @@
RootCallbackVisitor(RootCallback* callback, void* arg, uint32_t tid)
: callback_(callback), arg_(arg), tid_(tid) {}
- mirror::Object* operator()(mirror::Object* obj, size_t, const StackVisitor*) const {
- return callback_(obj, arg_, tid_, kRootJavaFrame);
+ void operator()(mirror::Object** obj, size_t, const StackVisitor*) const {
+ callback_(obj, arg_, tid_, kRootJavaFrame);
}
private:
@@ -2007,17 +2009,15 @@
void Thread::VisitRoots(RootCallback* visitor, void* arg) {
uint32_t thread_id = GetThreadId();
if (opeer_ != nullptr) {
- opeer_ = visitor(opeer_, arg, thread_id, kRootThreadObject);
+ visitor(&opeer_, arg, thread_id, kRootThreadObject);
}
if (exception_ != nullptr) {
- exception_ = down_cast<mirror::Throwable*>(visitor(exception_, arg, thread_id,
- kRootNativeStack));
+ visitor(reinterpret_cast<mirror::Object**>(&exception_), arg, thread_id, kRootNativeStack);
}
throw_location_.VisitRoots(visitor, arg);
if (class_loader_override_ != nullptr) {
- class_loader_override_ =
- down_cast<mirror::ClassLoader*>(visitor(class_loader_override_, arg, thread_id,
- kRootNativeStack));
+ visitor(reinterpret_cast<mirror::Object**>(&class_loader_override_), arg, thread_id,
+ kRootNativeStack);
}
jni_env_->locals.VisitRoots(visitor, arg, thread_id, kRootJNILocal);
jni_env_->monitors.VisitRoots(visitor, arg, thread_id, kRootJNIMonitor);
@@ -2030,20 +2030,18 @@
ReleaseLongJumpContext(context);
for (instrumentation::InstrumentationStackFrame& frame : *GetInstrumentationStack()) {
if (frame.this_object_ != nullptr) {
- frame.this_object_ = visitor(frame.this_object_, arg, thread_id, kRootJavaFrame);
+ visitor(&frame.this_object_, arg, thread_id, kRootJavaFrame);
}
DCHECK(frame.method_ != nullptr);
- frame.method_ = down_cast<mirror::ArtMethod*>(visitor(frame.method_, arg, thread_id,
- kRootJavaFrame));
+ visitor(reinterpret_cast<mirror::Object**>(&frame.method_), arg, thread_id, kRootJavaFrame);
}
}
-static mirror::Object* VerifyRoot(mirror::Object* root, void* arg, uint32_t /*thread_id*/,
- RootType /*root_type*/) {
+static void VerifyRoot(mirror::Object** root, void* arg, uint32_t /*thread_id*/,
+ RootType /*root_type*/) {
DCHECK(root != nullptr);
DCHECK(arg != nullptr);
- reinterpret_cast<gc::Heap*>(arg)->VerifyObject(root);
- return root;
+ reinterpret_cast<gc::Heap*>(arg)->VerifyObject(*root);
}
void Thread::VerifyStackImpl() {