Add GcRoot to clean up and enforce read barriers.
Introduce a value-type wrapper around Object* for GC roots so that 1)
we won't have to directly add the read barrier code in many places and
2) we can avoid accidentally bypassing/missing read barriers on GC
roots (the GcRoot interface ensures that the read barrier is executed
on a read).
The jdwp test passed.
Bug: 12687968
Change-Id: Ib167c7c325b3c7e3900133578815f04d219972a1
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1cbf841..e34a2d7 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -95,11 +95,7 @@
Runtime* Runtime::instance_ = NULL;
Runtime::Runtime()
- : pre_allocated_OutOfMemoryError_(nullptr),
- resolution_method_(nullptr),
- imt_conflict_method_(nullptr),
- default_imt_(nullptr),
- instruction_set_(kNone),
+ : instruction_set_(kNone),
compiler_callbacks_(nullptr),
is_zygote_(false),
must_relocate_(false),
@@ -147,9 +143,6 @@
implicit_null_checks_(false),
implicit_so_checks_(false),
implicit_suspend_checks_(false) {
- for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
- callee_save_methods_[i] = nullptr;
- }
}
Runtime::~Runtime() {
@@ -716,7 +709,7 @@
self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;",
"OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
"no stack available");
- pre_allocated_OutOfMemoryError_ = self->GetException(NULL);
+ pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException(NULL));
self->ClearException();
// Look for a native bridge.
@@ -931,8 +924,7 @@
}
mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() {
- mirror::Throwable* oome = ReadBarrier::BarrierForRoot<mirror::Throwable, kWithReadBarrier>(
- &pre_allocated_OutOfMemoryError_);
+ mirror::Throwable* oome = pre_allocated_OutOfMemoryError_.Read();
if (oome == NULL) {
LOG(ERROR) << "Failed to return pre-allocated OOME";
}
@@ -971,23 +963,21 @@
void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) {
java_vm_->VisitRoots(callback, arg);
- if (pre_allocated_OutOfMemoryError_ != nullptr) {
- callback(reinterpret_cast<mirror::Object**>(&pre_allocated_OutOfMemoryError_), arg, 0,
- kRootVMInternal);
- DCHECK(pre_allocated_OutOfMemoryError_ != nullptr);
+ if (!pre_allocated_OutOfMemoryError_.IsNull()) {
+ pre_allocated_OutOfMemoryError_.VisitRoot(callback, arg, 0, kRootVMInternal);
+ DCHECK(!pre_allocated_OutOfMemoryError_.IsNull());
}
- callback(reinterpret_cast<mirror::Object**>(&resolution_method_), arg, 0, kRootVMInternal);
- DCHECK(resolution_method_ != nullptr);
+ resolution_method_.VisitRoot(callback, arg, 0, kRootVMInternal);
+ DCHECK(!resolution_method_.IsNull());
if (HasImtConflictMethod()) {
- callback(reinterpret_cast<mirror::Object**>(&imt_conflict_method_), arg, 0, kRootVMInternal);
+ imt_conflict_method_.VisitRoot(callback, arg, 0, kRootVMInternal);
}
if (HasDefaultImt()) {
- callback(reinterpret_cast<mirror::Object**>(&default_imt_), arg, 0, kRootVMInternal);
+ default_imt_.VisitRoot(callback, arg, 0, kRootVMInternal);
}
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
- if (callee_save_methods_[i] != nullptr) {
- callback(reinterpret_cast<mirror::Object**>(&callee_save_methods_[i]), arg, 0,
- kRootVMInternal);
+ if (!callee_save_methods_[i].IsNull()) {
+ callee_save_methods_[i].VisitRoot(callback, arg, 0, kRootVMInternal);
}
}
{
@@ -1125,7 +1115,7 @@
void Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type) {
DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
- callee_save_methods_[type] = method;
+ callee_save_methods_[type] = GcRoot<mirror::ArtMethod>(method);
}
const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) {