Update Transaction for boot image extension.
And clean up transaction-related code to keep test code
out of the production binaries.
Test: Add TransactionTest#Constraints to transaction_test.
Test: m test-art-host-gtest
Test: testrunner.py --host
Test: aosp_taimen-userdebug boots.
Change-Id: Iefe5f1cfde95f564069249148f9e7d71564d7a10
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index c534a42..9a51e0f 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -21,12 +21,15 @@
#include "base/mutex-inl.h"
#include "base/stl_util.h"
#include "gc/accounting/card_table-inl.h"
+#include "gc/heap.h"
#include "gc_root-inl.h"
#include "intern_table.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
+#include "obj_ptr-inl.h"
+#include "runtime.h"
#include <list>
@@ -35,17 +38,14 @@
// TODO: remove (only used for debugging purpose).
static constexpr bool kEnableTransactionStats = false;
-Transaction::Transaction()
- : log_lock_("transaction log lock", kTransactionLogLock),
- aborted_(false),
- rolling_back_(false),
- strict_(false) {
- CHECK(Runtime::Current()->IsAotCompiler());
-}
-
-Transaction::Transaction(bool strict, mirror::Class* root) : Transaction() {
- strict_ = strict;
- root_ = root;
+Transaction::Transaction(bool strict, mirror::Class* root)
+ : log_lock_("transaction log lock", kTransactionLogLock),
+ aborted_(false),
+ rolling_back_(false),
+ heap_(strict ? nullptr : Runtime::Current()->GetHeap()),
+ root_(root) {
+ DCHECK_EQ(strict, IsStrict());
+ DCHECK(Runtime::Current()->IsAotCompiler());
}
Transaction::~Transaction() {
@@ -111,35 +111,33 @@
return rolling_back_;
}
-bool Transaction::IsStrict() {
- MutexLock mu(Thread::Current(), log_lock_);
- return strict_;
-}
-
const std::string& Transaction::GetAbortMessage() {
MutexLock mu(Thread::Current(), log_lock_);
return abort_message_;
}
-bool Transaction::WriteConstraint(mirror::Object* obj, ArtField* field) {
- MutexLock mu(Thread::Current(), log_lock_);
- if (strict_ // no constraint for boot image
- && field->IsStatic() // no constraint instance updating
- && obj != root_) { // modifying other classes' static field, fail
- return true;
+bool Transaction::WriteConstraint(Thread* self, ObjPtr<mirror::Object> obj, ArtField* field) {
+ MutexLock mu(self, log_lock_);
+ if (IsStrict()) {
+ return field->IsStatic() && // no constraint instance updating
+ obj != root_; // modifying other classes' static field, fail
+ } else {
+ // For boot image extension, prevent changes in boot image.
+ // For boot image there are no boot image spaces and this returns false.
+ return heap_->ObjectIsInBootImageSpace(obj);
}
- return false;
}
-bool Transaction::ReadConstraint(mirror::Object* obj, ArtField* field) {
+bool Transaction::ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj, ArtField* field) {
DCHECK(field->IsStatic());
DCHECK(obj->IsClass());
- MutexLock mu(Thread::Current(), log_lock_);
- if (!strict_ || // no constraint for boot image
- obj == root_) { // self-updating, pass
+ MutexLock mu(self, log_lock_);
+ if (IsStrict()) {
+ return obj != root_; // fail if not self-updating
+ } else {
+ // For boot image and boot image extension, allow reading any field.
return false;
}
- return true;
}
void Transaction::RecordWriteFieldBoolean(mirror::Object* obj,