diff options
Diffstat (limited to 'openjdkjvmti/transform.cc')
-rw-r--r-- | openjdkjvmti/transform.cc | 173 |
1 files changed, 0 insertions, 173 deletions
diff --git a/openjdkjvmti/transform.cc b/openjdkjvmti/transform.cc index 9c440ef367..753697dbe6 100644 --- a/openjdkjvmti/transform.cc +++ b/openjdkjvmti/transform.cc @@ -70,185 +70,13 @@ namespace openjdkjvmti { -// A FaultHandler that will deal with initializing ClassDefinitions when they are actually needed. -class TransformationFaultHandler final : public art::FaultHandler { - public: - explicit TransformationFaultHandler(art::FaultManager* manager) - : art::FaultHandler(manager), - uninitialized_class_definitions_lock_("JVMTI Initialized class definitions lock", - art::LockLevel::kSignalHandlingLock), - class_definition_initialized_cond_("JVMTI Initialized class definitions condition", - uninitialized_class_definitions_lock_) { - manager->AddHandler(this, /* generated_code= */ false); - } - - ~TransformationFaultHandler() { - art::MutexLock mu(art::Thread::Current(), uninitialized_class_definitions_lock_); - uninitialized_class_definitions_.clear(); - } - - bool Action(int sig, siginfo_t* siginfo, void* context ATTRIBUTE_UNUSED) override { - DCHECK_EQ(sig, SIGSEGV); - art::Thread* self = art::Thread::Current(); - uintptr_t ptr = reinterpret_cast<uintptr_t>(siginfo->si_addr); - if (UNLIKELY(uninitialized_class_definitions_lock_.IsExclusiveHeld(self))) { - // It's possible this is just some other unrelated segv that should be - // handled separately, continue to later handlers. This is likely due to - // running out of memory somewhere along the FixedUpDexFile pipeline and - // is likely unrecoverable. By returning false here though we will get a - // better, more accurate, stack-trace later that points to the actual - // issue. - LOG(WARNING) << "Recursive SEGV occurred during Transformation dequickening at 0x" << std::hex - << ptr; - return false; - } - ArtClassDefinition* res = nullptr; - - { - // NB Technically using a mutex and condition variables here is non-posix compliant but - // everything should be fine since both glibc and bionic implementations of mutexs and - // condition variables work fine so long as the thread was not interrupted during a - // lock/unlock (which it wasn't) on all architectures we care about. - art::MutexLock mu(self, uninitialized_class_definitions_lock_); - auto it = std::find_if(uninitialized_class_definitions_.begin(), - uninitialized_class_definitions_.end(), - [&](const auto op) { return op->ContainsAddress(ptr); }); - if (it != uninitialized_class_definitions_.end()) { - res = *it; - // Remove the class definition. - uninitialized_class_definitions_.erase(it); - // Put it in the initializing list - initializing_class_definitions_.push_back(res); - } else { - // Wait for the ptr to be initialized (if it is currently initializing). - while (DefinitionIsInitializing(ptr)) { - WaitForClassInitializationToFinish(); - } - // Return true (continue with user code) if we find that the definition has been - // initialized. Return false (continue on to next signal handler) if the definition is not - // initialized or found. - return std::find_if(initialized_class_definitions_.begin(), - initialized_class_definitions_.end(), - [&](const auto op) { return op->ContainsAddress(ptr); }) != - initialized_class_definitions_.end(); - } - } - - if (LIKELY(self != nullptr)) { - CHECK_EQ(self->GetState(), art::ThreadState::kNative) - << "Transformation fault handler occurred outside of native mode"; - } - - VLOG(signals) << "Lazy initialization of dex file for transformation of " << res->GetName() - << " during SEGV"; - res->InitializeMemory(); - - { - art::MutexLock mu(self, uninitialized_class_definitions_lock_); - // Move to initialized state and notify waiters. - initializing_class_definitions_.erase(std::find(initializing_class_definitions_.begin(), - initializing_class_definitions_.end(), - res)); - initialized_class_definitions_.push_back(res); - class_definition_initialized_cond_.Broadcast(self); - } - - return true; - } - - void RemoveDefinition(ArtClassDefinition* def) REQUIRES(!uninitialized_class_definitions_lock_) { - art::MutexLock mu(art::Thread::Current(), uninitialized_class_definitions_lock_); - auto it = std::find(uninitialized_class_definitions_.begin(), - uninitialized_class_definitions_.end(), - def); - if (it != uninitialized_class_definitions_.end()) { - uninitialized_class_definitions_.erase(it); - return; - } - while (std::find(initializing_class_definitions_.begin(), - initializing_class_definitions_.end(), - def) != initializing_class_definitions_.end()) { - WaitForClassInitializationToFinish(); - } - it = std::find(initialized_class_definitions_.begin(), - initialized_class_definitions_.end(), - def); - CHECK(it != initialized_class_definitions_.end()) << "Could not find class definition for " - << def->GetName(); - initialized_class_definitions_.erase(it); - } - - void AddArtDefinition(ArtClassDefinition* def) REQUIRES(!uninitialized_class_definitions_lock_) { - DCHECK(def->IsLazyDefinition()); - art::MutexLock mu(art::Thread::Current(), uninitialized_class_definitions_lock_); - uninitialized_class_definitions_.push_back(def); - } - - private: - bool DefinitionIsInitializing(uintptr_t ptr) REQUIRES(uninitialized_class_definitions_lock_) { - return std::find_if(initializing_class_definitions_.begin(), - initializing_class_definitions_.end(), - [&](const auto op) { return op->ContainsAddress(ptr); }) != - initializing_class_definitions_.end(); - } - - void WaitForClassInitializationToFinish() REQUIRES(uninitialized_class_definitions_lock_) { - class_definition_initialized_cond_.Wait(art::Thread::Current()); - } - - art::Mutex uninitialized_class_definitions_lock_ ACQUIRED_BEFORE(art::Locks::abort_lock_); - art::ConditionVariable class_definition_initialized_cond_ - GUARDED_BY(uninitialized_class_definitions_lock_); - - // A list of the class definitions that have a non-readable map. - std::vector<ArtClassDefinition*> uninitialized_class_definitions_ - GUARDED_BY(uninitialized_class_definitions_lock_); - - // A list of class definitions that are currently undergoing unquickening. Threads should wait - // until the definition is no longer in this before returning. - std::vector<ArtClassDefinition*> initializing_class_definitions_ - GUARDED_BY(uninitialized_class_definitions_lock_); - - // A list of class definitions that are already unquickened. Threads should immediately return if - // it is here. - std::vector<ArtClassDefinition*> initialized_class_definitions_ - GUARDED_BY(uninitialized_class_definitions_lock_); -}; - -static TransformationFaultHandler* gTransformFaultHandler = nullptr; static EventHandler* gEventHandler = nullptr; void Transformer::Register(EventHandler* eh) { - // Although we create this the fault handler is actually owned by the 'art::fault_manager' which - // will take care of destroying it. - if (art::MemMap::kCanReplaceMapping && ArtClassDefinition::kEnableOnDemandDexDequicken) { - gTransformFaultHandler = new TransformationFaultHandler(&art::fault_manager); - } gEventHandler = eh; } -// Simple helper to add and remove the class definition from the fault handler. -class ScopedDefinitionHandler { - public: - explicit ScopedDefinitionHandler(ArtClassDefinition* def) - : def_(def), is_lazy_(def_->IsLazyDefinition()) { - if (is_lazy_) { - gTransformFaultHandler->AddArtDefinition(def_); - } - } - - ~ScopedDefinitionHandler() { - if (is_lazy_) { - gTransformFaultHandler->RemoveDefinition(def_); - } - } - - private: - ArtClassDefinition* def_; - bool is_lazy_; -}; - // Initialize templates. template void Transformer::TransformSingleClassDirect<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>( @@ -272,7 +100,6 @@ void Transformer::TransformSingleClassDirect(EventHandler* event_handler, // native state early. This also avoids any problems that the FaultHandler might have in // determining if an access to the dex_data is from generated code or not. art::ScopedThreadStateChange stsc(self, art::ThreadState::kNative); - ScopedDefinitionHandler handler(def); jint new_len = -1; unsigned char* new_data = nullptr; art::ArrayRef<const unsigned char> dex_data = def->GetDexData(); |