src/hotspot/cpu/zero/methodHandles_zero.cpp
changeset 50736 f703d45c5687
parent 49480 d7df2dd501ce
--- a/src/hotspot/cpu/zero/methodHandles_zero.cpp	Sat Jun 23 01:32:41 2018 -0400
+++ b/src/hotspot/cpu/zero/methodHandles_zero.cpp	Tue Jun 05 11:55:39 2018 +0200
@@ -26,6 +26,7 @@
 #include "precompiled.hpp"
 #include "interpreter/cppInterpreterGenerator.hpp"
 #include "interpreter/interpreter.hpp"
+#include "interpreter/interpreterRuntime.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.inline.hpp"
@@ -65,6 +66,37 @@
 
 }
 
+void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) {
+
+  JavaThread *thread = (JavaThread *) THREAD;
+  // Set up the frame anchor if it isn't already
+  bool has_last_Java_frame = thread->has_last_Java_frame();
+  if (!has_last_Java_frame) {
+    intptr_t *sp = thread->zero_stack()->sp();
+    ZeroFrame *frame = thread->top_zero_frame();
+    while (frame) {
+      if (frame->is_interpreter_frame()) {
+        interpreterState istate =
+          frame->as_interpreter_frame()->interpreter_state();
+        if (istate->self_link() == istate)
+          break;
+      }
+
+      sp = ((intptr_t *) frame) + 1;
+      frame = frame->next();
+    }
+
+    assert(frame != NULL, "must be");
+    thread->set_last_Java_frame(frame, sp);
+  }
+  InterpreterRuntime::throw_AbstractMethodErrorVerbose(thread, rcvr, interface_method);
+  // Reset the frame anchor if necessary
+  if (!has_last_Java_frame) {
+    thread->reset_last_Java_frame();
+  }
+
+}
+
 int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) {
 
   JavaThread *thread = (JavaThread *) THREAD;
@@ -124,8 +156,15 @@
 
   itableMethodEntry* im = ki->first_method_entry(recv->klass());
   Method* vmtarget = im[vmindex].method();
-
-  invoke_target(vmtarget, THREAD);
+  // Check that the vmtarget entry is non-null.  A null entry means
+  // that the method no longer exists (got deleted) or is private.
+  // Private class methods can never be an implementation of an
+  // interface method. In those cases, throw AME.
+  if (vmtarget != NULL) {
+    invoke_target(vmtarget, THREAD);
+  } else {
+    throw_AME(recv->klass(), target, THREAD);
+  }
 
   return 0;
 }