diff options
author | 2024-05-02 10:56:42 +0000 | |
---|---|---|
committer | 2024-05-03 03:44:33 +0000 | |
commit | db15ea652d13811e236e1f12c88807ebfed05da9 (patch) | |
tree | 85d01be01468cd684a01dc0ee2b349867f6f2d6a /runtime/interpreter/unstarted_runtime.cc | |
parent | f91d21c0b0e4a03102eaa6cfae0f500f8139bc40 (diff) |
Refactor transaction checks in switch interpreter.
Prepare for moving the transactional interpreter from
`runtime/` to `dex2oat/` by moving transaction checking code
to a new file `active_transaction_checker.h`, and breaking
unstarted runtime dependency on transaction code by adding
an indirection with a virtual call through `ClassLinker`.
Consistently return the same value from contraint checks.
Previously we were returning the negated result from the
`CheckWrite{,Value}Constraint()` compared to the value we
received from `Transaction::Write{,Value}Constraint()`.
Test: m test-art-host-gtest
Test: testrunner.py --host --interp-ac
Change-Id: I88a168b6c770932d014e3a40486480590cef0401
Diffstat (limited to 'runtime/interpreter/unstarted_runtime.cc')
-rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 7309391b32..2bdb5900b8 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -78,9 +78,10 @@ static void AbortTransactionOrFail(Thread* self, const char* fmt, ...) static void AbortTransactionOrFail(Thread* self, const char* fmt, ...) { va_list args; - if (Runtime::Current()->IsActiveTransaction()) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { va_start(args, fmt); - AbortTransactionV(self, fmt, args); + runtime->AbortTransactionV(self, fmt, args); va_end(args); } else { va_start(args, fmt); @@ -176,7 +177,7 @@ static void CheckExceptionGenerateClassNotFound(Thread* self) // initialize a class differently than when executing at run time. // If we're not aborting the transaction yet, abort now. b/183691501 if (!runtime->IsTransactionAborted()) { - AbortTransactionF(self, "ClassNotFoundException"); + runtime->AbortTransactionF(self, "ClassNotFoundException"); } } else { // If not in a transaction, it cannot be the transaction abort exception. Wrap it. @@ -301,12 +302,11 @@ void UnstartedRuntime::UnstartedClassNewInstance( } // If we're in a transaction, class must not be finalizable (it or a superclass has a finalizer). - if (Runtime::Current()->IsActiveTransaction()) { - if (h_klass->IsFinalizable()) { - AbortTransactionF(self, "Class for newInstance is finalizable: '%s'", - h_klass->PrettyClass().c_str()); - return; - } + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction() && + runtime->GetClassLinker()->TransactionAllocationConstraint(self, h_klass.Get())) { + DCHECK(self->IsExceptionPending()); + return; } // There are two situations in which we'll abort this run. @@ -314,7 +314,7 @@ void UnstartedRuntime::UnstartedClassNewInstance( // 2) If we can't find the default constructor. We'll postpone the exception to runtime. // Note that 2) could likely be handled here, but for safety abort the transaction. bool ok = false; - auto* cl = Runtime::Current()->GetClassLinker(); + auto* cl = runtime->GetClassLinker(); if (cl->EnsureInitialized(self, h_klass, true, true)) { ArtMethod* cons = h_klass->FindConstructor("()V", cl->GetImagePointerSize()); if (cons != nullptr && ShouldDenyAccessToMember(cons, shadow_frame)) { @@ -771,7 +771,7 @@ void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass( // If we're not aborting the transaction yet, abort now. b/183691501 // See CheckExceptionGenerateClassNotFound() for more detailed explanation. if (!runtime->IsTransactionAborted()) { - AbortTransactionF(self, "ClassNotFoundException"); + runtime->AbortTransactionF(self, "ClassNotFoundException"); } } else { // If not in a transaction, it cannot be the transaction abort exception. Clear it. @@ -855,7 +855,9 @@ void UnstartedRuntime::UnstartedSystemArraycopy(Thread* self, return; } - if (Runtime::Current()->IsActiveTransaction() && !CheckWriteConstraint(self, dst_obj)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction() && + runtime->GetClassLinker()->TransactionWriteConstraint(self, dst_obj)) { DCHECK(self->IsExceptionPending()); return; } @@ -1589,8 +1591,9 @@ void UnstartedRuntime::UnstartedJdkUnsafeCompareAndSwapLong( int64_t newValue = shadow_frame->GetVRegLong(arg_offset + 6); bool success; // Check whether we're in a transaction, call accordingly. - if (Runtime::Current()->IsActiveTransaction()) { - if (!CheckWriteConstraint(self, obj)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + if (runtime->GetClassLinker()->TransactionWriteConstraint(self, obj)) { DCHECK(self->IsExceptionPending()); return; } @@ -1635,8 +1638,10 @@ void UnstartedRuntime::UnstartedJdkUnsafeCompareAndSwapObject( } bool success; // Check whether we're in a transaction, call accordingly. - if (Runtime::Current()->IsActiveTransaction()) { - if (!CheckWriteConstraint(self, obj) || !CheckWriteValueConstraint(self, new_value)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + if (runtime->GetClassLinker()->TransactionWriteConstraint(self, obj) || + runtime->GetClassLinker()->TransactionWriteValueConstraint(self, new_value)) { DCHECK(self->IsExceptionPending()); return; } @@ -1682,8 +1687,10 @@ void UnstartedRuntime::UnstartedJdkUnsafePutReferenceVolatile(Thread* self, } int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2); mirror::Object* value = shadow_frame->GetVRegReference(arg_offset + 4); - if (Runtime::Current()->IsActiveTransaction()) { - if (!CheckWriteConstraint(self, obj) || !CheckWriteValueConstraint(self, value)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + if (runtime->GetClassLinker()->TransactionWriteConstraint(self, obj) || + runtime->GetClassLinker()->TransactionWriteValueConstraint(self, value)) { DCHECK(self->IsExceptionPending()); return; } @@ -1707,8 +1714,10 @@ void UnstartedRuntime::UnstartedJdkUnsafePutOrderedObject(Thread* self, int64_t offset = shadow_frame->GetVRegLong(arg_offset + 2); mirror::Object* new_value = shadow_frame->GetVRegReference(arg_offset + 4); std::atomic_thread_fence(std::memory_order_release); - if (Runtime::Current()->IsActiveTransaction()) { - if (!CheckWriteConstraint(self, obj) || !CheckWriteValueConstraint(self, new_value)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + if (runtime->GetClassLinker()->TransactionWriteConstraint(self, obj) || + runtime->GetClassLinker()->TransactionWriteValueConstraint(self, new_value)) { DCHECK(self->IsExceptionPending()); return; } @@ -2154,8 +2163,9 @@ void UnstartedRuntime::UnstartedJNIJdkUnsafeCompareAndSwapInt( jint expectedValue = args[3]; jint newValue = args[4]; bool success; - if (Runtime::Current()->IsActiveTransaction()) { - if (!CheckWriteConstraint(self, obj)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + if (runtime->GetClassLinker()->TransactionWriteConstraint(self, obj)) { DCHECK(self->IsExceptionPending()); return; } @@ -2211,8 +2221,10 @@ void UnstartedRuntime::UnstartedJNIJdkUnsafePutReference(Thread* self, } jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1]; ObjPtr<mirror::Object> new_value = reinterpret_cast32<mirror::Object*>(args[3]); - if (Runtime::Current()->IsActiveTransaction()) { - if (!CheckWriteConstraint(self, obj) || !CheckWriteValueConstraint(self, new_value)) { + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + if (runtime->GetClassLinker()->TransactionWriteConstraint(self, obj) || + runtime->GetClassLinker()->TransactionWriteValueConstraint(self, new_value)) { DCHECK(self->IsExceptionPending()); return; } @@ -2420,12 +2432,16 @@ void UnstartedRuntime::Jni(Thread* self, ArtMethod* method, mirror::Object* rece // Clear out the result in case it's not zeroed out. result->SetL(nullptr); (*iter->second)(self, method, receiver, args, result); - } else if (Runtime::Current()->IsActiveTransaction()) { - AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s", - ArtMethod::PrettyMethod(method).c_str()); } else { - LOG(FATAL) << "Calling native method " << ArtMethod::PrettyMethod(method) << " in an unstarted " - "non-transactional runtime"; + Runtime* runtime = Runtime::Current(); + if (runtime->IsActiveTransaction()) { + runtime->AbortTransactionF(self, + "Attempt to invoke native method in non-started runtime: %s", + ArtMethod::PrettyMethod(method).c_str()); + } else { + LOG(FATAL) << "Calling native method " << ArtMethod::PrettyMethod(method) + << " in an unstarted non-transactional runtime"; + } } } |