提交 941f953a 编写于 作者: D dbuck

8174962: Better interface invocations

Reviewed-by: jrose, coleenp, ahgross, acorn, vlivanov
上级 4ca79a53
/* /*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -75,14 +75,21 @@ class DirectMethodHandle extends MethodHandle { ...@@ -75,14 +75,21 @@ class DirectMethodHandle extends MethodHandle {
mtype = mtype.insertParameterTypes(0, receiver); mtype = mtype.insertParameterTypes(0, receiver);
} }
if (!member.isField()) { if (!member.isField()) {
if (refKind == REF_invokeSpecial) { switch (refKind) {
case REF_invokeSpecial: {
member = member.asSpecial(); member = member.asSpecial();
LambdaForm lform = preparedLambdaForm(member); LambdaForm lform = preparedLambdaForm(member);
return new Special(mtype, lform, member); return new Special(mtype, lform, member);
} else { }
case REF_invokeInterface: {
LambdaForm lform = preparedLambdaForm(member);
return new Interface(mtype, lform, member, receiver);
}
default: {
LambdaForm lform = preparedLambdaForm(member); LambdaForm lform = preparedLambdaForm(member);
return new DirectMethodHandle(mtype, lform, member); return new DirectMethodHandle(mtype, lform, member);
} }
}
} else { } else {
LambdaForm lform = preparedFieldLambdaForm(member); LambdaForm lform = preparedFieldLambdaForm(member);
if (member.isStatic()) { if (member.isStatic()) {
...@@ -191,6 +198,7 @@ class DirectMethodHandle extends MethodHandle { ...@@ -191,6 +198,7 @@ class DirectMethodHandle extends MethodHandle {
private static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) { private static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
boolean needsInit = (which == LF_INVSTATIC_INIT); boolean needsInit = (which == LF_INVSTATIC_INIT);
boolean doesAlloc = (which == LF_NEWINVSPECIAL); boolean doesAlloc = (which == LF_NEWINVSPECIAL);
boolean needsReceiverCheck = (which == LF_INVINTERFACE);
String linkerName, lambdaName; String linkerName, lambdaName;
switch (which) { switch (which) {
case LF_INVVIRTUAL: linkerName = "linkToVirtual"; lambdaName = "DMH.invokeVirtual"; break; case LF_INVVIRTUAL: linkerName = "linkToVirtual"; lambdaName = "DMH.invokeVirtual"; break;
...@@ -218,6 +226,7 @@ class DirectMethodHandle extends MethodHandle { ...@@ -218,6 +226,7 @@ class DirectMethodHandle extends MethodHandle {
int nameCursor = ARG_LIMIT; int nameCursor = ARG_LIMIT;
final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1); final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1);
final int GET_MEMBER = nameCursor++; final int GET_MEMBER = nameCursor++;
final int CHECK_RECEIVER = (needsReceiverCheck ? nameCursor++ : -1);
final int LINKER_CALL = nameCursor++; final int LINKER_CALL = nameCursor++;
Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
assert(names.length == nameCursor); assert(names.length == nameCursor);
...@@ -232,6 +241,10 @@ class DirectMethodHandle extends MethodHandle { ...@@ -232,6 +241,10 @@ class DirectMethodHandle extends MethodHandle {
} }
assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]); assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class); Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
if (needsReceiverCheck) {
names[CHECK_RECEIVER] = new Name(Lazy.NF_checkReceiver, names[DMH_THIS], names[ARG_BASE]);
outArgs[0] = names[CHECK_RECEIVER];
}
assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args! assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
int result = LAST_RESULT; int result = LAST_RESULT;
if (doesAlloc) { if (doesAlloc) {
...@@ -375,6 +388,29 @@ class DirectMethodHandle extends MethodHandle { ...@@ -375,6 +388,29 @@ class DirectMethodHandle extends MethodHandle {
} }
} }
/** This subclass represents invokeinterface instructions. */
static class Interface extends DirectMethodHandle {
private final Class<?> refc;
private Interface(MethodType mtype, LambdaForm form, MemberName member, Class<?> refc) {
super(mtype, form, member);
assert refc.isInterface() : refc;
this.refc = refc;
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new Interface(mt, lf, member, refc);
}
Object checkReceiver(Object recv) {
if (!refc.isInstance(recv)) {
String msg = String.format("Class %s does not implement the requested interface %s",
recv.getClass().getName(), refc.getName());
throw new IncompatibleClassChangeError(msg);
}
return recv;
}
}
/** This subclass handles constructor references. */ /** This subclass handles constructor references. */
static class Constructor extends DirectMethodHandle { static class Constructor extends DirectMethodHandle {
final MemberName initMethod; final MemberName initMethod;
...@@ -657,7 +693,8 @@ class DirectMethodHandle extends MethodHandle { ...@@ -657,7 +693,8 @@ class DirectMethodHandle extends MethodHandle {
NF_staticOffset, NF_staticOffset,
NF_checkCast, NF_checkCast,
NF_allocateInstance, NF_allocateInstance,
NF_constructorMethod; NF_constructorMethod,
NF_checkReceiver;
static { static {
try { try {
NamedFunction nfs[] = { NamedFunction nfs[] = {
...@@ -680,7 +717,9 @@ class DirectMethodHandle extends MethodHandle { ...@@ -680,7 +717,9 @@ class DirectMethodHandle extends MethodHandle {
NF_allocateInstance = new NamedFunction(DirectMethodHandle.class NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("allocateInstance", Object.class)), .getDeclaredMethod("allocateInstance", Object.class)),
NF_constructorMethod = new NamedFunction(DirectMethodHandle.class NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("constructorMethod", Object.class)) .getDeclaredMethod("constructorMethod", Object.class)),
NF_checkReceiver = new NamedFunction(new MemberName(Interface.class
.getDeclaredMethod("checkReceiver", Object.class)))
}; };
for (NamedFunction nf : nfs) { for (NamedFunction nf : nfs) {
// Each nf must be statically invocable or we get tied up in our bootstraps. // Each nf must be statically invocable or we get tied up in our bootstraps.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册