diff options
| -rw-r--r-- | dex2oat/dex2oat.cc | 5 | ||||
| -rw-r--r-- | runtime/common_throws.cc | 4 | ||||
| -rw-r--r-- | runtime/debug_print.cc | 46 | ||||
| -rw-r--r-- | runtime/debug_print.h | 3 | ||||
| -rw-r--r-- | runtime/jit/profile_compilation_info.h | 6 | ||||
| -rw-r--r-- | runtime/method_handles.cc | 8 | ||||
| -rw-r--r-- | runtime/verifier/register_line-inl.h | 9 | ||||
| -rw-r--r-- | test/956-methodhandles/expected.txt | 12 | ||||
| -rw-r--r-- | test/956-methodhandles/src/Main.java | 56 | ||||
| -rw-r--r-- | test/956-methodhandles/src/other/Chatty.java | 23 | ||||
| -rw-r--r-- | tools/libcore_failures.txt | 7 |
11 files changed, 162 insertions, 17 deletions
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 760147e62e..1e4ed58c8c 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -2516,7 +2516,10 @@ class Dex2Oat FINAL { compiler_options_.get(), oat_file.get())); elf_writers_.back()->Start(); - const bool do_oat_writer_layout = DoDexLayoutOptimizations() || DoOatLayoutOptimizations(); + bool do_oat_writer_layout = DoDexLayoutOptimizations() || DoOatLayoutOptimizations(); + if (profile_compilation_info_ != nullptr && profile_compilation_info_->IsEmpty()) { + do_oat_writer_layout = false; + } oat_writers_.emplace_back(new linker::OatWriter( IsBootImage(), timings_, diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 1b088e24f1..b72dc3ff4c 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -24,6 +24,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" #include "class_linker-inl.h" +#include "debug_print.h" #include "dex/dex_file-inl.h" #include "dex/dex_instruction-inl.h" #include "dex/invoke_type.h" @@ -152,6 +153,7 @@ void ThrowWrappedBootstrapMethodError(const char* fmt, ...) { // ClassCastException void ThrowClassCastException(ObjPtr<mirror::Class> dest_type, ObjPtr<mirror::Class> src_type) { + DumpB77342775DebugData(dest_type, src_type); ThrowException("Ljava/lang/ClassCastException;", nullptr, StringPrintf("%s cannot be cast to %s", mirror::Class::PrettyDescriptor(src_type).c_str(), @@ -279,6 +281,7 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceSuper(ArtMethod* method, << "' does not implement interface '" << mirror::Class::PrettyDescriptor(target_class) << "' in call to '" << ArtMethod::PrettyMethod(method) << "'"; + DumpB77342775DebugData(target_class, this_object->GetClass()); ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer != nullptr ? referrer->GetDeclaringClass() : nullptr, msg.str().c_str()); @@ -295,6 +298,7 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(ArtMethod* inter << "' does not implement interface '" << mirror::Class::PrettyDescriptor(interface_method->GetDeclaringClass()) << "' in call to '" << ArtMethod::PrettyMethod(interface_method) << "'"; + DumpB77342775DebugData(interface_method->GetDeclaringClass(), this_object->GetClass()); ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer != nullptr ? referrer->GetDeclaringClass() : nullptr, msg.str().c_str()); diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc index 44a183669d..c7530bec6e 100644 --- a/runtime/debug_print.cc +++ b/runtime/debug_print.cc @@ -110,4 +110,50 @@ std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* clas return oss.str(); } +void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::Class> src_class) { + std::string target_descriptor_storage; + const char* target_descriptor = target_class->GetDescriptor(&target_descriptor_storage); + const char kCheckedPrefix[] = "Lorg/apache/http/"; + // Avoid spam for other packages. (That spam would break some ART run-tests for example.) + if (strncmp(target_descriptor, kCheckedPrefix, sizeof(kCheckedPrefix) - 1) != 0) { + return; + } + auto matcher = [target_descriptor, target_class](ObjPtr<mirror::Class> klass) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (klass->DescriptorEquals(target_descriptor)) { + LOG(ERROR) << " descriptor match in " + << DescribeLoaders(klass->GetClassLoader(), target_descriptor) + << " match? " << std::boolalpha << (klass == target_class); + } + }; + + std::string source_descriptor_storage; + const char* source_descriptor = src_class->GetDescriptor(&source_descriptor_storage); + + if (target_class->IsInterface()) { + ObjPtr<mirror::IfTable> iftable = src_class->GetIfTable(); + CHECK(iftable != nullptr); + size_t ifcount = iftable->Count(); + LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor + << " with loader " << DescribeLoaders(src_class->GetClassLoader(), target_descriptor) + << " in interface table for " << source_descriptor << " ifcount=" << ifcount; + for (size_t i = 0; i != ifcount; ++i) { + ObjPtr<mirror::Class> iface = iftable->GetInterface(i); + CHECK(iface != nullptr); + LOG(ERROR) << " iface #" << i << ": " << iface->PrettyDescriptor(); + matcher(iface); + } + } else { + LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor + << " with loader " << DescribeLoaders(src_class->GetClassLoader(), target_descriptor) + << " in superclass chain for " << source_descriptor; + for (ObjPtr<mirror::Class> klass = src_class; + klass != nullptr; + klass = klass->GetSuperClass()) { + LOG(ERROR) << " - " << klass->PrettyDescriptor(); + matcher(klass); + } + } +} + } // namespace art diff --git a/runtime/debug_print.h b/runtime/debug_print.h index 479c36a02f..df00f064bd 100644 --- a/runtime/debug_print.h +++ b/runtime/debug_print.h @@ -29,6 +29,9 @@ std::string DescribeSpace(ObjPtr<mirror::Class> klass) std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::Class> src_class) + REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + } // namespace art #endif // ART_RUNTIME_DEBUG_PRINT_H_ diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h index 6c56db9f49..5c4b9e7202 100644 --- a/runtime/jit/profile_compilation_info.h +++ b/runtime/jit/profile_compilation_info.h @@ -439,6 +439,9 @@ class ProfileCompilationInfo { // the method returns false. Otherwise it returns true. bool UpdateProfileKeys(const std::vector<std::unique_ptr<const DexFile>>& dex_files); + // Checks if the profile is empty. + bool IsEmpty() const; + private: enum ProfileLoadStatus { kProfileLoadWouldOverwiteData, @@ -586,9 +589,6 @@ class ProfileCompilationInfo { // the key or the checksum mismatches. const DexFileData* FindDexData(const DexFile* dex_file) const; - // Checks if the profile is empty. - bool IsEmpty() const; - // Inflate the input buffer (in_buffer) of size in_size. It returns a buffer of // compressed data for the input buffer of "compressed_data_size" size. std::unique_ptr<uint8_t[]> DeflateBuffer(const uint8_t* in_buffer, diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc index 82370c4631..64ab78997f 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -674,13 +674,15 @@ ArtMethod* RefineTargetMethod(Thread* self, return WellKnownClasses::StringInitToStringFactory(target_method); } } else if (handle_kind == mirror::MethodHandle::Kind::kInvokeSuper) { - ObjPtr<mirror::Class> declaring_class = target_method->GetDeclaringClass(); - // Note that we're not dynamically dispatching on the type of the receiver // here. We use the static type of the "receiver" object that we've // recorded in the method handle's type, which will be the same as the // special caller that was specified at the point of lookup. ObjPtr<mirror::Class> referrer_class = handle_type->GetPTypes()->Get(0); + ObjPtr<mirror::Class> declaring_class = target_method->GetDeclaringClass(); + if (referrer_class == declaring_class) { + return target_method; + } if (!declaring_class->IsInterface()) { ObjPtr<mirror::Class> super_class = referrer_class->GetSuperClass(); uint16_t vtable_index = target_method->GetMethodIndex(); @@ -690,8 +692,6 @@ ArtMethod* RefineTargetMethod(Thread* self, // will always be declared by super_class (or one of its super classes). DCHECK_LT(vtable_index, super_class->GetVTableLength()); return super_class->GetVTableEntry(vtable_index, kRuntimePointerSize); - } else { - return referrer_class->FindVirtualMethodForInterfaceSuper(target_method, kRuntimePointerSize); } } return target_method; diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h index 39d73f54d8..5160daf42d 100644 --- a/runtime/verifier/register_line-inl.h +++ b/runtime/verifier/register_line-inl.h @@ -20,6 +20,7 @@ #include "register_line.h" #include "base/logging.h" // For VLOG. +#include "debug_print.h" #include "method_verifier.h" #include "reg_type_cache-inl.h" @@ -147,6 +148,14 @@ inline bool RegisterLine::VerifyRegisterType(MethodVerifier* verifier, uint32_t } verifier->Fail(fail_type) << "register v" << vsrc << " has type " << src_type << " but expected " << check_type; + if (check_type.IsNonZeroReferenceTypes() && + !check_type.IsUnresolvedTypes() && + check_type.HasClass() && + src_type.IsNonZeroReferenceTypes() && + !src_type.IsUnresolvedTypes() && + src_type.HasClass()) { + DumpB77342775DebugData(check_type.GetClass(), src_type.GetClass()); + } return false; } if (check_type.IsLowHalf()) { diff --git a/test/956-methodhandles/expected.txt b/test/956-methodhandles/expected.txt index 9b0932708e..6954c22ccb 100644 --- a/test/956-methodhandles/expected.txt +++ b/test/956-methodhandles/expected.txt @@ -3,7 +3,17 @@ foo_A foo_A foo_B privateRyan_D -Received exception: Expected (java.lang.String, java.lang.String)java.lang.String but was (java.lang.String, java.lang.Object)void +Received WrongMethodTypeException exception +G.sayHi() +G.sayHi() +G.sayHi() +F.sayHi() +F.sayHi() +H.chatter() +H.chatter() +H.chatter() +Chatty.chatter() +Chatty.chatter() String constructors done. testReferenceReturnValueConversions done. testPrimitiveReturnValueConversions done. diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java index 1ddef03d62..dee818a4ee 100644 --- a/test/956-methodhandles/src/Main.java +++ b/test/956-methodhandles/src/Main.java @@ -30,6 +30,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import other.Chatty; + public class Main { public static class A { @@ -66,6 +68,30 @@ public class Main { public static final Lookup lookup = MethodHandles.lookup(); } + private interface F { + public default void sayHi() { + System.out.println("F.sayHi()"); + } + } + + public static class G implements F { + public void sayHi() { + System.out.println("G.sayHi()"); + } + public MethodHandles.Lookup getLookup() { + return MethodHandles.lookup(); + } + } + + public static class H implements Chatty { + public void chatter() { + System.out.println("H.chatter()"); + } + public MethodHandles.Lookup getLookup() { + return MethodHandles.lookup(); + } + } + public static void main(String[] args) throws Throwable { testfindSpecial_invokeSuperBehaviour(); testfindSpecial_invokeDirectBehaviour(); @@ -173,7 +199,7 @@ public class Main { handle.invokeExact("a", new Object()); System.out.println("invokeExact(\"a\", new Object()) unexpectedly succeeded."); } catch (WrongMethodTypeException ex) { - System.out.println("Received exception: " + ex.getMessage()); + System.out.println("Received WrongMethodTypeException exception"); } } @@ -528,6 +554,34 @@ public class Main { privateStaticField.set(null, "updatedStaticValue"); mh.invokeExact("updatedStaticValue2"); assertEquals("updatedStaticValue2", (String) privateStaticField.get(null)); + + // unreflectSpecial testing - F is an interface that G implements + + G g = new G(); + g.sayHi(); // prints "G.sayHi()" + + MethodHandles.Lookup lookupInG = g.getLookup(); + Method methodInG = G.class.getDeclaredMethod("sayHi"); + lookupInG.unreflectSpecial(methodInG, G.class).invoke(g); // prints "G.sayHi()" + + Method methodInF = F.class.getDeclaredMethod("sayHi"); + lookupInG.unreflect(methodInF).invoke(g); // prints "G.sayHi()" + lookupInG.in(G.class).unreflectSpecial(methodInF, G.class).invoke(g); // prints "F.sayHi()" + lookupInG.unreflectSpecial(methodInF, G.class).bindTo(g).invokeWithArguments(); + + // unreflectSpecial testing - other.Chatty is an interface that H implements + + H h = new H(); + h.chatter(); + + MethodHandles.Lookup lookupInH = h.getLookup(); + Method methodInH = H.class.getDeclaredMethod("chatter"); + lookupInH.unreflectSpecial(methodInH, H.class).invoke(h); + + Method methodInChatty = Chatty.class.getDeclaredMethod("chatter"); + lookupInH.unreflect(methodInChatty).invoke(h); + lookupInH.in(H.class).unreflectSpecial(methodInChatty, H.class).invoke(h); + lookupInH.unreflectSpecial(methodInChatty, H.class).bindTo(h).invokeWithArguments(); } // This method only exists to fool Jack's handling of types. See b/32536744. diff --git a/test/956-methodhandles/src/other/Chatty.java b/test/956-methodhandles/src/other/Chatty.java new file mode 100644 index 0000000000..98aef14b90 --- /dev/null +++ b/test/956-methodhandles/src/other/Chatty.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package other; + +public interface Chatty { + public default void chatter() { + System.out.println("Chatty.chatter()"); + } +} diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt index 68aeedde85..60aac3cdb5 100644 --- a/tools/libcore_failures.txt +++ b/tools/libcore_failures.txt @@ -214,12 +214,5 @@ description: "java.io.IOException: Error writing ASN.1 encoding", result: EXEC_FAILED, names: ["libcore.javax.crypto.spec.AlgorithmParametersTestGCM#testEncoding"] -}, -{ - description: "Failure only on device. Blacklist it temporarily", - result: EXEC_FAILED, - modes: [device], - bug: 69023954, - names: ["libcore.libcore.io.OsTest#test_setgroups"] } ] |