Replace GcRoots in the verifier to use VariableSizedHandleScope.
This removes the cruft in creating static instances, and the need to
explicitly visit verifier roots.
Test: test.py
Change-Id: Ia0f0a82cbc66bb57f30610587f080e75d4d32e92
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index dc3f6dc..16efc2e 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -634,10 +634,15 @@
/*out*/ std::string* descriptor,
/*out*/ SlotType* type)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ art::StackHandleScope<2> hs(art::Thread::Current());
+ art::Handle<art::mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ art::Handle<art::mirror::ClassLoader> class_loader(hs.NewHandle(method->GetClassLoader()));
std::unique_ptr<art::verifier::MethodVerifier> verifier(
art::verifier::MethodVerifier::CalculateVerificationInfo(
art::Thread::Current(),
method,
+ dex_cache,
+ class_loader,
dex_pc));
if (verifier == nullptr) {
JVMTI_LOG(WARNING, jvmti_) << "Unable to extract verification information from "
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d4e4c3e..a8f5987 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1077,8 +1077,6 @@
// initialize the StackOverflowError class (as it might require running the verifier). Instead,
// ensure that the class will be initialized.
if (kMemoryToolIsAvailable && !Runtime::Current()->IsAotCompiler()) {
- verifier::ClassVerifier::Init(this); // Need to prepare the verifier.
-
ObjPtr<mirror::Class> soe_klass = FindSystemClass(self, "Ljava/lang/StackOverflowError;");
if (soe_klass == nullptr || !EnsureInitialized(self, hs.NewHandle(soe_klass), true, true)) {
// Strange, but don't crash.
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index be1c58d..9b4af66 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -129,8 +129,7 @@
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, mutator_lock, held_mutexes, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, held_mutexes, flip_function,
sizeof(void*) * kLockLevelCount);
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, flip_function, method_verifier, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, method_verifier, thread_local_mark_stack, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, flip_function, thread_local_mark_stack, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_mark_stack, async_exception, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, async_exception, top_reflective_handle_scope,
sizeof(void*));
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index eccdf2a..36c8cde 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -526,7 +526,6 @@
oat_file_manager_ = nullptr;
Thread::Shutdown();
QuasiAtomic::Shutdown();
- verifier::ClassVerifier::Shutdown();
// Destroy allocators before shutting down the MemMap because they may use it.
java_vm_.reset();
@@ -1910,8 +1909,6 @@
CHECK(class_linker_ != nullptr);
- verifier::ClassVerifier::Init(class_linker_);
-
if (runtime_options.Exists(Opt::MethodTrace)) {
trace_config_.reset(new TraceConfig());
trace_config_->trace_file = runtime_options.ReleaseOrDefault(Opt::MethodTraceFile);
@@ -2537,7 +2534,6 @@
.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
pre_allocated_NoClassDefFoundError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
VisitImageRoots(visitor);
- verifier::ClassVerifier::VisitStaticRoots(visitor);
VisitTransactionRoots(visitor);
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 00a1468..1b72275 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -109,7 +109,6 @@
#include "thread-inl.h"
#include "thread_list.h"
#include "trace.h"
-#include "verifier/method_verifier.h"
#include "verify_object.h"
#include "well_known_classes-inl.h"
@@ -4433,9 +4432,6 @@
mapper.VisitShadowFrame(record->GetShadowFrame());
}
}
- for (auto* verifier = tlsPtr_.method_verifier; verifier != nullptr; verifier = verifier->link_) {
- verifier->VisitRoots(visitor, RootInfo(kRootNativeStack, thread_id));
- }
// Visit roots on this thread's stack
RuntimeContextType context;
RootCallbackVisitor visitor_to_callback(visitor, thread_id);
@@ -4640,16 +4636,6 @@
return mprotect(pregion, kStackOverflowProtectedSize, PROT_READ|PROT_WRITE) == 0;
}
-void Thread::PushVerifier(verifier::MethodVerifier* verifier) {
- verifier->link_ = tlsPtr_.method_verifier;
- tlsPtr_.method_verifier = verifier;
-}
-
-void Thread::PopVerifier(verifier::MethodVerifier* verifier) {
- CHECK_EQ(tlsPtr_.method_verifier, verifier);
- tlsPtr_.method_verifier = verifier->link_;
-}
-
size_t Thread::NumberOfHeldMutexes() const {
size_t count = 0;
for (BaseMutex* mu : tlsPtr_.held_mutexes) {
diff --git a/runtime/thread.h b/runtime/thread.h
index 8167e70..578f989 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -82,7 +82,6 @@
} // namespace mirror
namespace verifier {
-class MethodVerifier;
class VerifierDeps;
} // namespace verifier
@@ -1389,9 +1388,6 @@
return false;
}
- void PushVerifier(verifier::MethodVerifier* verifier);
- void PopVerifier(verifier::MethodVerifier* verifier);
-
void InitStringEntryPoints();
void ModifyDebugDisallowReadBarrier(int8_t delta) {
@@ -1961,7 +1957,6 @@
thread_local_alloc_stack_end(nullptr),
mutator_lock(nullptr),
flip_function(nullptr),
- method_verifier(nullptr),
thread_local_mark_stack(nullptr),
async_exception(nullptr),
top_reflective_handle_scope(nullptr),
@@ -2110,9 +2105,6 @@
// The function used for thread flip.
Closure* flip_function;
- // Current method verifier, used for root marking.
- verifier::MethodVerifier* method_verifier;
-
union {
// Thread-local mark stack for the concurrent copying collector.
gc::accounting::AtomicStack<mirror::Object>* thread_local_mark_stack;
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
index 8946bb2..40584f4 100644
--- a/runtime/verifier/class_verifier.cc
+++ b/runtime/verifier/class_verifier.cc
@@ -187,17 +187,5 @@
return failure_data.kind;
}
-void ClassVerifier::Init(ClassLinker* class_linker) {
- MethodVerifier::Init(class_linker);
-}
-
-void ClassVerifier::Shutdown() {
- MethodVerifier::Shutdown();
-}
-
-void ClassVerifier::VisitStaticRoots(RootVisitor* visitor) {
- MethodVerifier::VisitStaticRoots(visitor);
-}
-
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
index 3048e6f..65bc28c 100644
--- a/runtime/verifier/class_verifier.h
+++ b/runtime/verifier/class_verifier.h
@@ -34,7 +34,6 @@
class ClassLinker;
class CompilerCallbacks;
class DexFile;
-class RootVisitor;
class Thread;
namespace dex {
@@ -69,12 +68,6 @@
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
- static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_);
- static void Shutdown();
-
- static void VisitStaticRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
DISALLOW_COPY_AND_ASSIGN(ClassVerifier);
};
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9cdbce9..89e2f04 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4950,9 +4950,10 @@
bool allow_thread_suspension,
bool aot_mode)
: self_(self),
+ handles_(self),
arena_stack_(arena_pool),
allocator_(&arena_stack_),
- reg_types_(class_linker, can_load_classes, allocator_, allow_thread_suspension),
+ reg_types_(class_linker, can_load_classes, allocator_, handles_, allow_thread_suspension),
reg_table_(allocator_),
work_insn_idx_(dex::kDexNoIndex),
dex_method_idx_(dex_method_idx),
@@ -4966,11 +4967,9 @@
class_linker_(class_linker),
verifier_deps_(verifier_deps),
link_(nullptr) {
- self->PushVerifier(this);
}
MethodVerifier::~MethodVerifier() {
- Thread::Current()->PopVerifier(this);
STLDeleteElements(&failure_messages_);
}
@@ -5168,10 +5167,9 @@
MethodVerifier* MethodVerifier::CalculateVerificationInfo(
Thread* self,
ArtMethod* method,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
uint32_t dex_pc) {
- StackHandleScope<2> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(method->GetClassLoader()));
std::unique_ptr<impl::MethodVerifier<false>> verifier(
new impl::MethodVerifier<false>(self,
Runtime::Current()->GetClassLinker(),
@@ -5307,22 +5305,6 @@
api_level);
}
-void MethodVerifier::Init(ClassLinker* class_linker) {
- art::verifier::RegTypeCache::Init(class_linker);
-}
-
-void MethodVerifier::Shutdown() {
- verifier::RegTypeCache::ShutDown();
-}
-
-void MethodVerifier::VisitStaticRoots(RootVisitor* visitor) {
- RegTypeCache::VisitStaticRoots(visitor);
-}
-
-void MethodVerifier::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
- reg_types_.VisitRoots(visitor, root_info);
-}
-
std::ostream& MethodVerifier::Fail(VerifyError error, bool pending_exc) {
// Mark the error type as encountered.
encountered_failure_types_ |= static_cast<uint32_t>(error);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 92cfb45..649a245 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -113,6 +113,8 @@
// No classes will be loaded.
static MethodVerifier* CalculateVerificationInfo(Thread* self,
ArtMethod* method,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
uint32_t dex_pc)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -155,16 +157,8 @@
uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
- static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_);
- static void Shutdown();
-
virtual ~MethodVerifier();
- static void VisitStaticRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
- void VisitRoots(RootVisitor* visitor, const RootInfo& roots)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
const CodeItemDataAccessor& CodeItem() const {
return code_item_accessor_;
}
@@ -291,6 +285,9 @@
// The thread we're verifying on.
Thread* const self_;
+ // Handles for classes in the `RegTypeCache`.
+ VariableSizedHandleScope handles_;
+
// Arena allocator.
ArenaStack arena_stack_;
ScopedArenaAllocator allocator_;
diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h
index efe03a8..7fb24b2 100644
--- a/runtime/verifier/reg_type-inl.h
+++ b/runtime/verifier/reg_type-inl.h
@@ -154,72 +154,6 @@
return AssignableFrom(*this, src, true, verifier);
}
-inline const DoubleHiType* DoubleHiType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const DoubleLoType* DoubleLoType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const LongHiType* LongHiType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const LongLoType* LongLoType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const FloatType* FloatType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const CharType* CharType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const ShortType* ShortType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const ByteType* ByteType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-
-inline const IntegerType* IntegerType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const BooleanType* BooleanType::GetInstance() {
- DCHECK(BooleanType::instance_ != nullptr);
- return BooleanType::instance_;
-}
-
-inline const ConflictType* ConflictType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const UndefinedType* UndefinedType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
-inline const NullType* NullType::GetInstance() {
- DCHECK(instance_ != nullptr);
- return instance_;
-}
-
inline void* RegType::operator new(size_t size, ScopedArenaAllocator* allocator) {
return allocator->Alloc(size, kArenaAllocMisc);
}
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 40b880e..0433c6d 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -40,21 +40,7 @@
using android::base::StringPrintf;
-const UndefinedType* UndefinedType::instance_ = nullptr;
-const ConflictType* ConflictType::instance_ = nullptr;
-const BooleanType* BooleanType::instance_ = nullptr;
-const ByteType* ByteType::instance_ = nullptr;
-const ShortType* ShortType::instance_ = nullptr;
-const CharType* CharType::instance_ = nullptr;
-const FloatType* FloatType::instance_ = nullptr;
-const LongLoType* LongLoType::instance_ = nullptr;
-const LongHiType* LongHiType::instance_ = nullptr;
-const DoubleLoType* DoubleLoType::instance_ = nullptr;
-const DoubleHiType* DoubleHiType::instance_ = nullptr;
-const IntegerType* IntegerType::instance_ = nullptr;
-const NullType* NullType::instance_ = nullptr;
-
-PrimitiveType::PrimitiveType(ObjPtr<mirror::Class> klass,
+PrimitiveType::PrimitiveType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id)
: RegType(klass, descriptor, cache_id) {
@@ -62,13 +48,13 @@
CHECK(!descriptor.empty());
}
-Cat1Type::Cat1Type(ObjPtr<mirror::Class> klass,
+Cat1Type::Cat1Type(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id)
: PrimitiveType(klass, descriptor, cache_id) {
}
-Cat2Type::Cat2Type(ObjPtr<mirror::Class> klass,
+Cat2Type::Cat2Type(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id)
: PrimitiveType(klass, descriptor, cache_id) {
@@ -135,191 +121,11 @@
return "Integer";
}
-const DoubleHiType* DoubleHiType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new DoubleHiType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void DoubleHiType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const DoubleLoType* DoubleLoType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new DoubleLoType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void DoubleLoType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const LongLoType* LongLoType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new LongLoType(klass, descriptor, cache_id);
- return instance_;
-}
-
-const LongHiType* LongHiType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new LongHiType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void LongHiType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-void LongLoType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const FloatType* FloatType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new FloatType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void FloatType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const CharType* CharType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new CharType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void CharType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const ShortType* ShortType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new ShortType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void ShortType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const ByteType* ByteType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new ByteType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void ByteType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const IntegerType* IntegerType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new IntegerType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void IntegerType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const ConflictType* ConflictType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new ConflictType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void ConflictType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-const BooleanType* BooleanType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(BooleanType::instance_ == nullptr);
- instance_ = new BooleanType(klass, descriptor, cache_id);
- return BooleanType::instance_;
-}
-
-void BooleanType::Destroy() {
- if (BooleanType::instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
std::string UndefinedType::Dump() const REQUIRES_SHARED(Locks::mutator_lock_) {
return "Undefined";
}
-const UndefinedType* UndefinedType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new UndefinedType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void UndefinedType::Destroy() {
- if (instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-PreciseReferenceType::PreciseReferenceType(ObjPtr<mirror::Class> klass,
+PreciseReferenceType::PreciseReferenceType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id)
: RegType(klass, descriptor, cache_id) {
@@ -935,14 +741,10 @@
if (!klass_.IsNull()) {
CHECK(!descriptor_.empty()) << *this;
std::string temp;
- CHECK_EQ(descriptor_, klass_.Read()->GetDescriptor(&temp)) << *this;
+ CHECK_EQ(descriptor_, klass_->GetDescriptor(&temp)) << *this;
}
}
-void RegType::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const {
- klass_.VisitRootIfNonNull(visitor, root_info);
-}
-
void UninitializedThisReferenceType::CheckInvariants() const {
CHECK_EQ(GetAllocationPc(), 0U) << *this;
}
@@ -950,19 +752,19 @@
void UnresolvedUninitializedThisRefType::CheckInvariants() const {
CHECK_EQ(GetAllocationPc(), 0U) << *this;
CHECK(!descriptor_.empty()) << *this;
- CHECK(klass_.IsNull()) << *this;
+ CHECK(!HasClass()) << *this;
}
void UnresolvedUninitializedRefType::CheckInvariants() const {
CHECK(!descriptor_.empty()) << *this;
- CHECK(klass_.IsNull()) << *this;
+ CHECK(!HasClass()) << *this;
}
UnresolvedMergedType::UnresolvedMergedType(const RegType& resolved,
const BitVector& unresolved,
const RegTypeCache* reg_type_cache,
uint16_t cache_id)
- : UnresolvedType("", cache_id),
+ : UnresolvedType(reg_type_cache->GetNullHandle(), "", cache_id),
reg_type_cache_(reg_type_cache),
resolved_part_(resolved),
unresolved_types_(unresolved, false, unresolved.GetAllocator()) {
@@ -973,7 +775,7 @@
// Unresolved merged types: merged types should be defined.
CHECK(descriptor_.empty()) << *this;
- CHECK(klass_.IsNull()) << *this;
+ CHECK(!HasClass()) << *this;
CHECK(!resolved_part_.IsConflict());
CHECK(resolved_part_.IsReferenceTypes());
@@ -1017,13 +819,13 @@
void UnresolvedReferenceType::CheckInvariants() const {
CHECK(!descriptor_.empty()) << *this;
- CHECK(klass_.IsNull()) << *this;
+ CHECK(!HasClass()) << *this;
}
void UnresolvedSuperClass::CheckInvariants() const {
// Unresolved merged types: merged types should be defined.
CHECK(descriptor_.empty()) << *this;
- CHECK(klass_.IsNull()) << *this;
+ CHECK(!HasClass()) << *this;
CHECK_NE(unresolved_child_id_, 0U) << *this;
}
@@ -1032,21 +834,5 @@
return os;
}
-const NullType* NullType::CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id) {
- CHECK(instance_ == nullptr);
- instance_ = new NullType(klass, descriptor, cache_id);
- return instance_;
-}
-
-void NullType::Destroy() {
- if (NullType::instance_ != nullptr) {
- delete instance_;
- instance_ = nullptr;
- }
-}
-
-
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index c13784c..6cc9880 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -29,6 +29,7 @@
#include "base/macros.h"
#include "dex/primitive.h"
#include "gc_root.h"
+#include "handle.h"
#include "handle_scope.h"
#include "obj_ptr.h"
@@ -193,9 +194,15 @@
}
ObjPtr<mirror::Class> GetClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!IsUnresolvedReference());
- DCHECK(!klass_.IsNull()) << Dump();
+ DCHECK(!klass_.IsNull());
DCHECK(HasClass());
- return klass_.Read();
+ return klass_.Get();
+ }
+ Handle<mirror::Class> GetClassHandle() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(!IsUnresolvedReference());
+ DCHECK(!klass_.IsNull()) << Dump();
+ DCHECK(HasClass()) << Dump();
+ return klass_;
}
uint16_t GetId() const { return cache_id_; }
const RegType& GetSuperClass(RegTypeCache* cache) const
@@ -247,9 +254,6 @@
virtual ~RegType() {}
- void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
static void* operator new(size_t size) noexcept {
return ::operator new(size);
}
@@ -304,7 +308,7 @@
}
protected:
- RegType(ObjPtr<mirror::Class> klass,
+ RegType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: descriptor_(descriptor),
@@ -323,7 +327,7 @@
virtual AssignmentType GetAssignmentTypeImpl() const = 0;
const std::string_view descriptor_;
- mutable GcRoot<mirror::Class> klass_; // Non-const only due to moving classes.
+ const Handle<mirror::Class> klass_;
const uint16_t cache_id_;
friend class RegTypeCache;
@@ -348,31 +352,16 @@
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- // Get the singleton Conflict instance.
- static const ConflictType* GetInstance() PURE;
-
- // Create the singleton instance.
- static const ConflictType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Destroy the singleton instance.
- static void Destroy();
-
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kConflict;
}
- private:
- ConflictType(ObjPtr<mirror::Class> klass,
+ ConflictType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
-
- static const ConflictType* instance_;
};
// A variant of the bottom type used to specify an undefined value in the
@@ -384,36 +373,21 @@
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- // Get the singleton Undefined instance.
- static const UndefinedType* GetInstance() PURE;
-
- // Create the singleton instance.
- static const UndefinedType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Destroy the singleton instance.
- static void Destroy();
-
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kNotAssignable;
}
- private:
- UndefinedType(ObjPtr<mirror::Class> klass,
+ UndefinedType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
-
- static const UndefinedType* instance_;
};
class PrimitiveType : public RegType {
public:
- PrimitiveType(ObjPtr<mirror::Class> klass,
+ PrimitiveType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -422,7 +396,7 @@
class Cat1Type : public PrimitiveType {
public:
- Cat1Type(ObjPtr<mirror::Class> klass,
+ Cat1Type(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
};
@@ -431,155 +405,107 @@
public:
bool IsInteger() const override { return true; }
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- static const IntegerType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const IntegerType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kInteger;
}
- private:
- IntegerType(ObjPtr<mirror::Class> klass,
+ IntegerType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const IntegerType* instance_;
};
class BooleanType final : public Cat1Type {
public:
bool IsBoolean() const override { return true; }
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- static const BooleanType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const BooleanType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kBoolean;
}
- private:
- BooleanType(ObjPtr<mirror::Class> klass,
+ BooleanType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
-
- static const BooleanType* instance_;
};
class ByteType final : public Cat1Type {
public:
bool IsByte() const override { return true; }
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- static const ByteType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const ByteType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kByte;
}
- private:
- ByteType(ObjPtr<mirror::Class> klass,
+ ByteType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const ByteType* instance_;
};
class ShortType final : public Cat1Type {
public:
bool IsShort() const override { return true; }
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- static const ShortType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const ShortType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kShort;
}
- private:
- ShortType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor,
+ ShortType(Handle<mirror::Class> klass,
+ const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const ShortType* instance_;
};
class CharType final : public Cat1Type {
public:
bool IsChar() const override { return true; }
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- static const CharType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const CharType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kChar;
}
- private:
- CharType(ObjPtr<mirror::Class> klass,
+ CharType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const CharType* instance_;
};
class FloatType final : public Cat1Type {
public:
bool IsFloat() const override { return true; }
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
- static const FloatType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const FloatType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kFloat;
}
- private:
- FloatType(ObjPtr<mirror::Class> klass,
+ FloatType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const FloatType* instance_;
};
class Cat2Type : public PrimitiveType {
public:
- Cat2Type(ObjPtr<mirror::Class> klass,
+ Cat2Type(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
};
@@ -589,50 +515,34 @@
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
bool IsLongLo() const override { return true; }
bool IsLong() const override { return true; }
- static const LongLoType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const LongLoType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kLongLo;
}
- private:
- LongLoType(ObjPtr<mirror::Class> klass,
+ LongLoType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const LongLoType* instance_;
};
class LongHiType final : public Cat2Type {
public:
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
bool IsLongHi() const override { return true; }
- static const LongHiType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const LongHiType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kNotAssignable;
}
- private:
- LongHiType(ObjPtr<mirror::Class> klass,
+ LongHiType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const LongHiType* instance_;
};
class DoubleLoType final : public Cat2Type {
@@ -640,56 +550,42 @@
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
bool IsDoubleLo() const override { return true; }
bool IsDouble() const override { return true; }
- static const DoubleLoType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const DoubleLoType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kDoubleLo;
}
- private:
- DoubleLoType(ObjPtr<mirror::Class> klass,
+ DoubleLoType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const DoubleLoType* instance_;
};
class DoubleHiType final : public Cat2Type {
public:
std::string Dump() const override REQUIRES_SHARED(Locks::mutator_lock_);
bool IsDoubleHi() const override { return true; }
- static const DoubleHiType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static const DoubleHiType* GetInstance() PURE;
- static void Destroy();
AssignmentType GetAssignmentTypeImpl() const override {
return AssignmentType::kNotAssignable;
}
- private:
- DoubleHiType(ObjPtr<mirror::Class> klass,
+ DoubleHiType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
- static const DoubleHiType* instance_;
};
class ConstantType : public RegType {
public:
- ConstantType(uint32_t constant, uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
- : RegType(nullptr, "", cache_id), constant_(constant) {
+ ConstantType(Handle<mirror::Class> klass,
+ uint32_t constant,
+ uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
+ : RegType(klass, "", cache_id), constant_(constant) {
}
@@ -749,9 +645,9 @@
class PreciseConstType final : public ConstantType {
public:
- PreciseConstType(uint32_t constant, uint16_t cache_id)
+ PreciseConstType(Handle<mirror::Class> cls, uint32_t constant, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : ConstantType(constant, cache_id) {
+ : ConstantType(cls, constant, cache_id) {
CheckConstructorInvariants(this);
}
@@ -766,9 +662,9 @@
class PreciseConstLoType final : public ConstantType {
public:
- PreciseConstLoType(uint32_t constant, uint16_t cache_id)
+ PreciseConstLoType(Handle<mirror::Class> cls, uint32_t constant, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : ConstantType(constant, cache_id) {
+ : ConstantType(cls, constant, cache_id) {
CheckConstructorInvariants(this);
}
bool IsPreciseConstantLo() const override { return true; }
@@ -781,9 +677,9 @@
class PreciseConstHiType final : public ConstantType {
public:
- PreciseConstHiType(uint32_t constant, uint16_t cache_id)
+ PreciseConstHiType(Handle<mirror::Class> cls, uint32_t constant, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : ConstantType(constant, cache_id) {
+ : ConstantType(cls, constant, cache_id) {
CheckConstructorInvariants(this);
}
bool IsPreciseConstantHi() const override { return true; }
@@ -796,9 +692,9 @@
class ImpreciseConstType final : public ConstantType {
public:
- ImpreciseConstType(uint32_t constat, uint16_t cache_id)
+ ImpreciseConstType(Handle<mirror::Class> cls, uint32_t constat, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : ConstantType(constat, cache_id) {
+ : ConstantType(cls, constat, cache_id) {
CheckConstructorInvariants(this);
}
bool IsImpreciseConstant() const override { return true; }
@@ -811,9 +707,9 @@
class ImpreciseConstLoType final : public ConstantType {
public:
- ImpreciseConstLoType(uint32_t constant, uint16_t cache_id)
+ ImpreciseConstLoType(Handle<mirror::Class> cls, uint32_t constant, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : ConstantType(constant, cache_id) {
+ : ConstantType(cls, constant, cache_id) {
CheckConstructorInvariants(this);
}
bool IsImpreciseConstantLo() const override { return true; }
@@ -826,9 +722,9 @@
class ImpreciseConstHiType final : public ConstantType {
public:
- ImpreciseConstHiType(uint32_t constant, uint16_t cache_id)
+ ImpreciseConstHiType(Handle<mirror::Class> cls, uint32_t constant, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : ConstantType(constant, cache_id) {
+ : ConstantType(cls, constant, cache_id) {
CheckConstructorInvariants(this);
}
bool IsImpreciseConstantHi() const override { return true; }
@@ -846,17 +742,6 @@
return true;
}
- // Get the singleton Null instance.
- static const NullType* GetInstance() PURE;
-
- // Create the singleton instance.
- static const NullType* CreateInstance(ObjPtr<mirror::Class> klass,
- const std::string_view& descriptor,
- uint16_t cache_id)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- static void Destroy();
-
std::string Dump() const override {
return "null";
}
@@ -869,14 +754,11 @@
return true;
}
- private:
- NullType(ObjPtr<mirror::Class> klass, const std::string_view& descriptor, uint16_t cache_id)
+ NullType(Handle<mirror::Class> klass, const std::string_view& descriptor, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
-
- static const NullType* instance_;
};
// Common parent of all uninitialized types. Uninitialized types are created by
@@ -884,7 +766,7 @@
// instructions and must be passed to a constructor.
class UninitializedType : public RegType {
public:
- UninitializedType(ObjPtr<mirror::Class> klass,
+ UninitializedType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint32_t allocation_pc,
uint16_t cache_id)
@@ -909,7 +791,7 @@
// Similar to ReferenceType but not yet having been passed to a constructor.
class UninitializedReferenceType final : public UninitializedType {
public:
- UninitializedReferenceType(ObjPtr<mirror::Class> klass,
+ UninitializedReferenceType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint32_t allocation_pc,
uint16_t cache_id)
@@ -929,11 +811,12 @@
// constructor.
class UnresolvedUninitializedRefType final : public UninitializedType {
public:
- UnresolvedUninitializedRefType(const std::string_view& descriptor,
+ UnresolvedUninitializedRefType(Handle<mirror::Class> klass,
+ const std::string_view& descriptor,
uint32_t allocation_pc,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : UninitializedType(nullptr, descriptor, allocation_pc, cache_id) {
+ : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
CheckConstructorInvariants(this);
}
@@ -951,7 +834,7 @@
// of a constructor.
class UninitializedThisReferenceType final : public UninitializedType {
public:
- UninitializedThisReferenceType(ObjPtr<mirror::Class> klass,
+ UninitializedThisReferenceType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -971,9 +854,11 @@
class UnresolvedUninitializedThisRefType final : public UninitializedType {
public:
- UnresolvedUninitializedThisRefType(const std::string_view& descriptor, uint16_t cache_id)
+ UnresolvedUninitializedThisRefType(Handle<mirror::Class> klass,
+ const std::string_view& descriptor,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : UninitializedType(nullptr, descriptor, 0, cache_id) {
+ : UninitializedType(klass, descriptor, 0, cache_id) {
CheckConstructorInvariants(this);
}
@@ -991,7 +876,7 @@
// sub-class.
class ReferenceType final : public RegType {
public:
- ReferenceType(ObjPtr<mirror::Class> klass,
+ ReferenceType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
@@ -1016,7 +901,7 @@
// type.
class PreciseReferenceType final : public RegType {
public:
- PreciseReferenceType(ObjPtr<mirror::Class> klass,
+ PreciseReferenceType(Handle<mirror::Class> klass,
const std::string_view& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1037,9 +922,11 @@
// Common parent of unresolved types.
class UnresolvedType : public RegType {
public:
- UnresolvedType(const std::string_view& descriptor, uint16_t cache_id)
+ UnresolvedType(Handle<mirror::Class> klass,
+ const std::string_view& descriptor,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : RegType(nullptr, descriptor, cache_id) {}
+ : RegType(klass, descriptor, cache_id) {}
bool IsNonZeroReferenceTypes() const override;
@@ -1053,9 +940,11 @@
// of this type must be conservative.
class UnresolvedReferenceType final : public UnresolvedType {
public:
- UnresolvedReferenceType(const std::string_view& descriptor, uint16_t cache_id)
+ UnresolvedReferenceType(Handle<mirror::Class> cls,
+ const std::string_view& descriptor,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : UnresolvedType(descriptor, cache_id) {
+ : UnresolvedType(cls, descriptor, cache_id) {
CheckConstructorInvariants(this);
}
@@ -1072,10 +961,12 @@
// Type representing the super-class of an unresolved type.
class UnresolvedSuperClass final : public UnresolvedType {
public:
- UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache,
+ UnresolvedSuperClass(Handle<mirror::Class> cls,
+ uint16_t child_id,
+ RegTypeCache* reg_type_cache,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
- : UnresolvedType("", cache_id),
+ : UnresolvedType(cls, "", cache_id),
unresolved_child_id_(child_id),
reg_type_cache_(reg_type_cache) {
CheckConstructorInvariants(this);
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index c5ff2b3..b987c2c 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -42,49 +42,49 @@
// We only expect 0 to be a precise constant.
DCHECK_IMPLIES(value == 0, precise);
if (precise && (value >= kMinSmallConstant) && (value <= kMaxSmallConstant)) {
- return *small_precise_constants_[value - kMinSmallConstant];
+ return *down_cast<const ConstantType*>(entries_[value - kMinSmallConstant]);
}
return FromCat1NonSmallConstant(value, precise);
}
inline const BooleanType& RegTypeCache::Boolean() {
- return *BooleanType::GetInstance();
+ return *down_cast<const BooleanType*>(entries_[kBooleanCacheId]);
}
inline const ByteType& RegTypeCache::Byte() {
- return *ByteType::GetInstance();
+ return *down_cast<const ByteType*>(entries_[kByteCacheId]);
}
inline const CharType& RegTypeCache::Char() {
- return *CharType::GetInstance();
+ return *down_cast<const CharType*>(entries_[kCharCacheId]);
}
inline const ShortType& RegTypeCache::Short() {
- return *ShortType::GetInstance();
+ return *down_cast<const ShortType*>(entries_[kShortCacheId]);
}
inline const IntegerType& RegTypeCache::Integer() {
- return *IntegerType::GetInstance();
+ return *down_cast<const IntegerType*>(entries_[kIntCacheId]);
}
inline const FloatType& RegTypeCache::Float() {
- return *FloatType::GetInstance();
+ return *down_cast<const FloatType*>(entries_[kFloatCacheId]);
}
inline const LongLoType& RegTypeCache::LongLo() {
- return *LongLoType::GetInstance();
+ return *down_cast<const LongLoType*>(entries_[kLongLoCacheId]);
}
inline const LongHiType& RegTypeCache::LongHi() {
- return *LongHiType::GetInstance();
+ return *down_cast<const LongHiType*>(entries_[kLongHiCacheId]);
}
inline const DoubleLoType& RegTypeCache::DoubleLo() {
- return *DoubleLoType::GetInstance();
+ return *down_cast<const DoubleLoType*>(entries_[kDoubleLoCacheId]);
}
inline const DoubleHiType& RegTypeCache::DoubleHi() {
- return *DoubleHiType::GetInstance();
+ return *down_cast<const DoubleHiType*>(entries_[kDoubleHiCacheId]);
}
inline const UndefinedType& RegTypeCache::Undefined() {
- return *UndefinedType::GetInstance();
+ return *down_cast<const UndefinedType*>(entries_[kUndefinedCacheId]);
}
inline const ConflictType& RegTypeCache::Conflict() {
- return *ConflictType::GetInstance();
+ return *down_cast<const ConflictType*>(entries_[kConflictCacheId]);
}
inline const NullType& RegTypeCache::Null() {
- return *NullType::GetInstance();
+ return *down_cast<const NullType*>(entries_[kNullCacheId]);
}
inline const ImpreciseConstType& RegTypeCache::ByteConstant() {
@@ -186,9 +186,9 @@
DCHECK(new_entry != nullptr);
entries_.push_back(new_entry);
if (new_entry->HasClass()) {
- ObjPtr<mirror::Class> klass = new_entry->GetClass();
+ Handle<mirror::Class> klass = new_entry->GetClassHandle();
DCHECK(!klass->IsPrimitive());
- klass_entries_.push_back(std::make_pair(GcRoot<mirror::Class>(klass), new_entry));
+ klass_entries_.push_back(std::make_pair(klass, new_entry));
}
return *new_entry;
}
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 0bba6e8..55b3733 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -25,6 +25,7 @@
#include "base/scoped_arena_allocator.h"
#include "base/stl_util.h"
#include "class_linker-inl.h"
+#include "class_root-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "mirror/class-inl.h"
@@ -34,17 +35,6 @@
namespace art {
namespace verifier {
-bool RegTypeCache::primitive_initialized_ = false;
-uint16_t RegTypeCache::primitive_count_ = 0;
-const PreciseConstType* RegTypeCache::small_precise_constants_[kMaxSmallConstant -
- kMinSmallConstant + 1];
-
-namespace {
-
-ClassLinker* gInitClassLinker = nullptr;
-
-} // namespace
-
ALWAYS_INLINE static inline bool MatchingPrecisionForClass(const RegType* entry, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (entry->IsPreciseReference() == precise) {
@@ -61,32 +51,42 @@
}
void RegTypeCache::FillPrimitiveAndSmallConstantTypes() {
- // Note: this must have the same order as CreatePrimitiveAndSmallConstantTypes.
- entries_.push_back(UndefinedType::GetInstance());
- entries_.push_back(ConflictType::GetInstance());
- entries_.push_back(NullType::GetInstance());
- entries_.push_back(BooleanType::GetInstance());
- entries_.push_back(ByteType::GetInstance());
- entries_.push_back(ShortType::GetInstance());
- entries_.push_back(CharType::GetInstance());
- entries_.push_back(IntegerType::GetInstance());
- entries_.push_back(LongLoType::GetInstance());
- entries_.push_back(LongHiType::GetInstance());
- entries_.push_back(FloatType::GetInstance());
- entries_.push_back(DoubleLoType::GetInstance());
- entries_.push_back(DoubleHiType::GetInstance());
+ entries_.resize(kNumPrimitivesAndSmallConstants);
for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) {
int32_t i = value - kMinSmallConstant;
- DCHECK_EQ(entries_.size(), small_precise_constants_[i]->GetId());
- entries_.push_back(small_precise_constants_[i]);
+ entries_[i] = new (&allocator_) PreciseConstType(null_handle_, value, i);
}
- DCHECK_EQ(entries_.size(), primitive_count_);
+
+#define CREATE_PRIMITIVE_TYPE(type, class_root, descriptor, id) \
+ entries_[id] = new (&allocator_) type( \
+ handles_.NewHandle(GetClassRoot(class_root, class_linker_)), \
+ descriptor, \
+ id); \
+
+ CREATE_PRIMITIVE_TYPE(BooleanType, ClassRoot::kPrimitiveBoolean, "Z", kBooleanCacheId);
+ CREATE_PRIMITIVE_TYPE(ByteType, ClassRoot::kPrimitiveByte, "B", kByteCacheId);
+ CREATE_PRIMITIVE_TYPE(ShortType, ClassRoot::kPrimitiveShort, "S", kShortCacheId);
+ CREATE_PRIMITIVE_TYPE(CharType, ClassRoot::kPrimitiveChar, "C", kCharCacheId);
+ CREATE_PRIMITIVE_TYPE(IntegerType, ClassRoot::kPrimitiveInt, "I", kIntCacheId);
+ CREATE_PRIMITIVE_TYPE(LongLoType, ClassRoot::kPrimitiveLong, "J", kLongLoCacheId);
+ CREATE_PRIMITIVE_TYPE(LongHiType, ClassRoot::kPrimitiveLong, "J", kLongHiCacheId);
+ CREATE_PRIMITIVE_TYPE(FloatType, ClassRoot::kPrimitiveFloat, "F", kFloatCacheId);
+ CREATE_PRIMITIVE_TYPE(DoubleLoType, ClassRoot::kPrimitiveDouble, "D", kDoubleLoCacheId);
+ CREATE_PRIMITIVE_TYPE(DoubleHiType, ClassRoot::kPrimitiveDouble, "D", kDoubleHiCacheId);
+
+#undef CREATE_PRIMITIVE_TYPE
+
+ entries_[kUndefinedCacheId] =
+ new (&allocator_) UndefinedType(null_handle_, "", kUndefinedCacheId);
+ entries_[kConflictCacheId] =
+ new (&allocator_) ConflictType(null_handle_, "", kConflictCacheId);
+ entries_[kNullCacheId] =
+ new (&allocator_) NullType(null_handle_, "", kNullCacheId);
}
const RegType& RegTypeCache::FromDescriptor(ObjPtr<mirror::ClassLoader> loader,
const char* descriptor,
bool precise) {
- DCHECK(RegTypeCache::primitive_initialized_);
if (descriptor[1] == '\0') {
switch (descriptor[0]) {
case 'Z':
@@ -116,28 +116,28 @@
}
}
+
const RegType& RegTypeCache::RegTypeFromPrimitiveType(Primitive::Type prim_type) const {
- DCHECK(RegTypeCache::primitive_initialized_);
switch (prim_type) {
case Primitive::kPrimBoolean:
- return *BooleanType::GetInstance();
+ return *entries_[kBooleanCacheId];
case Primitive::kPrimByte:
- return *ByteType::GetInstance();
+ return *entries_[kByteCacheId];
case Primitive::kPrimShort:
- return *ShortType::GetInstance();
+ return *entries_[kShortCacheId];
case Primitive::kPrimChar:
- return *CharType::GetInstance();
+ return *entries_[kCharCacheId];
case Primitive::kPrimInt:
- return *IntegerType::GetInstance();
+ return *entries_[kIntCacheId];
case Primitive::kPrimLong:
- return *LongLoType::GetInstance();
+ return *entries_[kLongLoCacheId];
case Primitive::kPrimFloat:
- return *FloatType::GetInstance();
+ return *entries_[kFloatCacheId];
case Primitive::kPrimDouble:
- return *DoubleLoType::GetInstance();
+ return *entries_[kDoubleLoCacheId];
case Primitive::kPrimVoid:
default:
- return *ConflictType::GetInstance();
+ return *entries_[kConflictCacheId];
}
}
@@ -187,7 +187,7 @@
std::string_view sv_descriptor(descriptor);
// Try looking up the class in the cache first. We use a std::string_view to avoid
// repeated strlen operations on the descriptor.
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
if (MatchDescriptor(i, sv_descriptor, precise)) {
return *(entries_[i]);
}
@@ -209,10 +209,13 @@
if (klass->CannotBeAssignedFromOtherTypes() || precise) {
DCHECK_IMPLIES(klass->IsAbstract(), klass->IsArrayClass());
DCHECK(!klass->IsInterface());
- entry =
- new (&allocator_) PreciseReferenceType(klass, AddString(sv_descriptor), entries_.size());
+ entry = new (&allocator_) PreciseReferenceType(handles_.NewHandle(klass),
+ AddString(sv_descriptor),
+ entries_.size());
} else {
- entry = new (&allocator_) ReferenceType(klass, AddString(sv_descriptor), entries_.size());
+ entry = new (&allocator_) ReferenceType(handles_.NewHandle(klass),
+ AddString(sv_descriptor),
+ entries_.size());
}
return AddEntry(entry);
} else { // Class not resolved.
@@ -225,8 +228,9 @@
DCHECK(!Thread::Current()->IsExceptionPending());
}
if (IsValidDescriptor(descriptor)) {
- return AddEntry(
- new (&allocator_) UnresolvedReferenceType(AddString(sv_descriptor), entries_.size()));
+ return AddEntry(new (&allocator_) UnresolvedReferenceType(null_handle_,
+ AddString(sv_descriptor),
+ entries_.size()));
} else {
// The descriptor is broken return the unknown type as there's nothing sensible that
// could be done at runtime
@@ -237,7 +241,8 @@
const RegType& RegTypeCache::MakeUnresolvedReference() {
// The descriptor is intentionally invalid so nothing else will match this type.
- return AddEntry(new (&allocator_) UnresolvedReferenceType(AddString("a"), entries_.size()));
+ return AddEntry(new (&allocator_) UnresolvedReferenceType(
+ null_handle_, AddString("a"), entries_.size()));
}
const RegType* RegTypeCache::FindClass(ObjPtr<mirror::Class> klass, bool precise) const {
@@ -248,8 +253,8 @@
return &RegTypeFromPrimitiveType(klass->GetPrimitiveType());
}
for (auto& pair : klass_entries_) {
- const ObjPtr<mirror::Class> reg_klass = pair.first.Read();
- if (reg_klass == klass) {
+ const Handle<mirror::Class> reg_klass = pair.first;
+ if (reg_klass.Get() == klass) {
const RegType* reg_type = pair.second;
if (MatchingPrecisionForClass(reg_type, precise)) {
return reg_type;
@@ -266,8 +271,10 @@
DCHECK(FindClass(klass, precise) == nullptr);
RegType* const reg_type = precise
? static_cast<RegType*>(
- new (&allocator_) PreciseReferenceType(klass, descriptor, entries_.size()))
- : new (&allocator_) ReferenceType(klass, descriptor, entries_.size());
+ new (&allocator_) PreciseReferenceType(handles_.NewHandle(klass),
+ descriptor,
+ entries_.size()))
+ : new (&allocator_) ReferenceType(handles_.NewHandle(klass), descriptor, entries_.size());
return &AddEntry(reg_type);
}
@@ -285,13 +292,14 @@
RegTypeCache::RegTypeCache(ClassLinker* class_linker,
bool can_load_classes,
ScopedArenaAllocator& allocator,
+ VariableSizedHandleScope& handles,
bool can_suspend)
: entries_(allocator.Adapter(kArenaAllocVerifier)),
klass_entries_(allocator.Adapter(kArenaAllocVerifier)),
allocator_(allocator),
+ handles_(handles),
class_linker_(class_linker),
can_load_classes_(can_load_classes) {
- DCHECK_EQ(class_linker, gInitClassLinker);
DCHECK(can_suspend || !can_load_classes) << "Cannot load classes if suspension is disabled!";
if (kIsDebugBuild && can_suspend) {
Thread::Current()->AssertThreadSuspensionIsAllowable(gAborting == 0);
@@ -305,92 +313,6 @@
FillPrimitiveAndSmallConstantTypes();
}
-RegTypeCache::~RegTypeCache() {
- DCHECK_LE(primitive_count_, entries_.size());
-}
-
-void RegTypeCache::ShutDown() {
- if (RegTypeCache::primitive_initialized_) {
- UndefinedType::Destroy();
- ConflictType::Destroy();
- BooleanType::Destroy();
- ByteType::Destroy();
- ShortType::Destroy();
- CharType::Destroy();
- IntegerType::Destroy();
- LongLoType::Destroy();
- LongHiType::Destroy();
- FloatType::Destroy();
- DoubleLoType::Destroy();
- DoubleHiType::Destroy();
- NullType::Destroy();
- for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) {
- const PreciseConstType* type = small_precise_constants_[value - kMinSmallConstant];
- delete type;
- small_precise_constants_[value - kMinSmallConstant] = nullptr;
- }
- RegTypeCache::primitive_initialized_ = false;
- RegTypeCache::primitive_count_ = 0;
- }
-}
-
-// Helper for create_primitive_type_instance lambda.
-namespace {
-template <typename T>
-struct TypeHelper {
- using type = T;
- static_assert(std::is_convertible<T*, RegType*>::value, "T must be a RegType");
-
- const char* descriptor;
-
- explicit TypeHelper(const char* d) : descriptor(d) {}
-};
-} // namespace
-
-void RegTypeCache::CreatePrimitiveAndSmallConstantTypes(ClassLinker* class_linker) {
- gInitClassLinker = class_linker;
-
- // Note: this must have the same order as FillPrimitiveAndSmallConstantTypes.
-
- // It is acceptable to pass on the const char* in type to CreateInstance, as all calls below are
- // with compile-time constants that will have global lifetime. Use of the lambda ensures this
- // code cannot leak to other users.
- auto create_primitive_type_instance = [&](auto type) REQUIRES_SHARED(Locks::mutator_lock_) {
- using Type = typename decltype(type)::type;
- ObjPtr<mirror::Class> klass = nullptr;
- // Try loading the class from linker.
- DCHECK(type.descriptor != nullptr);
- if (strlen(type.descriptor) > 0) {
- klass = class_linker->FindSystemClass(Thread::Current(), type.descriptor);
- DCHECK(klass != nullptr);
- }
- const Type* entry = Type::CreateInstance(klass,
- type.descriptor,
- RegTypeCache::primitive_count_);
- RegTypeCache::primitive_count_++;
- return entry;
- };
- create_primitive_type_instance(TypeHelper<UndefinedType>(""));
- create_primitive_type_instance(TypeHelper<ConflictType>(""));
- create_primitive_type_instance(TypeHelper<NullType>(""));
- create_primitive_type_instance(TypeHelper<BooleanType>("Z"));
- create_primitive_type_instance(TypeHelper<ByteType>("B"));
- create_primitive_type_instance(TypeHelper<ShortType>("S"));
- create_primitive_type_instance(TypeHelper<CharType>("C"));
- create_primitive_type_instance(TypeHelper<IntegerType>("I"));
- create_primitive_type_instance(TypeHelper<LongLoType>("J"));
- create_primitive_type_instance(TypeHelper<LongHiType>("J"));
- create_primitive_type_instance(TypeHelper<FloatType>("F"));
- create_primitive_type_instance(TypeHelper<DoubleLoType>("D"));
- create_primitive_type_instance(TypeHelper<DoubleHiType>("D"));
-
- for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) {
- PreciseConstType* type = new PreciseConstType(value, primitive_count_);
- small_precise_constants_[value - kMinSmallConstant] = type;
- primitive_count_++;
- }
-}
-
const RegType& RegTypeCache::FromUnresolvedMerge(const RegType& left,
const RegType& right,
MethodVerifier* verifier) {
@@ -461,7 +383,7 @@
}
// Check if entry already exists.
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedMergedReference()) {
const UnresolvedMergedType* cmp_type = down_cast<const UnresolvedMergedType*>(cur_entry);
@@ -482,7 +404,7 @@
const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
// Check if entry already exists.
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedSuperClass()) {
const UnresolvedSuperClass* tmp_entry =
@@ -494,14 +416,15 @@
}
}
}
- return AddEntry(new (&allocator_) UnresolvedSuperClass(child.GetId(), this, entries_.size()));
+ return AddEntry(new (&allocator_) UnresolvedSuperClass(
+ null_handle_, child.GetId(), this, entries_.size()));
}
const UninitializedType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
UninitializedType* entry = nullptr;
const std::string_view& descriptor(type.GetDescriptor());
if (type.IsUnresolvedTypes()) {
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedAndUninitializedReference() &&
down_cast<const UnresolvedUninitializedRefType*>(cur_entry)->GetAllocationPc()
@@ -510,12 +433,13 @@
return *down_cast<const UnresolvedUninitializedRefType*>(cur_entry);
}
}
- entry = new (&allocator_) UnresolvedUninitializedRefType(descriptor,
+ entry = new (&allocator_) UnresolvedUninitializedRefType(null_handle_,
+ descriptor,
allocation_pc,
entries_.size());
} else {
ObjPtr<mirror::Class> klass = type.GetClass();
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUninitializedReference() &&
down_cast<const UninitializedReferenceType*>(cur_entry)
@@ -524,7 +448,7 @@
return *down_cast<const UninitializedReferenceType*>(cur_entry);
}
}
- entry = new (&allocator_) UninitializedReferenceType(klass,
+ entry = new (&allocator_) UninitializedReferenceType(handles_.NewHandle(klass),
descriptor,
allocation_pc,
entries_.size());
@@ -537,25 +461,25 @@
if (uninit_type.IsUnresolvedTypes()) {
const std::string_view& descriptor(uninit_type.GetDescriptor());
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedReference() &&
cur_entry->GetDescriptor() == descriptor) {
return *cur_entry;
}
}
- entry = new (&allocator_) UnresolvedReferenceType(descriptor, entries_.size());
+ entry = new (&allocator_) UnresolvedReferenceType(null_handle_, descriptor, entries_.size());
} else {
ObjPtr<mirror::Class> klass = uninit_type.GetClass();
if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
// For uninitialized "this reference" look for reference types that are not precise.
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
return *cur_entry;
}
}
- entry = new (&allocator_) ReferenceType(klass, "", entries_.size());
+ entry = new (&allocator_) ReferenceType(handles_.NewHandle(klass), "", entries_.size());
} else if (!klass->IsPrimitive()) {
// We're uninitialized because of allocation, look or create a precise type as allocations
// may only create objects of that type.
@@ -568,13 +492,13 @@
// 2) Checking whether the klass is instantiable and using conflict may produce a hard
// error when the value is used, which leads to a VerifyError, which is not the
// correct semantics.
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsPreciseReference() && cur_entry->GetClass() == klass) {
return *cur_entry;
}
}
- entry = new (&allocator_) PreciseReferenceType(klass,
+ entry = new (&allocator_) PreciseReferenceType(handles_.NewHandle(klass),
uninit_type.GetDescriptor(),
entries_.size());
} else {
@@ -588,31 +512,34 @@
UninitializedType* entry;
const std::string_view& descriptor(type.GetDescriptor());
if (type.IsUnresolvedTypes()) {
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
cur_entry->GetDescriptor() == descriptor) {
return *down_cast<const UninitializedType*>(cur_entry);
}
}
- entry = new (&allocator_) UnresolvedUninitializedThisRefType(descriptor, entries_.size());
+ entry = new (&allocator_) UnresolvedUninitializedThisRefType(
+ null_handle_, descriptor, entries_.size());
} else {
ObjPtr<mirror::Class> klass = type.GetClass();
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
return *down_cast<const UninitializedType*>(cur_entry);
}
}
- entry = new (&allocator_) UninitializedThisReferenceType(klass, descriptor, entries_.size());
+ entry = new (&allocator_) UninitializedThisReferenceType(handles_.NewHandle(klass),
+ descriptor,
+ entries_.size());
}
return AddEntry(entry);
}
const ConstantType& RegTypeCache::FromCat1NonSmallConstant(int32_t value, bool precise) {
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
- if (cur_entry->klass_.IsNull() && cur_entry->IsConstant() &&
+ if (!cur_entry->HasClass() && cur_entry->IsConstant() &&
cur_entry->IsPreciseConstant() == precise &&
(down_cast<const ConstantType*>(cur_entry))->ConstantValue() == value) {
return *down_cast<const ConstantType*>(cur_entry);
@@ -620,15 +547,15 @@
}
ConstantType* entry;
if (precise) {
- entry = new (&allocator_) PreciseConstType(value, entries_.size());
+ entry = new (&allocator_) PreciseConstType(null_handle_, value, entries_.size());
} else {
- entry = new (&allocator_) ImpreciseConstType(value, entries_.size());
+ entry = new (&allocator_) ImpreciseConstType(null_handle_, value, entries_.size());
}
return AddEntry(entry);
}
const ConstantType& RegTypeCache::FromCat2ConstLo(int32_t value, bool precise) {
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsConstantLo() && (cur_entry->IsPrecise() == precise) &&
(down_cast<const ConstantType*>(cur_entry))->ConstantValueLo() == value) {
@@ -637,15 +564,15 @@
}
ConstantType* entry;
if (precise) {
- entry = new (&allocator_) PreciseConstLoType(value, entries_.size());
+ entry = new (&allocator_) PreciseConstLoType(null_handle_, value, entries_.size());
} else {
- entry = new (&allocator_) ImpreciseConstLoType(value, entries_.size());
+ entry = new (&allocator_) ImpreciseConstLoType(null_handle_, value, entries_.size());
}
return AddEntry(entry);
}
const ConstantType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
- for (size_t i = primitive_count_; i < entries_.size(); i++) {
+ for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsConstantHi() && (cur_entry->IsPrecise() == precise) &&
(down_cast<const ConstantType*>(cur_entry))->ConstantValueHi() == value) {
@@ -654,9 +581,9 @@
}
ConstantType* entry;
if (precise) {
- entry = new (&allocator_) PreciseConstHiType(value, entries_.size());
+ entry = new (&allocator_) PreciseConstHiType(null_handle_, value, entries_.size());
} else {
- entry = new (&allocator_) ImpreciseConstHiType(value, entries_.size());
+ entry = new (&allocator_) ImpreciseConstHiType(null_handle_, value, entries_.size());
}
return AddEntry(entry);
}
@@ -693,39 +620,5 @@
}
}
-void RegTypeCache::VisitStaticRoots(RootVisitor* visitor) {
- // Visit the primitive types, this is required since if there are no active verifiers they wont
- // be in the entries array, and therefore not visited as roots.
- if (primitive_initialized_) {
- RootInfo ri(kRootUnknown);
- UndefinedType::GetInstance()->VisitRoots(visitor, ri);
- ConflictType::GetInstance()->VisitRoots(visitor, ri);
- BooleanType::GetInstance()->VisitRoots(visitor, ri);
- ByteType::GetInstance()->VisitRoots(visitor, ri);
- ShortType::GetInstance()->VisitRoots(visitor, ri);
- CharType::GetInstance()->VisitRoots(visitor, ri);
- IntegerType::GetInstance()->VisitRoots(visitor, ri);
- LongLoType::GetInstance()->VisitRoots(visitor, ri);
- LongHiType::GetInstance()->VisitRoots(visitor, ri);
- FloatType::GetInstance()->VisitRoots(visitor, ri);
- DoubleLoType::GetInstance()->VisitRoots(visitor, ri);
- DoubleHiType::GetInstance()->VisitRoots(visitor, ri);
- for (int32_t value = kMinSmallConstant; value <= kMaxSmallConstant; ++value) {
- small_precise_constants_[value - kMinSmallConstant]->VisitRoots(visitor, ri);
- }
- }
-}
-
-void RegTypeCache::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
- // Exclude the static roots that are visited by VisitStaticRoots().
- for (size_t i = primitive_count_; i < entries_.size(); ++i) {
- entries_[i]->VisitRoots(visitor, root_info);
- }
- for (auto& pair : klass_entries_) {
- GcRoot<mirror::Class>& root = pair.first;
- root.VisitRoot(visitor, root_info);
- }
-}
-
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index a6d226a..d88d4db 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -26,6 +26,7 @@
#include "base/scoped_arena_containers.h"
#include "dex/primitive.h"
#include "gc_root.h"
+#include "handle_scope.h"
namespace art {
@@ -68,17 +69,8 @@
RegTypeCache(ClassLinker* class_linker,
bool can_load_classes,
ScopedArenaAllocator& allocator,
+ VariableSizedHandleScope& handles,
bool can_suspend = true);
- ~RegTypeCache();
- static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_) {
- if (!RegTypeCache::primitive_initialized_) {
- CHECK_EQ(RegTypeCache::primitive_count_, 0);
- CreatePrimitiveAndSmallConstantTypes(class_linker);
- CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants);
- RegTypeCache::primitive_initialized_ = true;
- }
- }
- static void ShutDown();
const art::verifier::RegType& GetFromId(uint16_t id) const;
const RegType& From(ObjPtr<mirror::ClassLoader> loader, const char* descriptor, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -161,15 +153,32 @@
void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_);
const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
- void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitStaticRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
ClassLinker* GetClassLinker() {
return class_linker_;
}
+ Handle<mirror::Class> GetNullHandle() const {
+ return null_handle_;
+ }
+
+ static constexpr int32_t kMinSmallConstant = -1;
+ static constexpr int32_t kMaxSmallConstant = 4;
+ static constexpr int32_t kNumSmallConstants = kMaxSmallConstant - kMinSmallConstant + 1;
+ static constexpr size_t kNumPrimitivesAndSmallConstants = 13 + kNumSmallConstants;
+ static constexpr int32_t kBooleanCacheId = kNumSmallConstants;
+ static constexpr int32_t kByteCacheId = kNumSmallConstants + 1;
+ static constexpr int32_t kShortCacheId = kNumSmallConstants + 2;
+ static constexpr int32_t kCharCacheId = kNumSmallConstants + 3;
+ static constexpr int32_t kIntCacheId = kNumSmallConstants + 4;
+ static constexpr int32_t kLongLoCacheId = kNumSmallConstants + 5;
+ static constexpr int32_t kLongHiCacheId = kNumSmallConstants + 6;
+ static constexpr int32_t kFloatCacheId = kNumSmallConstants + 7;
+ static constexpr int32_t kDoubleLoCacheId = kNumSmallConstants + 8;
+ static constexpr int32_t kDoubleHiCacheId = kNumSmallConstants + 9;
+ static constexpr int32_t kUndefinedCacheId = kNumSmallConstants + 10;
+ static constexpr int32_t kConflictCacheId = kNumSmallConstants + 11;
+ static constexpr int32_t kNullCacheId = kNumSmallConstants + 12;
+
private:
void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Class> ResolveClass(const char* descriptor, ObjPtr<mirror::ClassLoader> loader)
@@ -187,33 +196,19 @@
// verifier and return a string view.
std::string_view AddString(const std::string_view& str);
- static void CreatePrimitiveAndSmallConstantTypes(ClassLinker* class_linker)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // A quick look up for popular small constants.
- static constexpr int32_t kMinSmallConstant = -1;
- static constexpr int32_t kMaxSmallConstant = 4;
- static const PreciseConstType* small_precise_constants_[kMaxSmallConstant -
- kMinSmallConstant + 1];
-
- static constexpr size_t kNumPrimitivesAndSmallConstants =
- 13 + (kMaxSmallConstant - kMinSmallConstant + 1);
-
- // Have the well known global primitives been created?
- static bool primitive_initialized_;
-
- // Number of well known primitives that will be copied into a RegTypeCache upon construction.
- static uint16_t primitive_count_;
-
// The actual storage for the RegTypes.
ScopedArenaVector<const RegType*> entries_;
// Fast lookup for quickly finding entries that have a matching class.
- ScopedArenaVector<std::pair<GcRoot<mirror::Class>, const RegType*>> klass_entries_;
+ ScopedArenaVector<std::pair<Handle<mirror::Class>, const RegType*>> klass_entries_;
// Arena allocator.
ScopedArenaAllocator& allocator_;
+ // Handle scope containing classes.
+ VariableSizedHandleScope& handles_;
+ ScopedNullHandle<mirror::Class> null_handle_;
+
ClassLinker* class_linker_;
// Whether or not we're allowed to load classes.
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index a36cf71..8ab7fc8 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -43,7 +43,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& ref_type_const_0 = cache.FromCat1Const(10, true);
const RegType& ref_type_const_1 = cache.FromCat1Const(10, true);
const RegType& ref_type_const_2 = cache.FromCat1Const(30, true);
@@ -67,7 +69,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
int64_t val = static_cast<int32_t>(1234);
const RegType& precise_lo = cache.FromCat2ConstLo(static_cast<int32_t>(val), true);
const RegType& precise_hi = cache.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
@@ -93,7 +97,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& bool_reg_type = cache.Boolean();
EXPECT_FALSE(bool_reg_type.IsUndefined());
@@ -368,7 +374,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& imprecise_obj = cache.JavaLangObject(false);
const RegType& precise_obj = cache.JavaLangObject(true);
const RegType& precise_obj_2 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true);
@@ -385,7 +393,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
@@ -403,7 +413,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
const RegType& ref_type = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
@@ -427,7 +439,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& unresolved_ref = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
const RegType& unresolved_ref_another = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExistEither;", true);
const RegType& resolved_ref = cache.JavaLangString();
@@ -455,7 +469,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& ref_type = cache.JavaLangString();
const RegType& ref_type_2 = cache.JavaLangString();
const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/String;", true);
@@ -477,7 +493,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& ref_type = cache.JavaLangObject(true);
const RegType& ref_type_2 = cache.JavaLangObject(true);
const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true);
@@ -492,7 +510,9 @@
ScopedObjectAccess soa(Thread::Current());
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
- RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache_new(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& string = cache_new.JavaLangString();
const RegType& Object = cache_new.JavaLangObject(true);
EXPECT_TRUE(string.Merge(Object, &cache_new, /* verifier= */ nullptr).IsJavaLangObject());
@@ -517,7 +537,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache_new(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
constexpr int32_t kTestConstantValue = 10;
const RegType& float_type = cache_new.Float();
@@ -550,7 +572,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache_new(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
constexpr int32_t kTestConstantValue = 10;
const RegType& long_lo_type = cache_new.LongLo();
@@ -610,7 +634,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache_new(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
constexpr int32_t kTestConstantValue = 10;
const RegType& double_lo_type = cache_new.DoubleLo();
@@ -724,7 +750,9 @@
ScopedDisableMovingGC no_gc(soa.Self());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& conflict = cache.Conflict();
const RegType& zero = cache.Zero();
@@ -1048,7 +1076,9 @@
ArenaStack stack(Runtime::Current()->GetArenaPool());
ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache_new(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& imprecise_const = cache_new.FromCat1Const(10, false);
const RegType& precise_const = cache_new.FromCat1Const(10, true);
@@ -1087,7 +1117,9 @@
constexpr const char* kNumberArrayFour = "[[[[Ljava/lang/Number;";
constexpr const char* kNumberArrayFive = "[[[[[Ljava/lang/Number;";
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& int_array_array = cache.From(nullptr, kIntArrayFive, false);
ASSERT_TRUE(int_array_array.HasClass());
const RegType& float_array_array = cache.From(nullptr, kFloatArrayFive, false);
@@ -1127,7 +1159,9 @@
ScopedDisableMovingGC no_gc(soa.Self());
- RegTypeCache cache(Runtime::Current()->GetClassLinker(), true, allocator);
+ VariableSizedHandleScope handles(soa.Self());
+ RegTypeCache cache(
+ Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles);
const RegType& c1_reg_type = *cache.InsertClass(in1, c1.Get(), false);
const RegType& c2_reg_type = *cache.InsertClass(in2, c2.Get(), false);
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 7b5a496..6fa87c6 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -184,7 +184,7 @@
reg_to_lock_depths_(std::less<uint32_t>(),
allocator.Adapter(kArenaAllocVerifier)),
this_initialized_(false) {
- std::uninitialized_fill_n(line_, num_regs_, 0u);
+ std::uninitialized_fill_n(line_, num_regs_, RegTypeCache::kUndefinedCacheId);
SetResultTypeToUnknown(reg_types);
}