summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/dex2oat.cc5
-rw-r--r--runtime/common_throws.cc4
-rw-r--r--runtime/debug_print.cc46
-rw-r--r--runtime/debug_print.h3
-rw-r--r--runtime/jit/profile_compilation_info.h6
-rw-r--r--runtime/method_handles.cc8
-rw-r--r--runtime/verifier/register_line-inl.h9
-rw-r--r--test/956-methodhandles/expected.txt12
-rw-r--r--test/956-methodhandles/src/Main.java56
-rw-r--r--test/956-methodhandles/src/other/Chatty.java23
-rw-r--r--tools/libcore_failures.txt7
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"]
}
]