203 lines
7.9 KiB
C++
203 lines
7.9 KiB
C++
/* Copyright (C) 2017 The Android Open Source Project
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This file implements interfaces from the file jvmti.h. This implementation
|
|
* is licensed under the same terms as the file jvmti.h. The
|
|
* copyright and license information for the file jvmti.h follows.
|
|
*
|
|
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
#ifndef ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
|
|
#define ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
|
|
|
|
#include <atomic>
|
|
#include <iosfwd>
|
|
#include <unordered_map>
|
|
|
|
#include "base/mutex.h"
|
|
#include "runtime_callbacks.h"
|
|
|
|
#include <jvmti.h>
|
|
|
|
namespace art {
|
|
class ArtMethod;
|
|
class ScopedObjectAccessUnchecked;
|
|
namespace mirror {
|
|
class Class;
|
|
} // namespace mirror
|
|
} // namespace art
|
|
|
|
namespace openjdkjvmti {
|
|
|
|
class DeoptManager;
|
|
|
|
struct JvmtiMethodInspectionCallback : public art::MethodInspectionCallback {
|
|
public:
|
|
explicit JvmtiMethodInspectionCallback(DeoptManager* manager) : manager_(manager) {}
|
|
|
|
bool IsMethodBeingInspected(art::ArtMethod* method)
|
|
override REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
bool IsMethodSafeToJit(art::ArtMethod* method)
|
|
override REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
bool MethodNeedsDebugVersion(art::ArtMethod* method)
|
|
override REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
private:
|
|
DeoptManager* manager_;
|
|
};
|
|
|
|
class ScopedDeoptimizationContext;
|
|
|
|
class DeoptManager {
|
|
public:
|
|
DeoptManager();
|
|
|
|
void Setup();
|
|
void Shutdown();
|
|
|
|
void DumpDeoptInfo(art::Thread* self, std::ostream& stream);
|
|
|
|
void RemoveDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
|
|
!art::Roles::uninterruptible_);
|
|
void AddDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
|
|
!art::Roles::uninterruptible_);
|
|
bool MethodHasBreakpoints(art::ArtMethod* method)
|
|
REQUIRES(!deoptimization_status_lock_);
|
|
|
|
void RemoveMethodBreakpoint(art::ArtMethod* method)
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
void AddMethodBreakpoint(art::ArtMethod* method)
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
void AddDeoptimizeAllMethods()
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
void RemoveDeoptimizeAllMethods()
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
jvmtiError AddDeoptimizeThreadMethods(art::ScopedObjectAccessUnchecked& soa, jthread thread)
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
jvmtiError RemoveDeoptimizeThreadMethods(art::ScopedObjectAccessUnchecked& soa, jthread thread)
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
void DeoptimizeThread(art::Thread* target)
|
|
REQUIRES(!art::Locks::thread_list_lock_)
|
|
REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
void DeoptimizeAllThreads() REQUIRES_SHARED(art::Locks::mutator_lock_);
|
|
|
|
void FinishSetup()
|
|
REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
|
|
REQUIRES(art::Locks::mutator_lock_);
|
|
|
|
static DeoptManager* Get();
|
|
|
|
bool HaveLocalsChanged() const {
|
|
return set_local_variable_called_.load();
|
|
}
|
|
|
|
void SetLocalsUpdated() {
|
|
set_local_variable_called_.store(true);
|
|
}
|
|
|
|
private:
|
|
bool MethodHasBreakpointsLocked(art::ArtMethod* method)
|
|
REQUIRES(breakpoint_status_lock_);
|
|
|
|
// Wait until nothing is currently in the middle of deoptimizing/undeoptimizing something. This is
|
|
// needed to ensure that everything is synchronized since threads need to drop the
|
|
// deoptimization_status_lock_ while deoptimizing methods.
|
|
void WaitForDeoptimizationToFinish(art::Thread* self)
|
|
RELEASE(deoptimization_status_lock_) REQUIRES(!art::Locks::mutator_lock_);
|
|
|
|
void WaitForDeoptimizationToFinishLocked(art::Thread* self)
|
|
REQUIRES(deoptimization_status_lock_, !art::Locks::mutator_lock_);
|
|
|
|
void AddDeoptimizeAllMethodsLocked(art::Thread* self)
|
|
RELEASE(deoptimization_status_lock_)
|
|
REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
|
|
|
|
void RemoveDeoptimizeAllMethodsLocked(art::Thread* self)
|
|
RELEASE(deoptimization_status_lock_)
|
|
REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
|
|
|
|
void PerformGlobalDeoptimization(art::Thread* self)
|
|
RELEASE(deoptimization_status_lock_)
|
|
REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
|
|
|
|
void PerformGlobalUndeoptimization(art::Thread* self)
|
|
RELEASE(deoptimization_status_lock_)
|
|
REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
|
|
|
|
void PerformLimitedDeoptimization(art::Thread* self, art::ArtMethod* method)
|
|
RELEASE(deoptimization_status_lock_)
|
|
REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
|
|
|
|
void PerformLimitedUndeoptimization(art::Thread* self, art::ArtMethod* method)
|
|
RELEASE(deoptimization_status_lock_)
|
|
REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
|
|
|
|
static constexpr const char* kDeoptManagerInstrumentationKey = "JVMTI_DeoptManager";
|
|
|
|
art::Mutex deoptimization_status_lock_ ACQUIRED_BEFORE(art::Locks::classlinker_classes_lock_);
|
|
art::ConditionVariable deoptimization_condition_ GUARDED_BY(deoptimization_status_lock_);
|
|
bool performing_deoptimization_ GUARDED_BY(deoptimization_status_lock_);
|
|
|
|
// Number of times we have gotten requests to deopt everything.
|
|
uint32_t global_deopt_count_ GUARDED_BY(deoptimization_status_lock_);
|
|
|
|
// Number of users of deoptimization there currently are.
|
|
uint32_t deopter_count_ GUARDED_BY(deoptimization_status_lock_);
|
|
|
|
// A mutex that just protects the breakpoint-status map. This mutex should always be at the
|
|
// bottom of the lock hierarchy. Nothing more should be locked if we hold this.
|
|
art::Mutex breakpoint_status_lock_ ACQUIRED_BEFORE(art::Locks::abort_lock_);
|
|
// A map from methods to the number of breakpoints in them from all envs.
|
|
std::unordered_map<art::ArtMethod*, uint32_t> breakpoint_status_
|
|
GUARDED_BY(breakpoint_status_lock_);
|
|
|
|
// The MethodInspectionCallback we use to tell the runtime if we care about particular methods.
|
|
JvmtiMethodInspectionCallback inspection_callback_;
|
|
|
|
// Set to true if anything calls SetLocalVariables on any thread since we need to be careful about
|
|
// OSR after this.
|
|
std::atomic<bool> set_local_variable_called_;
|
|
|
|
// Helper for setting up/tearing-down for deoptimization.
|
|
friend class ScopedDeoptimizationContext;
|
|
};
|
|
|
|
} // namespace openjdkjvmti
|
|
#endif // ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
|