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 {
 }