summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc315
1 files changed, 248 insertions, 67 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 7db83688e2..d02cf17d44 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -70,6 +70,7 @@
#include "jni_internal.h"
#include "leb128.h"
#include "linear_alloc.h"
+#include "mirror/call_site.h"
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/class_ext.h"
@@ -82,6 +83,7 @@
#include "mirror/method.h"
#include "mirror/method_type.h"
#include "mirror/method_handle_impl.h"
+#include "mirror/method_handles_lookup.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
@@ -405,7 +407,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_);
Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>(
heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))));
- CHECK(java_lang_Class.Get() != nullptr);
+ CHECK(java_lang_Class != nullptr);
mirror::Class::SetClassClass(java_lang_Class.Get());
java_lang_Class->SetClass(java_lang_Class.Get());
if (kUseBakerReadBarrier) {
@@ -425,7 +427,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// java_lang_Object comes next so that object_array_class can be created.
Handle<mirror::Class> java_lang_Object(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Object::ClassSize(image_pointer_size_))));
- CHECK(java_lang_Object.Get() != nullptr);
+ CHECK(java_lang_Object != nullptr);
// backfill Object as the super class of Class.
java_lang_Class->SetSuperClass(java_lang_Object.Get());
mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusLoaded, self);
@@ -624,9 +626,9 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Setup the single, global copy of "iftable".
auto java_lang_Cloneable = hs.NewHandle(FindSystemClass(self, "Ljava/lang/Cloneable;"));
- CHECK(java_lang_Cloneable.Get() != nullptr);
+ CHECK(java_lang_Cloneable != nullptr);
auto java_io_Serializable = hs.NewHandle(FindSystemClass(self, "Ljava/io/Serializable;"));
- CHECK(java_io_Serializable.Get() != nullptr);
+ CHECK(java_io_Serializable != nullptr);
// We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
// crawl up and explicitly list all of the supers as well.
array_iftable_.Read()->SetInterface(0, java_lang_Cloneable.Get());
@@ -695,6 +697,18 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
SetClassRoot(kJavaLangInvokeMethodHandleImpl, class_root);
mirror::MethodHandleImpl::SetClass(class_root);
+ // Create java.lang.invoke.MethodHandles.Lookup.class root
+ class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandles$Lookup;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangInvokeMethodHandlesLookup, class_root);
+ mirror::MethodHandlesLookup::SetClass(class_root);
+
+ // Create java.lang.invoke.CallSite.class root
+ class_root = FindSystemClass(self, "Ljava/lang/invoke/CallSite;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangInvokeCallSite, class_root);
+ mirror::CallSite::SetClass(class_root);
+
class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;");
CHECK(class_root != nullptr);
SetClassRoot(kDalvikSystemEmulatedStackFrame, class_root);
@@ -981,6 +995,8 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass));
mirror::MethodType::SetClass(GetClassRoot(kJavaLangInvokeMethodType));
mirror::MethodHandleImpl::SetClass(GetClassRoot(kJavaLangInvokeMethodHandleImpl));
+ mirror::MethodHandlesLookup::SetClass(GetClassRoot(kJavaLangInvokeMethodHandlesLookup));
+ mirror::CallSite::SetClass(GetClassRoot(kJavaLangInvokeCallSite));
mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
@@ -1231,12 +1247,13 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
if (dex_file->NumProtoIds() < num_method_types) {
num_method_types = dex_file->NumProtoIds();
}
-
+ const size_t num_call_sites = dex_file->NumCallSiteIds();
CHECK_EQ(num_strings, dex_cache->NumStrings());
CHECK_EQ(num_types, dex_cache->NumResolvedTypes());
CHECK_EQ(num_methods, dex_cache->NumResolvedMethods());
CHECK_EQ(num_fields, dex_cache->NumResolvedFields());
CHECK_EQ(num_method_types, dex_cache->NumResolvedMethodTypes());
+ CHECK_EQ(num_call_sites, dex_cache->NumResolvedCallSites());
DexCacheArraysLayout layout(image_pointer_size_, dex_file);
uint8_t* const raw_arrays = oat_dex_file->GetDexCacheArrays();
if (num_strings != 0u) {
@@ -1316,6 +1333,22 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
mirror::MethodTypeDexCachePair::Initialize(method_types);
dex_cache->SetResolvedMethodTypes(method_types);
}
+ if (num_call_sites != 0u) {
+ GcRoot<mirror::CallSite>* const image_resolved_call_sites =
+ dex_cache->GetResolvedCallSites();
+ GcRoot<mirror::CallSite>* const call_sites =
+ reinterpret_cast<GcRoot<mirror::CallSite>*>(raw_arrays + layout.CallSitesOffset());
+ for (size_t j = 0; kIsDebugBuild && j < num_call_sites; ++j) {
+ DCHECK(call_sites[j].IsNull());
+ }
+ CopyNonNull(image_resolved_call_sites,
+ num_call_sites,
+ call_sites,
+ [](const GcRoot<mirror::CallSite>& elem) {
+ return elem.IsNull();
+ });
+ dex_cache->SetResolvedCallSites(call_sites);
+ }
}
{
WriterMutexLock mu2(self, *Locks::dex_lock_);
@@ -1615,7 +1648,7 @@ bool ClassLinker::AddImageSpace(
DCHECK(out_dex_files != nullptr);
DCHECK(error_msg != nullptr);
const uint64_t start_time = NanoTime();
- const bool app_image = class_loader.Get() != nullptr;
+ const bool app_image = class_loader != nullptr;
const ImageHeader& header = space->GetImageHeader();
ObjPtr<mirror::Object> dex_caches_object = header.GetImageRoot(ImageHeader::kDexCaches);
DCHECK(dex_caches_object != nullptr);
@@ -1645,7 +1678,7 @@ bool ClassLinker::AddImageSpace(
"Class loader should be the last image root.");
MutableHandle<mirror::ClassLoader> image_class_loader(hs.NewHandle(
app_image ? header.GetImageRoot(ImageHeader::kClassLoader)->AsClassLoader() : nullptr));
- DCHECK(class_roots.Get() != nullptr);
+ DCHECK(class_roots != nullptr);
if (class_roots->GetLength() != static_cast<int32_t>(kClassRootsMax)) {
*error_msg = StringPrintf("Expected %d class roots but got %d",
class_roots->GetLength(),
@@ -2074,7 +2107,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
classes.Assign(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, class_table_size));
- CHECK(classes.Get() != nullptr); // OOME.
+ CHECK(classes != nullptr); // OOME.
GetClassInToObjectArray accumulator(classes.Get());
VisitClasses(&accumulator);
if (accumulator.Succeeded()) {
@@ -2115,6 +2148,8 @@ ClassLinker::~ClassLinker() {
mirror::ShortArray::ResetArrayClass();
mirror::MethodType::ResetClass();
mirror::MethodHandleImpl::ResetClass();
+ mirror::MethodHandlesLookup::ResetClass();
+ mirror::CallSite::ResetClass();
mirror::EmulatedStackFrame::ResetClass();
Thread* const self = Thread::Current();
for (const ClassLoaderData& data : class_loaders_) {
@@ -2152,7 +2187,7 @@ mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_locatio
DCHECK(out_location != nullptr);
auto dex_cache(hs.NewHandle(ObjPtr<mirror::DexCache>::DownCast(
GetClassRoot(kJavaLangDexCache)->AllocObject(self))));
- if (dex_cache.Get() == nullptr) {
+ if (dex_cache == nullptr) {
self->AssertPendingOOMException();
return nullptr;
}
@@ -2453,7 +2488,7 @@ mirror::Class* ClassLinker::FindClass(Thread* self,
return EnsureResolved(self, descriptor, klass);
}
// Class is not yet loaded.
- if (descriptor[0] != '[' && class_loader.Get() == nullptr) {
+ if (descriptor[0] != '[' && class_loader == nullptr) {
// Non-array class and the boot class loader, search the boot class path.
ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_);
if (pair.second != nullptr) {
@@ -2616,14 +2651,14 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
}
}
- if (klass.Get() == nullptr) {
+ if (klass == nullptr) {
// Allocate a class with the status of not ready.
// Interface object should get the right size here. Regular class will
// figure out the right size later and be replaced with one of the right
// size when the class becomes resolved.
klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
}
- if (UNLIKELY(klass.Get() == nullptr)) {
+ if (UNLIKELY(klass == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
}
@@ -2716,7 +2751,7 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
return nullptr;
}
self->AssertNoPendingException();
- CHECK(h_new_class.Get() != nullptr) << descriptor;
+ CHECK(h_new_class != nullptr) << descriptor;
CHECK(h_new_class->IsResolved() && !h_new_class->IsErroneousResolved()) << descriptor;
// Instrumentation may have updated entrypoints for all methods of all
@@ -2997,7 +3032,7 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
Handle<mirror::Class> klass,
ObjPtr<mirror::ClassLoader> class_loader) {
- CHECK(klass.Get() != nullptr);
+ CHECK(klass != nullptr);
CHECK(klass->GetDexCache() != nullptr);
CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus());
const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
@@ -3112,6 +3147,7 @@ void ClassLinker::LoadClassMembers(Thread* self,
last_field_idx = field_idx;
}
}
+
// Load instance fields.
LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
allocator,
@@ -3128,6 +3164,7 @@ void ClassLinker::LoadClassMembers(Thread* self,
last_field_idx = field_idx;
}
}
+
if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
UNLIKELY(num_ifields != it.NumInstanceFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
@@ -3367,7 +3404,7 @@ ObjPtr<mirror::DexCache> ClassLinker::RegisterDexFile(const DexFile& dex_file,
WriterMutexLock mu(self, *Locks::dex_lock_);
old_data = FindDexCacheDataLocked(dex_file);
old_dex_cache = DecodeDexCache(self, old_data);
- if (old_dex_cache == nullptr && h_dex_cache.Get() != nullptr) {
+ if (old_dex_cache == nullptr && h_dex_cache != nullptr) {
// Do InitializeDexCache while holding dex lock to make sure two threads don't call it at the
// same time with the same dex cache. Since the .bss is shared this can cause failing DCHECK
// that the arrays are null.
@@ -3383,12 +3420,12 @@ ObjPtr<mirror::DexCache> ClassLinker::RegisterDexFile(const DexFile& dex_file,
if (old_dex_cache != nullptr) {
// Another thread managed to initialize the dex cache faster, so use that DexCache.
// If this thread encountered OOME, ignore it.
- DCHECK_EQ(h_dex_cache.Get() == nullptr, self->IsExceptionPending());
+ DCHECK_EQ(h_dex_cache == nullptr, self->IsExceptionPending());
self->ClearException();
// We cannot call EnsureSameClassLoader() while holding the dex_lock_.
return EnsureSameClassLoader(self, old_dex_cache, old_data, h_class_loader.Get());
}
- if (h_dex_cache.Get() == nullptr) {
+ if (h_dex_cache == nullptr) {
self->AssertPendingOOMException();
return nullptr;
}
@@ -3517,12 +3554,12 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
StackHandleScope<2> hs(self);
MutableHandle<mirror::Class> component_type(hs.NewHandle(FindClass(self, descriptor + 1,
class_loader)));
- if (component_type.Get() == nullptr) {
+ if (component_type == nullptr) {
DCHECK(self->IsExceptionPending());
// We need to accept erroneous classes as component types.
const size_t component_hash = ComputeModifiedUtf8Hash(descriptor + 1);
component_type.Assign(LookupClass(self, descriptor + 1, component_hash, class_loader.Get()));
- if (component_type.Get() == nullptr) {
+ if (component_type == nullptr) {
DCHECK(self->IsExceptionPending());
return nullptr;
} else {
@@ -3583,9 +3620,9 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
new_class.Assign(GetClassRoot(kLongArrayClass));
}
}
- if (new_class.Get() == nullptr) {
+ if (new_class == nullptr) {
new_class.Assign(AllocClass(self, mirror::Array::ClassSize(image_pointer_size_)));
- if (new_class.Get() == nullptr) {
+ if (new_class == nullptr) {
self->AssertPendingOOMException();
return nullptr;
}
@@ -3818,8 +3855,8 @@ bool ClassLinker::AttemptSupertypeVerification(Thread* self,
Handle<mirror::Class> klass,
Handle<mirror::Class> supertype) {
DCHECK(self != nullptr);
- DCHECK(klass.Get() != nullptr);
- DCHECK(supertype.Get() != nullptr);
+ DCHECK(klass != nullptr);
+ DCHECK(supertype != nullptr);
if (!supertype->IsVerified() && !supertype->IsErroneous()) {
VerifyClass(self, supertype);
@@ -3836,13 +3873,13 @@ bool ClassLinker::AttemptSupertypeVerification(Thread* self,
LOG(WARNING) << error_msg << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
StackHandleScope<1> hs(self);
Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException()));
- if (cause.Get() != nullptr) {
+ if (cause != nullptr) {
// Set during VerifyClass call (if at all).
self->ClearException();
}
// Change into a verify error.
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
- if (cause.Get() != nullptr) {
+ if (cause != nullptr) {
self->GetException()->SetCause(cause.Get());
}
ClassReference ref(klass->GetDexCache()->GetDexFile(), klass->GetDexClassDefIndex());
@@ -3921,7 +3958,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
StackHandleScope<2> hs(self);
MutableHandle<mirror::Class> supertype(hs.NewHandle(klass->GetSuperClass()));
// If we have a superclass and we get a hard verification failure we can return immediately.
- if (supertype.Get() != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
+ if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
return verifier::MethodVerifier::kHardFailure;
}
@@ -3936,14 +3973,14 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
// but choose not to for an optimization. If the interfaces is being verified due to a class
// initialization (which would need all the default interfaces to be verified) the class code
// will trigger the recursive verification anyway.
- if ((supertype.Get() == nullptr || supertype->IsVerified()) // See (1)
+ if ((supertype == nullptr || supertype->IsVerified()) // See (1)
&& !klass->IsInterface()) { // See (2)
int32_t iftable_count = klass->GetIfTableCount();
MutableHandle<mirror::Class> iface(hs.NewHandle<mirror::Class>(nullptr));
// Loop through all interfaces this class has defined. It doesn't matter the order.
for (int32_t i = 0; i < iftable_count; i++) {
iface.Assign(klass->GetIfTable()->GetInterface(i));
- DCHECK(iface.Get() != nullptr);
+ DCHECK(iface != nullptr);
// We only care if we have default interfaces and can skip if we are already verified...
if (LIKELY(!iface->HasDefaultMethods() || iface->IsVerified())) {
continue;
@@ -3963,7 +4000,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
// At this point if verification failed, then supertype is the "first" supertype that failed
// verification (without a specific order). If verification succeeded, then supertype is either
// null or the original superclass of klass and is verified.
- DCHECK(supertype.Get() == nullptr ||
+ DCHECK(supertype == nullptr ||
supertype.Get() == klass->GetSuperClass() ||
!supertype->IsVerified());
@@ -4004,7 +4041,7 @@ verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
if (verifier_failure == verifier::MethodVerifier::kNoFailure) {
// Even though there were no verifier failures we need to respect whether the super-class and
// super-default-interfaces were verified or requiring runtime reverification.
- if (supertype.Get() == nullptr || supertype->IsVerified()) {
+ if (supertype == nullptr || supertype->IsVerified()) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
} else {
CHECK_EQ(supertype->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
@@ -4187,7 +4224,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
StackHandleScope<10> hs(self);
MutableHandle<mirror::Class> klass(hs.NewHandle(
AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class))));
- if (klass.Get() == nullptr) {
+ if (klass == nullptr) {
CHECK(self->IsExceptionPending()); // OOME.
return nullptr;
}
@@ -4611,7 +4648,7 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
MutableHandle<mirror::Class> handle_scope_iface(hs_iface.NewHandle<mirror::Class>(nullptr));
for (size_t i = 0; i < num_direct_interfaces; i++) {
handle_scope_iface.Assign(mirror::Class::GetDirectInterface(self, klass.Get(), i));
- CHECK(handle_scope_iface.Get() != nullptr);
+ CHECK(handle_scope_iface != nullptr);
CHECK(handle_scope_iface->IsInterface());
if (handle_scope_iface->HasBeenRecursivelyInitialized()) {
// We have already done this for this interface. Skip it.
@@ -4890,7 +4927,7 @@ static bool HasSameSignatureWithDifferentClassLoaders(Thread* self,
{
StackHandleScope<1> hs(self);
Handle<mirror::Class> return_type(hs.NewHandle(method1->GetReturnType(true /* resolve */)));
- if (UNLIKELY(return_type.Get() == nullptr)) {
+ if (UNLIKELY(return_type == nullptr)) {
ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method1);
return false;
}
@@ -4940,7 +4977,7 @@ static bool HasSameSignatureWithDifferentClassLoaders(Thread* self,
dex::TypeIndex param_type_idx = types1->GetTypeItem(i).type_idx_;
Handle<mirror::Class> param_type(hs.NewHandle(
method1->GetClassFromTypeIndex(param_type_idx, true /* resolve */)));
- if (UNLIKELY(param_type.Get() == nullptr)) {
+ if (UNLIKELY(param_type == nullptr)) {
ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
method1, i, param_type_idx);
return false;
@@ -5022,7 +5059,7 @@ bool ClassLinker::EnsureInitialized(Thread* self,
Handle<mirror::Class> c,
bool can_init_fields,
bool can_init_parents) {
- DCHECK(c.Get() != nullptr);
+ DCHECK(c != nullptr);
if (c->IsInitialized()) {
EnsureSkipAccessChecksMethods(c, image_pointer_size_);
self->AssertNoPendingException();
@@ -5202,7 +5239,7 @@ bool ClassLinker::LinkClass(Thread* self,
klass->SetMethodsPtrUnchecked(nullptr, 0, 0);
klass->SetSFieldsPtrUnchecked(nullptr);
klass->SetIFieldsPtrUnchecked(nullptr);
- if (UNLIKELY(h_new_class.Get() == nullptr)) {
+ if (UNLIKELY(h_new_class == nullptr)) {
self->AssertPendingOOMException();
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
return false;
@@ -5746,7 +5783,7 @@ bool ClassLinker::LinkVirtualMethods(
MutableHandle<mirror::PointerArray> vtable;
if (super_class->ShouldHaveEmbeddedVTable()) {
vtable = hs.NewHandle(AllocPointerArray(self, max_count));
- if (UNLIKELY(vtable.Get() == nullptr)) {
+ if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
}
@@ -5775,7 +5812,7 @@ bool ClassLinker::LinkVirtualMethods(
}
vtable = hs.NewHandle(down_cast<mirror::PointerArray*>(
super_vtable->CopyOf(self, max_count)));
- if (UNLIKELY(vtable.Get() == nullptr)) {
+ if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
}
@@ -5911,7 +5948,7 @@ bool ClassLinker::LinkVirtualMethods(
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count)));
- if (UNLIKELY(vtable.Get() == nullptr)) {
+ if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
}
@@ -5964,8 +6001,8 @@ static bool ContainsOverridingMethodOf(Thread* self,
PointerSize image_pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(self != nullptr);
- DCHECK(iface.Get() != nullptr);
- DCHECK(iftable.Get() != nullptr);
+ DCHECK(iface != nullptr);
+ DCHECK(iftable != nullptr);
DCHECK_GE(ifstart, 0u);
DCHECK_LT(ifstart, iftable->Count());
DCHECK_EQ(iface.Get(), iftable->GetInterface(ifstart));
@@ -6050,7 +6087,7 @@ ClassLinker::DefaultMethodSearchResult ClassLinker::FindDefaultMethodImplementat
<< "This will be a fatal error in subsequent versions of android. "
<< "Continuing anyway.";
}
- if (UNLIKELY(chosen_iface.Get() != nullptr)) {
+ if (UNLIKELY(chosen_iface != nullptr)) {
// We have multiple default impls of the same method. This is a potential default conflict.
// We need to check if this possibly conflicting method is either a superclass of the chosen
// default implementation or is overridden by a non-default interface method. In either case
@@ -6505,7 +6542,7 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
StackHandleScope<1> hs(self);
const bool has_superclass = klass->HasSuperClass();
const size_t super_ifcount = has_superclass ? klass->GetSuperClass()->GetIfTableCount() : 0U;
- const bool have_interfaces = interfaces.Get() != nullptr;
+ const bool have_interfaces = interfaces != nullptr;
const size_t num_interfaces =
have_interfaces ? interfaces->GetLength() : klass->NumDirectInterfaces();
if (num_interfaces == 0) {
@@ -6551,7 +6588,7 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
}
// Create the interface function table.
MutableHandle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount)));
- if (UNLIKELY(iftable.Get() == nullptr)) {
+ if (UNLIKELY(iftable == nullptr)) {
self->AssertPendingOOMException();
return false;
}
@@ -6589,7 +6626,7 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
DCHECK_NE(num_interfaces, 0U);
iftable.Assign(down_cast<mirror::IfTable*>(
iftable->CopyOf(self, new_ifcount * mirror::IfTable::kMax)));
- if (UNLIKELY(iftable.Get() == nullptr)) {
+ if (UNLIKELY(iftable == nullptr)) {
self->AssertPendingOOMException();
return false;
}
@@ -6630,7 +6667,7 @@ static void CheckClassOwnsVTableEntries(Thread* self,
Handle<mirror::PointerArray> check_vtable(hs.NewHandle(klass->GetVTableDuringLinking()));
ObjPtr<mirror::Class> super_temp = (klass->HasSuperClass()) ? klass->GetSuperClass() : nullptr;
Handle<mirror::Class> superclass(hs.NewHandle(super_temp));
- int32_t super_vtable_length = (superclass.Get() != nullptr) ? superclass->GetVTableLength() : 0;
+ int32_t super_vtable_length = (superclass != nullptr) ? superclass->GetVTableLength() : 0;
for (int32_t i = 0; i < check_vtable->GetLength(); ++i) {
ArtMethod* m = check_vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size);
CHECK(m != nullptr);
@@ -7289,7 +7326,7 @@ bool ClassLinker::LinkInterfaceMethods(
// For a new interface, however, we need the whole vtable in case a new
// interface method is implemented in the whole superclass.
using_virtuals = false;
- DCHECK(vtable.Get() != nullptr);
+ DCHECK(vtable != nullptr);
input_vtable_array = vtable;
input_array_length = input_vtable_array->GetLength();
}
@@ -7432,7 +7469,7 @@ bool ClassLinker::LinkInterfaceMethods(
if (fill_tables) {
vtable.Assign(helper.UpdateVtable(default_translations, vtable.Get()));
- if (UNLIKELY(vtable.Get() == nullptr)) {
+ if (UNLIKELY(vtable == nullptr)) {
// The helper has already called self->AssertPendingOOMException();
return false;
}
@@ -7452,12 +7489,12 @@ bool ClassLinker::LinkInterfaceMethods(
}
bool ClassLinker::LinkInstanceFields(Thread* self, Handle<mirror::Class> klass) {
- CHECK(klass.Get() != nullptr);
+ CHECK(klass != nullptr);
return LinkFields(self, klass, false, nullptr);
}
bool ClassLinker::LinkStaticFields(Thread* self, Handle<mirror::Class> klass, size_t* class_size) {
- CHECK(klass.Get() != nullptr);
+ CHECK(klass != nullptr);
return LinkFields(self, klass, true, class_size);
}
@@ -7713,7 +7750,7 @@ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) {
mirror::String* ClassLinker::ResolveString(const DexFile& dex_file,
dex::StringIndex string_idx,
Handle<mirror::DexCache> dex_cache) {
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
Thread::PoisonObjectPointersIfDebug();
ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
if (resolved != nullptr) {
@@ -7729,7 +7766,7 @@ mirror::String* ClassLinker::ResolveString(const DexFile& dex_file,
mirror::String* ClassLinker::LookupString(const DexFile& dex_file,
dex::StringIndex string_idx,
Handle<mirror::DexCache> dex_cache) {
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
if (resolved != nullptr) {
return resolved.Ptr();
@@ -7783,7 +7820,7 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file,
dex::TypeIndex type_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
Thread::PoisonObjectPointersIfDebug();
ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
if (resolved == nullptr) {
@@ -7821,7 +7858,7 @@ ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
Handle<mirror::ClassLoader> class_loader,
ArtMethod* referrer,
InvokeType type) {
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
// Check for hit in the dex cache.
ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
Thread::PoisonObjectPointersIfDebug();
@@ -8060,7 +8097,7 @@ ArtField* ClassLinker::ResolveField(const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader,
bool is_static) {
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr) {
@@ -8101,7 +8138,7 @@ ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
uint32_t field_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr) {
@@ -8132,7 +8169,7 @@ mirror::MethodType* ClassLinker::ResolveMethodType(const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
- DCHECK(dex_cache.Get() != nullptr);
+ DCHECK(dex_cache != nullptr);
ObjPtr<mirror::MethodType> resolved = dex_cache->GetResolvedMethodType(proto_idx);
if (resolved != nullptr) {
@@ -8146,7 +8183,7 @@ mirror::MethodType* ClassLinker::ResolveMethodType(const DexFile& dex_file,
const DexFile::ProtoId& proto_id = dex_file.GetProtoId(proto_idx);
Handle<mirror::Class> return_type(hs.NewHandle(
ResolveType(dex_file, proto_id.return_type_idx_, dex_cache, class_loader)));
- if (return_type.Get() == nullptr) {
+ if (return_type == nullptr) {
DCHECK(self->IsExceptionPending());
return nullptr;
}
@@ -8161,7 +8198,7 @@ mirror::MethodType* ClassLinker::ResolveMethodType(const DexFile& dex_file,
ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_method_args)));
- if (method_params.Get() == nullptr) {
+ if (method_params == nullptr) {
DCHECK(self->IsExceptionPending());
return nullptr;
}
@@ -8172,7 +8209,7 @@ mirror::MethodType* ClassLinker::ResolveMethodType(const DexFile& dex_file,
for (; it.HasNext(); it.Next()) {
const dex::TypeIndex type_idx = it.GetTypeIdx();
param_class.Assign(ResolveType(dex_file, type_idx, dex_cache, class_loader));
- if (param_class.Get() == nullptr) {
+ if (param_class == nullptr) {
DCHECK(self->IsExceptionPending());
return nullptr;
}
@@ -8189,6 +8226,148 @@ mirror::MethodType* ClassLinker::ResolveMethodType(const DexFile& dex_file,
return type.Get();
}
+mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_idx,
+ ArtMethod* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ Thread* const self = Thread::Current();
+ const DexFile* const dex_file = referrer->GetDexFile();
+ const DexFile::MethodHandleItem& mh = dex_file->GetMethodHandle(method_handle_idx);
+
+ union {
+ ArtField* field;
+ ArtMethod* method;
+ uintptr_t field_or_method;
+ } target;
+ uint32_t num_params;
+ mirror::MethodHandle::Kind kind;
+ DexFile::MethodHandleType handle_type =
+ static_cast<DexFile::MethodHandleType>(mh.method_handle_type_);
+ switch (handle_type) {
+ case DexFile::MethodHandleType::kStaticPut: {
+ kind = mirror::MethodHandle::Kind::kStaticPut;
+ target.field = ResolveField(mh.field_or_method_idx_, referrer, true /* is_static */);
+ num_params = 1;
+ break;
+ }
+ case DexFile::MethodHandleType::kStaticGet: {
+ kind = mirror::MethodHandle::Kind::kStaticGet;
+ target.field = ResolveField(mh.field_or_method_idx_, referrer, true /* is_static */);
+ num_params = 0;
+ break;
+ }
+ case DexFile::MethodHandleType::kInstancePut: {
+ kind = mirror::MethodHandle::Kind::kInstancePut;
+ target.field = ResolveField(mh.field_or_method_idx_, referrer, false /* is_static */);
+ num_params = 2;
+ break;
+ }
+ case DexFile::MethodHandleType::kInstanceGet: {
+ kind = mirror::MethodHandle::Kind::kInstanceGet;
+ target.field = ResolveField(mh.field_or_method_idx_, referrer, false /* is_static */);
+ num_params = 1;
+ break;
+ }
+ case DexFile::MethodHandleType::kInvokeStatic: {
+ kind = mirror::MethodHandle::Kind::kInvokeStatic;
+ target.method = ResolveMethod<kNoICCECheckForCache>(self,
+ mh.field_or_method_idx_,
+ referrer,
+ InvokeType::kStatic);
+ uint32_t shorty_length;
+ target.method->GetShorty(&shorty_length);
+ num_params = shorty_length - 1; // Remove 1 for return value.
+ break;
+ }
+ case DexFile::MethodHandleType::kInvokeInstance: {
+ kind = mirror::MethodHandle::Kind::kInvokeVirtual;
+ target.method = ResolveMethod<kNoICCECheckForCache>(self,
+ mh.field_or_method_idx_,
+ referrer,
+ InvokeType::kVirtual);
+ uint32_t shorty_length;
+ target.method->GetShorty(&shorty_length);
+ num_params = shorty_length - 1; // Remove 1 for return value.
+ break;
+ }
+ case DexFile::MethodHandleType::kInvokeConstructor: {
+ UNIMPLEMENTED(FATAL) << "Invoke constructor is implemented as a transform.";
+ num_params = 0;
+ }
+ }
+
+ StackHandleScope<5> hs(self);
+ ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
+ ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
+ mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params)));
+ if (method_params.Get() == nullptr) {
+ DCHECK(self->IsExceptionPending());
+ return nullptr;
+ }
+
+ Handle<mirror::Class> return_type;
+ switch (handle_type) {
+ case DexFile::MethodHandleType::kStaticPut: {
+ method_params->Set(0, target.field->GetType<true>());
+ return_type = hs.NewHandle(FindPrimitiveClass('V'));
+ break;
+ }
+ case DexFile::MethodHandleType::kStaticGet: {
+ return_type = hs.NewHandle(target.field->GetType<true>());
+ break;
+ }
+ case DexFile::MethodHandleType::kInstancePut: {
+ method_params->Set(0, target.field->GetDeclaringClass());
+ method_params->Set(1, target.field->GetType<true>());
+ return_type = hs.NewHandle(FindPrimitiveClass('V'));
+ break;
+ }
+ case DexFile::MethodHandleType::kInstanceGet: {
+ method_params->Set(0, target.field->GetDeclaringClass());
+ return_type = hs.NewHandle(target.field->GetType<true>());
+ break;
+ }
+ case DexFile::MethodHandleType::kInvokeStatic:
+ case DexFile::MethodHandleType::kInvokeInstance: {
+ // TODO(oth): This will not work for varargs methods as this
+ // requires instantiating a Transformer. This resolution step
+ // would be best done in managed code rather than in the run
+ // time (b/35235705)
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
+ DexFileParameterIterator it(*dex_file, target.method->GetPrototype());
+ for (int32_t i = 0; it.HasNext(); i++, it.Next()) {
+ const dex::TypeIndex type_idx = it.GetTypeIdx();
+ mirror::Class* klass = ResolveType(*dex_file, type_idx, dex_cache, class_loader);
+ if (nullptr == klass) {
+ DCHECK(self->IsExceptionPending());
+ return nullptr;
+ }
+ method_params->Set(i, klass);
+ }
+ return_type = hs.NewHandle(target.method->GetReturnType(true));
+ break;
+ }
+ case DexFile::MethodHandleType::kInvokeConstructor: {
+ // TODO(oth): b/35235705
+ UNIMPLEMENTED(FATAL) << "Invoke constructor is implemented as a transform.";
+ }
+ }
+
+ if (return_type.IsNull()) {
+ DCHECK(self->IsExceptionPending());
+ return nullptr;
+ }
+
+ Handle<mirror::MethodType>
+ mt(hs.NewHandle(mirror::MethodType::Create(self, return_type, method_params)));
+ if (mt.IsNull()) {
+ DCHECK(self->IsExceptionPending());
+ return nullptr;
+ }
+ return mirror::MethodHandleImpl::Create(self, target.field_or_method, kind, mt);
+}
+
bool ClassLinker::IsQuickResolutionStub(const void* entry_point) const {
return (entry_point == GetQuickResolutionStub()) ||
(quick_resolution_trampoline_ == entry_point);
@@ -8304,7 +8483,9 @@ const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) {
"[Ljava/lang/reflect/Constructor;",
"[Ljava/lang/reflect/Field;",
"[Ljava/lang/reflect/Method;",
+ "Ljava/lang/invoke/CallSite;",
"Ljava/lang/invoke/MethodHandleImpl;",
+ "Ljava/lang/invoke/MethodHandles$Lookup;",
"Ljava/lang/invoke/MethodType;",
"Ljava/lang/ClassLoader;",
"Ljava/lang/Throwable;",
@@ -8352,7 +8533,7 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self,
jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements);
Handle<mirror::Class> dex_elements_class(hs.NewHandle(dex_elements_field->GetType<true>()));
- DCHECK(dex_elements_class.Get() != nullptr);
+ DCHECK(dex_elements_class != nullptr);
DCHECK(dex_elements_class->IsArrayClass());
Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle(
mirror::ObjectArray<mirror::Object>::Alloc(self,
@@ -8381,21 +8562,21 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self,
Handle<mirror::LongArray> h_long_array = hs2.NewHandle(mirror::LongArray::Alloc(
self,
kDexFileIndexStart + 1));
- DCHECK(h_long_array.Get() != nullptr);
+ DCHECK(h_long_array != nullptr);
h_long_array->Set(kDexFileIndexStart, reinterpret_cast<intptr_t>(dex_file));
Handle<mirror::Object> h_dex_file = hs2.NewHandle(
cookie_field->GetDeclaringClass()->AllocObject(self));
- DCHECK(h_dex_file.Get() != nullptr);
+ DCHECK(h_dex_file != nullptr);
cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get());
Handle<mirror::String> h_file_name = hs2.NewHandle(
mirror::String::AllocFromModifiedUtf8(self, dex_file->GetLocation().c_str()));
- DCHECK(h_file_name.Get() != nullptr);
+ DCHECK(h_file_name != nullptr);
file_name_field->SetObject<false>(h_dex_file.Get(), h_file_name.Get());
Handle<mirror::Object> h_element = hs2.NewHandle(h_dex_element_class->AllocObject(self));
- DCHECK(h_element.Get() != nullptr);
+ DCHECK(h_element != nullptr);
element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get());
h_dex_elements->Set(index, h_element.Get());
@@ -8406,7 +8587,7 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self,
// Create DexPathList.
Handle<mirror::Object> h_dex_path_list = hs.NewHandle(
dex_elements_field->GetDeclaringClass()->AllocObject(self));
- DCHECK(h_dex_path_list.Get() != nullptr);
+ DCHECK(h_dex_path_list != nullptr);
// Set elements.
dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get());
@@ -8415,7 +8596,7 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self,
soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
Handle<mirror::Object> h_path_class_loader = hs.NewHandle(
h_path_class_class->AllocObject(self));
- DCHECK(h_path_class_loader.Get() != nullptr);
+ DCHECK(h_path_class_loader != nullptr);
// Set DexPathList.
ArtField* path_list_field =
jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList);