mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8078112: [TESTBUG] Integrate Selection/Resolution test suite into jtreg tests
Reviewed-by: ctornqvi, acorn
This commit is contained in:
parent
a02f8f2d30
commit
6bf9194f41
27 changed files with 10890 additions and 0 deletions
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package selectionresolution;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.DUP;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.POP;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.NEW;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.SWAP;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESPECIAL;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEINTERFACE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL;
|
||||
|
||||
class Method {
|
||||
public static final String defaultMethodName = "m";
|
||||
public static final String defaultMethodDescriptor = "()Ljava/lang/Integer;";
|
||||
public static final String methodDescriptorTemplate = "(L%s;)Ljava/lang/Integer;";
|
||||
private final ClassConstruct ownerClass;
|
||||
private final String ownerClassName;
|
||||
private final ClassVisitor cv;
|
||||
private final MethodVisitor mv;
|
||||
private final boolean isInterface;
|
||||
private final ClassBuilder.ExecutionMode execMode;
|
||||
|
||||
public Method(ClassConstruct ownerClass, ClassVisitor cv, String name, String descriptor, int access,
|
||||
ClassBuilder.ExecutionMode execMode) {
|
||||
this.ownerClassName = ownerClass.getName();
|
||||
this.ownerClass = ownerClass;
|
||||
this.isInterface = ownerClass.isInterface();
|
||||
this.execMode = execMode;
|
||||
this.cv = cv;
|
||||
mv = cv.visitMethod(access, name, descriptor, null, null);
|
||||
mv.visitCode();
|
||||
}
|
||||
/**
|
||||
* Add code for the m()Ljava/lang/Integer; method, always returns null
|
||||
*/
|
||||
public void makeDefaultMethod() {
|
||||
mv.visitTypeInsn(NEW, "java/lang/Integer");
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitLdcInsn(ownerClass.getIndex());
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>", "(I)V");
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
public void makePrivateCallMethod(String className) {
|
||||
makeSuperCallMethod(INVOKESPECIAL, className);
|
||||
}
|
||||
|
||||
public void makeSuperCallMethod(int invokeInstruction, String className) {
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
makeCall(invokeInstruction, className);
|
||||
mv.visitInsn(POP);
|
||||
done();
|
||||
}
|
||||
|
||||
public void defaultInvoke(int instr, String className, String objectRef) {
|
||||
switch (instr) {
|
||||
case INVOKEVIRTUAL:
|
||||
defaultInvokeVirtual(className, objectRef);
|
||||
break;
|
||||
case INVOKEINTERFACE:
|
||||
defaultInvokeInterface(className, objectRef);
|
||||
break;
|
||||
case INVOKESTATIC:
|
||||
defaultInvokeStatic(className);
|
||||
break;
|
||||
case INVOKESPECIAL:
|
||||
defaultInvokeSpecial(className, objectRef);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
public void defaultInvokeVirtual(String className, String objectRef) {
|
||||
String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
|
||||
makeNewObject(objectRef, objectRefPackageName);
|
||||
makeCall(INVOKEVIRTUAL, className, false);
|
||||
}
|
||||
|
||||
public void defaultInvokeInterface(String className, String objectRef) {
|
||||
String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
|
||||
makeNewObject(objectRef, objectRefPackageName);
|
||||
makeCall(INVOKEINTERFACE, className, true);
|
||||
}
|
||||
|
||||
public void defaultInvokeSpecial(String className, String objectRef) {
|
||||
String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
|
||||
makeNewObject(objectRef, objectRefPackageName);
|
||||
makeCall(INVOKESPECIAL, className, false);
|
||||
}
|
||||
|
||||
public void defaultInvokeStatic(String className) {
|
||||
makeCall(INVOKESTATIC, className);
|
||||
}
|
||||
|
||||
private Method makeCall(int invokeInstruction, String className) {
|
||||
return makeCall(invokeInstruction, className, isInterface);
|
||||
}
|
||||
|
||||
private Method makeCall(int invokeInstruction, String className, boolean isInterface) {
|
||||
switch(execMode) {
|
||||
case DIRECT: {
|
||||
mv.visitMethodInsn(invokeInstruction, className, defaultMethodName, defaultMethodDescriptor, isInterface);
|
||||
break;
|
||||
}
|
||||
case INDY: {
|
||||
Handle m = convertToHandle(invokeInstruction, className, defaultMethodName, defaultMethodDescriptor);
|
||||
Handle bsm = generateBootstrapMethod(m);
|
||||
mv.visitInvokeDynamicInsn(defaultMethodName, defaultMethodDescriptor, bsm);
|
||||
break;
|
||||
}
|
||||
case MH_INVOKE_EXACT:
|
||||
case MH_INVOKE_GENERIC: {
|
||||
String invokerName = execMode == ClassBuilder.ExecutionMode.MH_INVOKE_GENERIC
|
||||
? "invoke" : "invokeExact";
|
||||
|
||||
Handle m = convertToHandle(invokeInstruction, className, defaultMethodName, defaultMethodDescriptor);
|
||||
mv.visitLdcInsn(m);
|
||||
mv.visitInsn(SWAP);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL,
|
||||
"java/lang/invoke/MethodHandle",
|
||||
invokerName,
|
||||
String.format(methodDescriptorTemplate, className),
|
||||
false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("Unknown execution mode: " + execMode);
|
||||
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private Handle generateBootstrapMethod(Handle h) {
|
||||
String bootstrapName = "bootstrapMethod";
|
||||
MethodType bootstrapType = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
|
||||
|
||||
MethodVisitor bmv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, bootstrapName, bootstrapType.toMethodDescriptorString(), null, null);
|
||||
bmv.visitCode();
|
||||
|
||||
String constCallSite = "java/lang/invoke/ConstantCallSite";
|
||||
bmv.visitTypeInsn(NEW, constCallSite);
|
||||
bmv.visitInsn(DUP);
|
||||
|
||||
bmv.visitLdcInsn(h);
|
||||
|
||||
bmv.visitMethodInsn(INVOKESPECIAL, constCallSite, "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false);
|
||||
bmv.visitInsn(ARETURN);
|
||||
|
||||
bmv.visitMaxs(0,0);
|
||||
bmv.visitEnd();
|
||||
|
||||
return new Handle(H_INVOKESTATIC, ownerClassName, bootstrapName, bootstrapType.toMethodDescriptorString());
|
||||
}
|
||||
|
||||
|
||||
private static Handle convertToHandle(int invokeInstruction, String className, String methodName, String methodDesc) {
|
||||
int tag;
|
||||
switch (invokeInstruction) {
|
||||
case INVOKEVIRTUAL: tag = H_INVOKEVIRTUAL; break;
|
||||
case INVOKEINTERFACE: tag = H_INVOKEINTERFACE; break;
|
||||
case INVOKESPECIAL: tag = H_INVOKESPECIAL; break;
|
||||
case INVOKESTATIC: tag = H_INVOKESTATIC; break;
|
||||
default:
|
||||
throw new Error("Unknown invoke instruction: "+invokeInstruction);
|
||||
}
|
||||
|
||||
return new Handle(tag, className, methodName, methodDesc);
|
||||
}
|
||||
|
||||
private void makeNewObject(String objectRef, String objectRefPackageName) {
|
||||
String className = objectRef.substring(objectRef.lastIndexOf("/") + 1);
|
||||
makeStaticCall( objectRefPackageName + "/Helper",
|
||||
"get" + className,
|
||||
"()L" + objectRef + ";");
|
||||
mv.visitVarInsn(ASTORE, 1);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
}
|
||||
|
||||
public void makeTestCall(String className) {
|
||||
mv.visitTypeInsn(NEW, className);
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V", false);
|
||||
mv.visitVarInsn(ASTORE, 1);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, className, "test", "()Ljava/lang/Integer;", false);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
public Method makeStaticCall(String classname, String method, String descriptor) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, classname, method, descriptor, isInterface);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void makeConstructor(String extending) {
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, extending == null ? "java/lang/Object" : extending, "<init>", "()V", isInterface);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
public void makeInstantiateMethod(String className) {
|
||||
mv.visitTypeInsn(NEW, className);
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V", false);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue