summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-05-02 14:16:41 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-05-03 06:05:02 +0000
commit5a4566f39c3e22ecca1e88008af772c1a808ac9b (patch)
treec8f5697c8e708b2fa4ee82222c816097242933f3
parentdb15ea652d13811e236e1f12c88807ebfed05da9 (diff)
Clean up `Transaction` use in switch interpreter.
This is a follow-up to https://android-review.googlesource.com/3070189 to remove some more switch interpreter dependencies on the `Transaction` class. Test: m test-art-host-gtest Test: testrunner.py --host --interp-ac --optimizing Change-Id: I6f6bb470c727fb376b3552a3e15af7c8f0eea385
-rw-r--r--dex2oat/driver/compiler_driver.cc8
-rw-r--r--runtime/common_throws.h3
-rw-r--r--runtime/interpreter/active_transaction_checker.h29
-rw-r--r--runtime/interpreter/interpreter_common.cc1
-rw-r--r--runtime/interpreter/interpreter_common.h17
-rw-r--r--runtime/interpreter/interpreter_switch_impl-inl.h3
-rw-r--r--runtime/interpreter/unstarted_runtime.cc7
-rw-r--r--runtime/interpreter/unstarted_runtime_test.cc4
-rw-r--r--runtime/transaction.cc9
-rw-r--r--runtime/transaction.h2
-rw-r--r--runtime/transaction_test.cc4
11 files changed, 49 insertions, 38 deletions
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index e830e86d90..9ee7e64cad 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -43,6 +43,7 @@
#include "base/timing_logger.h"
#include "class_linker-inl.h"
#include "class_root-inl.h"
+#include "common_throws.h"
#include "compiled_method-inl.h"
#include "compiler.h"
#include "compiler_callbacks.h"
@@ -82,7 +83,6 @@
#include "thread_list.h"
#include "thread_pool.h"
#include "trampolines/trampoline_compiler.h"
-#include "transaction.h"
#include "utils/atomic_dex_ref_map-inl.h"
#include "utils/swap_space.h"
#include "vdex_file.h"
@@ -2329,10 +2329,8 @@ class InitializeClassVisitor : public CompilationVisitor {
// the transaction aborts and cannot resolve the type.
// TransactionAbortError is not initialized ant not in boot image, needed only by
// compiler and will be pruned by ImageWriter.
- Handle<mirror::Class> exception_class =
- hs.NewHandle(class_linker->FindClass(self,
- Transaction::kAbortExceptionDescriptor,
- class_loader));
+ Handle<mirror::Class> exception_class = hs.NewHandle(
+ class_linker->FindClass(self, kTransactionAbortErrorDescriptor, class_loader));
bool exception_initialized =
class_linker->EnsureInitialized(self, exception_class, true, true);
DCHECK(exception_initialized);
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index aeba3bb1bb..71b0968fc0 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -35,6 +35,9 @@ class DexFile;
enum InvokeType : uint32_t;
class Signature;
+// The descriptor of the transaction abort exception.
+constexpr const char kTransactionAbortErrorDescriptor[] = "Ldalvik/system/TransactionAbortError;";
+
// AbstractMethodError
void ThrowAbstractMethodError(ArtMethod* method)
diff --git a/runtime/interpreter/active_transaction_checker.h b/runtime/interpreter/active_transaction_checker.h
index 867dc251eb..16fa6b1829 100644
--- a/runtime/interpreter/active_transaction_checker.h
+++ b/runtime/interpreter/active_transaction_checker.h
@@ -33,10 +33,9 @@ class ActiveTransactionChecker {
Runtime* runtime = Runtime::Current();
if (runtime->GetTransaction()->WriteConstraint(obj)) {
DCHECK(runtime->GetHeap()->ObjectIsInBootImageSpace(obj) || obj->IsClass());
- const char* base_msg = runtime->GetHeap()->ObjectIsInBootImageSpace(obj)
- ? "Can't set fields of boot image "
- : "Can't set fields of ";
- runtime->AbortTransactionAndThrowAbortError(self, base_msg + obj->PrettyTypeOf());
+ const char* extra = runtime->GetHeap()->ObjectIsInBootImageSpace(obj) ? "boot image " : "";
+ runtime->AbortTransactionF(
+ self, "Can't set fields of %s%s", extra, obj->PrettyTypeOf().c_str());
return true;
}
return false;
@@ -47,10 +46,24 @@ class ActiveTransactionChecker {
Runtime* runtime = Runtime::Current();
if (runtime->GetTransaction()->WriteValueConstraint(value)) {
DCHECK(value != nullptr);
- std::string msg = value->IsClass()
- ? "Can't store reference to class " + value->AsClass()->PrettyDescriptor()
- : "Can't store reference to instance of " + value->GetClass()->PrettyDescriptor();
- runtime->AbortTransactionAndThrowAbortError(self, msg);
+ const char* description = value->IsClass() ? "class" : "instance of";
+ ObjPtr<mirror::Class> klass = value->IsClass() ? value->AsClass() : value->GetClass();
+ runtime->AbortTransactionF(
+ self, "Can't store reference to %s %s", description, klass->PrettyDescriptor().c_str());
+ return true;
+ }
+ return false;
+ }
+
+ static inline bool ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(obj->IsClass());
+ Runtime* runtime = Runtime::Current();
+ if (runtime->GetTransaction()->ReadConstraint(obj)) {
+ runtime->AbortTransactionF(
+ self,
+ "Can't read static fields of %s since it does not belong to clinit's class.",
+ obj->PrettyTypeOf().c_str());
return true;
}
return false;
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index ded500fd78..080b32f3d5 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -46,7 +46,6 @@
#include "shadow_frame-inl.h"
#include "stack.h"
#include "thread-inl.h"
-#include "transaction.h"
#include "var_handles.h"
#include "well_known_classes.h"
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index d2238d1d23..24fb8a83c4 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -20,7 +20,6 @@
#include "android-base/macros.h"
#include "instrumentation.h"
#include "interpreter.h"
-#include "transaction.h"
#include <math.h>
@@ -86,6 +85,12 @@ class InactiveTransactionChecker {
return false;
}
+ ALWAYS_INLINE static bool ReadConstraint([[maybe_unused]] Thread* self,
+ [[maybe_unused]] ObjPtr<mirror::Object> value)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return false;
+ }
+
ALWAYS_INLINE static bool AllocationConstraint([[maybe_unused]] Thread* self,
[[maybe_unused]] ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -397,12 +402,10 @@ ALWAYS_INLINE bool DoFieldGet(Thread* self,
ObjPtr<mirror::Object> obj;
if (is_static) {
obj = field->GetDeclaringClass();
- if (transaction_active) {
- if (Runtime::Current()->GetTransaction()->ReadConstraint(obj)) {
- Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Can't read static fields of "
- + obj->PrettyTypeOf() + " since it does not belong to clinit's class.");
- return false;
- }
+ using TransactionChecker = typename std::conditional_t<
+ transaction_active, ActiveTransactionChecker, InactiveTransactionChecker>;
+ if (TransactionChecker::ReadConstraint(self, obj)) {
+ return false;
}
} else {
obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index 0c50238e48..8ff6a897f8 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -23,6 +23,7 @@
#include "base/memory_tool.h"
#include "base/pointer_size.h"
#include "base/quasi_atomic.h"
+#include "common_throws.h"
#include "dex/dex_file_types.h"
#include "dex/dex_instruction_list.h"
#include "experimental_flags.h"
@@ -65,7 +66,7 @@ class InstructionHandler {
StackHandleScope<1u> hs(Self());
Handle<mirror::Throwable> abort_exception = hs.NewHandle(Self()->GetException());
DCHECK(abort_exception != nullptr);
- DCHECK(abort_exception->GetClass()->DescriptorEquals(Transaction::kAbortExceptionDescriptor));
+ DCHECK(abort_exception->GetClass()->DescriptorEquals(kTransactionAbortErrorDescriptor));
Self()->ClearException();
PerformNonStandardReturn(
Self(), shadow_frame_, ctx_->result, Instrumentation(), Accessor().InsSize());
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 2bdb5900b8..d865327473 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -62,7 +62,6 @@
#include "nth_caller_visitor.h"
#include "reflection.h"
#include "thread-inl.h"
-#include "transaction.h"
#include "unstarted_runtime_list.h"
#include "well_known_classes-inl.h"
@@ -167,8 +166,7 @@ static void CheckExceptionGenerateClassNotFound(Thread* self)
if (self->IsExceptionPending()) {
Runtime* runtime = Runtime::Current();
DCHECK_EQ(runtime->IsTransactionAborted(),
- self->GetException()->GetClass()->DescriptorEquals(
- Transaction::kAbortExceptionDescriptor))
+ self->GetException()->GetClass()->DescriptorEquals(kTransactionAbortErrorDescriptor))
<< self->GetException()->GetClass()->PrettyDescriptor();
if (runtime->IsActiveTransaction()) {
// The boot class path at run time may contain additional dex files with
@@ -764,8 +762,7 @@ void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
if (self->IsExceptionPending()) {
Runtime* runtime = Runtime::Current();
DCHECK_EQ(runtime->IsTransactionAborted(),
- self->GetException()->GetClass()->DescriptorEquals(
- Transaction::kAbortExceptionDescriptor))
+ self->GetException()->GetClass()->DescriptorEquals(kTransactionAbortErrorDescriptor))
<< self->GetException()->GetClass()->PrettyDescriptor();
if (runtime->IsActiveTransaction()) {
// If we're not aborting the transaction yet, abort now. b/183691501
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 494eb756a4..44c1e2627a 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -25,6 +25,7 @@
#include "class_linker.h"
#include "class_root-inl.h"
#include "common_runtime_test.h"
+#include "common_throws.h"
#include "dex/descriptors_names.h"
#include "dex/dex_instruction.h"
#include "handle.h"
@@ -42,7 +43,6 @@
#include "scoped_thread_state_change-inl.h"
#include "shadow_frame-inl.h"
#include "thread.h"
-#include "transaction.h"
#include "unstarted_runtime_list.h"
namespace art HIDDEN {
@@ -216,7 +216,7 @@ class UnstartedRuntimeTest : public CommonRuntimeTest {
void PrepareForAborts() REQUIRES_SHARED(Locks::mutator_lock_) {
ObjPtr<mirror::Object> result = Runtime::Current()->GetClassLinker()->FindClass(
Thread::Current(),
- Transaction::kAbortExceptionDescriptor,
+ kTransactionAbortErrorDescriptor,
ScopedNullHandle<mirror::ClassLoader>());
CHECK(result != nullptr);
}
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index d320c4d940..9a8fcd9739 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -20,6 +20,7 @@
#include "base/mutex-inl.h"
#include "base/stl_util.h"
+#include "common_throws.h"
#include "dex/descriptors_names.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
@@ -104,17 +105,15 @@ void Transaction::Abort(const std::string& abort_message) {
void Transaction::ThrowAbortError(Thread* self, const std::string* abort_message) {
const bool rethrow = (abort_message == nullptr);
if (kIsDebugBuild && rethrow) {
- CHECK(IsAborted()) << "Rethrow " << DescriptorToDot(Transaction::kAbortExceptionDescriptor)
+ CHECK(IsAborted()) << "Rethrow " << DescriptorToDot(kTransactionAbortErrorDescriptor)
<< " while transaction is not aborted";
}
if (rethrow) {
// Rethrow an exception with the earlier abort message stored in the transaction.
- self->ThrowNewWrappedException(Transaction::kAbortExceptionDescriptor,
- GetAbortMessage().c_str());
+ self->ThrowNewWrappedException(kTransactionAbortErrorDescriptor, GetAbortMessage().c_str());
} else {
// Throw an exception with the given abort message.
- self->ThrowNewWrappedException(Transaction::kAbortExceptionDescriptor,
- abort_message->c_str());
+ self->ThrowNewWrappedException(kTransactionAbortErrorDescriptor, abort_message->c_str());
}
}
diff --git a/runtime/transaction.h b/runtime/transaction.h
index 9f3282f8d9..847120234d 100644
--- a/runtime/transaction.h
+++ b/runtime/transaction.h
@@ -46,8 +46,6 @@ template<class MirrorType> class ObjPtr;
class Transaction final {
public:
- static constexpr const char* kAbortExceptionDescriptor = "Ldalvik/system/TransactionAbortError;";
-
Transaction(bool strict, mirror::Class* root, ArenaStack* arena_stack, ArenaPool* arena_pool);
~Transaction();
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index c4eb7e808b..db9d123521 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -20,6 +20,7 @@
#include "art_method-inl.h"
#include "class_linker-inl.h"
#include "common_runtime_test.h"
+#include "common_throws.h"
#include "dex/dex_file.h"
#include "mirror/array-alloc-inl.h"
#include "mirror/class-alloc-inl.h"
@@ -52,8 +53,7 @@ class TransactionTest : public CommonRuntimeTest {
class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
ASSERT_TRUE(h_klass->IsInitialized());
- h_klass.Assign(class_linker_->FindSystemClass(soa.Self(),
- Transaction::kAbortExceptionDescriptor));
+ h_klass.Assign(class_linker_->FindSystemClass(soa.Self(), kTransactionAbortErrorDescriptor));
ASSERT_TRUE(h_klass != nullptr);
class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
ASSERT_TRUE(h_klass->IsInitialized());