blob: 1f1052114405d102b9aa8c2913ad7124060aa92a [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_
#define ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_
#include <android-base/logging.h>
#include <array>
#include <compare>
#include <functional>
#include <stack>
#include "android-base/macros.h"
#include "base/enums.h"
#include "base/globals.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "reflective_handle.h"
#include "reflective_reference.h"
#include "reflective_value_visitor.h"
namespace art HIDDEN {
class ArtField;
class ArtMethod;
class BaseReflectiveHandleScope;
class Thread;
// This is a holder similar to StackHandleScope that is used to hold reflective references to
// ArtField and ArtMethod structures. A reflective reference is one that must be updated if the
// underlying class or instances are replaced due to structural redefinition or some other process.
// In general these don't need to be used. It's only when it's important that a reference to a field
// not become obsolete and it needs to be held over a suspend point that this should be used. This
// takes care of the book-keeping to allow the runtime to visit and update ReflectiveHandles when
// structural redefinition occurs.
class BaseReflectiveHandleScope {
public:
template <typename Visitor>
ALWAYS_INLINE void VisitTargets(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
FunctionReflectiveValueVisitor v(&visitor);
VisitTargets(&v);
}
ALWAYS_INLINE virtual ~BaseReflectiveHandleScope() {
DCHECK(link_ == nullptr);
}
virtual void VisitTargets(ReflectiveValueVisitor* visitor)
REQUIRES_SHARED(Locks::mutator_lock_) = 0;
BaseReflectiveHandleScope* GetLink() {
return link_;
}
Thread* GetThread() {
return self_;
}
void Describe(std::ostream& os) const;
protected:
ALWAYS_INLINE BaseReflectiveHandleScope() : self_(nullptr), link_(nullptr) {}
ALWAYS_INLINE inline void PushScope(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE inline void PopScope() REQUIRES_SHARED(Locks::mutator_lock_);
// Thread this node is rooted in.
Thread* self_;
// Next node in the handle-scope linked list. Root is held by Thread.
BaseReflectiveHandleScope* link_;
private:
DISALLOW_COPY_AND_ASSIGN(BaseReflectiveHandleScope);
};
std::ostream& operator<<(std::ostream& os, const BaseReflectiveHandleScope& brhs);
template <size_t kNumFields, size_t kNumMethods>
class StackReflectiveHandleScope : public BaseReflectiveHandleScope {
private:
static constexpr bool kHasFields = kNumFields > 0;
static constexpr bool kHasMethods = kNumMethods > 0;
public:
ALWAYS_INLINE explicit StackReflectiveHandleScope(Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE ~StackReflectiveHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);
void VisitTargets(ReflectiveValueVisitor* visitor) override REQUIRES_SHARED(Locks::mutator_lock_);
template <typename T,
typename = typename std::enable_if_t<(kHasFields && std::is_same_v<T, ArtField>) ||
(kHasMethods && std::is_same_v<T, ArtMethod>)>>
ALWAYS_INLINE MutableReflectiveHandle<T> NewHandle(T* t) REQUIRES_SHARED(Locks::mutator_lock_) {
if constexpr (std::is_same_v<T, ArtField>) {
return NewFieldHandle(t);
} else {
static_assert(std::is_same_v<T, ArtMethod>, "Expected ArtField or ArtMethod");
return NewMethodHandle(t);
}
}
template<typename T>
ALWAYS_INLINE ReflectiveHandleWrapper<T> NewReflectiveHandleWrapper(T** t)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
return ReflectiveHandleWrapper<T>(t, NewHandle(*t));
}
ALWAYS_INLINE MutableReflectiveHandle<ArtField> NewFieldHandle(ArtField* f)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
static_assert(kHasFields, "No fields");
DCHECK_LT(field_pos_, kNumFields);
MutableReflectiveHandle<ArtField> fh(GetMutableFieldHandle(field_pos_++));
fh.Assign(f);
return fh;
}
ALWAYS_INLINE ReflectiveHandleWrapper<ArtField> NewReflectiveFieldHandleWrapper(ArtField** f)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
return ReflectiveHandleWrapper<ArtField>(f, NewMethodHandle(*f));
}
ALWAYS_INLINE ArtField* GetField(size_t i) {
static_assert(kHasFields, "No fields");
return GetFieldReference(i)->Ptr();
}
ALWAYS_INLINE ReflectiveHandle<ArtField> GetFieldHandle(size_t i) {
static_assert(kHasFields, "No fields");
return ReflectiveHandle<ArtField>(GetFieldReference(i));
}
ALWAYS_INLINE MutableReflectiveHandle<ArtField> GetMutableFieldHandle(size_t i) {
static_assert(kHasFields, "No fields");
return MutableReflectiveHandle<ArtField>(GetFieldReference(i));
}
ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> NewMethodHandle(ArtMethod* m)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
static_assert(kHasMethods, "No methods");
DCHECK_LT(method_pos_, kNumMethods);
MutableReflectiveHandle<ArtMethod> mh(GetMutableMethodHandle(method_pos_++));
mh.Assign(m);
return mh;
}
ALWAYS_INLINE ReflectiveHandleWrapper<ArtMethod> NewReflectiveMethodHandleWrapper(ArtMethod** m)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
return ReflectiveHandleWrapper<ArtMethod>(m, NewMethodHandle(*m));
}
ALWAYS_INLINE ArtMethod* GetMethod(size_t i) {
static_assert(kHasMethods, "No methods");
return GetMethodReference(i)->Ptr();
}
ALWAYS_INLINE ReflectiveHandle<ArtMethod> GetMethodHandle(size_t i) {
static_assert(kHasMethods, "No methods");
return ReflectiveHandle<ArtMethod>(GetMethodReference(i));
}
ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> GetMutableMethodHandle(size_t i) {
static_assert(kHasMethods, "No methods");
return MutableReflectiveHandle<ArtMethod>(GetMethodReference(i));
}
size_t RemainingFieldSlots() const {
return kNumFields - field_pos_;
}
size_t RemainingMethodSlots() const {
return kNumMethods - method_pos_;
}
private:
ReflectiveReference<ArtMethod>* GetMethodReference(size_t i) {
DCHECK_LT(i, method_pos_);
return &methods_[i];
}
ReflectiveReference<ArtField>* GetFieldReference(size_t i) {
DCHECK_LT(i, field_pos_);
return &fields_[i];
}
size_t field_pos_;
size_t method_pos_;
std::array<ReflectiveReference<ArtField>, kNumFields> fields_;
std::array<ReflectiveReference<ArtMethod>, kNumMethods> methods_;
};
template <size_t kNumMethods>
using StackArtMethodHandleScope = StackReflectiveHandleScope</*kNumFields=*/0, kNumMethods>;
template <size_t kNumFields>
using StackArtFieldHandleScope = StackReflectiveHandleScope<kNumFields, /*kNumMethods=*/0>;
} // namespace art
#endif // ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_