Make LoadMethod{Handle,Type} instruction throwing.
Bug: 235576668
Test: 979-const-method-handle
Change-Id: Ia0077ea6c050adc33d109195177b3fc61236a876
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 5e2e4ee..89d9fca 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -1137,6 +1137,14 @@
}
}
+ void VisitLoadMethodHandle(HLoadMethodHandle* load_method_handle) override {
+ HandleThrowingInstruction(load_method_handle);
+ }
+
+ void VisitLoadMethodType(HLoadMethodType* load_method_type) override {
+ HandleThrowingInstruction(load_method_type);
+ }
+
void VisitStringBuilderAppend(HStringBuilderAppend* sb_append) override {
HandleThrowingInstruction(sb_append);
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 0767bf5..a923123 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -7243,6 +7243,10 @@
return SideEffects::CanTriggerGC();
}
+ bool CanThrow() const override { return true; }
+
+ bool NeedsEnvironment() const override { return true; }
+
DECLARE_INSTRUCTION(LoadMethodHandle);
protected:
@@ -7287,6 +7291,10 @@
return SideEffects::CanTriggerGC();
}
+ bool CanThrow() const override { return true; }
+
+ bool NeedsEnvironment() const override { return true; }
+
DECLARE_INSTRUCTION(LoadMethodType);
protected:
diff --git a/test/979-const-method-handle/javac_wrapper.sh b/test/979-const-method-handle/javac_wrapper.sh
index 3e2a0a3..5ed8481 100755
--- a/test/979-const-method-handle/javac_wrapper.sh
+++ b/test/979-const-method-handle/javac_wrapper.sh
@@ -34,3 +34,6 @@
transformed_class=classes/$(basename ${class})
${JAVA:-java} ${transformer_args} ${class} ${transformed_class}
done
+
+# Remove class which we want missing at runtime.
+rm classes/MissingType.class
diff --git a/test/979-const-method-handle/src/Main.java b/test/979-const-method-handle/src/Main.java
index 5368a22..04d782b 100644
--- a/test/979-const-method-handle/src/Main.java
+++ b/test/979-const-method-handle/src/Main.java
@@ -72,6 +72,14 @@
return null;
}
+ @ConstantMethodType(
+ returnType = void.class,
+ parameterTypes = {MissingType.class})
+ private static MethodType missingType() {
+ unreachable();
+ return null;
+ }
+
private static void repeatConstMethodType0(MethodType expected) {
System.out.print("repeatConstMethodType0(");
System.out.print(expected);
@@ -189,6 +197,16 @@
return null;
}
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.STATIC_GET,
+ owner = "PrivateMember",
+ fieldOrMethodName = "privateField",
+ descriptor = "I")
+ private static MethodHandle getPrivateField() {
+ unreachable();
+ return null;
+ }
+
private static void repeatConstMethodHandle() throws Throwable {
System.out.println("repeatConstMethodHandle()");
String[] values = {"A", "B", "C"};
@@ -243,5 +261,37 @@
System.out.println("Stack: capacity was " + stack.capacity());
stackTrim().invokeExact(stack);
System.out.println("Stack: capacity is " + stack.capacity());
+
+ // We used to not report in the compiler that loading a ConstMethodHandle/ConstMethodType
+ // can throw, which meant we were not catching the exception in the situation where we
+ // inline the loading.
+ try {
+ $inline$getPrivateField();
+ throw new Error("Expected IllegalAccessError");
+ } catch (IllegalAccessError e) {
+ // expected
+ }
+
+ try {
+ $inline$missingType();
+ throw new Error("Expected NoClassDefFoundError");
+ } catch (NoClassDefFoundError e) {
+ // expected
+ }
}
+
+ public static void $inline$getPrivateField() {
+ getPrivateField();
+ }
+
+ public static void $inline$missingType() {
+ missingType();
+ }
+}
+
+class PrivateMember {
+ private static int privateField;
+}
+
+class MissingType {
}