8203188: Add JEP-181 support to the Zero interpreter

Reviewed-by: dholmes, chrisphi
This commit is contained in:
Severin Gehwolf 2018-06-05 11:55:39 +02:00
parent 95bf19563b
commit 1a1303e1a6
3 changed files with 67 additions and 7 deletions

View File

@ -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 @@ oop MethodHandles::popFromStack(TRAPS) {
}
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 @@ int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t
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;
}

View File

@ -32,6 +32,7 @@ enum /* platform_dependent_constants */ {
private:
static oop popFromStack(TRAPS);
static void invoke_target(Method* method, TRAPS);
static void throw_AME(Klass* rcvr, Method* interface_method, TRAPS);
static int method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS);
static int method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS);
static int method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS);

View File

@ -2524,11 +2524,9 @@ run:
istate->set_msg(call_method);
// Special case of invokeinterface called for virtual method of
// java.lang.Object. See cpCacheOop.cpp for details.
// This code isn't produced by javac, but could be produced by
// another compliant java compiler.
// java.lang.Object. See cpCache.cpp for details.
Method* callee = NULL;
if (cache->is_forced_virtual()) {
Method* callee;
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
if (cache->is_vfinal()) {
callee = cache->f2_as_vfinal_method();
@ -2545,6 +2543,29 @@ run:
// Profile 'special case of invokeinterface' virtual call.
BI_PROFILE_UPDATE_VIRTUALCALL(rcvrKlass);
}
} else if (cache->is_vfinal()) {
// private interface method invocations
//
// Ensure receiver class actually implements
// the resolved interface class. The link resolver
// does this, but only for the first time this
// interface is being called.
int parms = cache->parameter_size();
oop rcvr = STACK_OBJECT(-parms);
CHECK_NULL(rcvr);
Klass* recv_klass = rcvr->klass();
Klass* resolved_klass = cache->f1_as_klass();
if (!recv_klass->is_subtype_of(resolved_klass)) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s",
recv_klass->external_name(),
resolved_klass->external_name());
VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), buf, note_no_trap);
}
callee = cache->f2_as_vfinal_method();
}
if (callee != NULL) {
istate->set_callee(callee);
istate->set_callee_entry_point(callee->from_interpreted_entry());
#ifdef VM_JVMTI
@ -2557,7 +2578,6 @@ run:
}
// this could definitely be cleaned up QQQ
Method* callee;
Method *interface_method = cache->f2_as_interface_method();
InstanceKlass* iclass = interface_method->method_holder();