8203188: Add JEP-181 support to the Zero interpreter
Reviewed-by: dholmes, chrisphi
This commit is contained in:
parent
95bf19563b
commit
1a1303e1a6
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user