Path: blob/master/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/share/GenFullCP.java
41162 views
/*1* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package vm.mlvm.cp.share;2425import jdk.internal.org.objectweb.asm.ByteVector;26import jdk.internal.org.objectweb.asm.ClassWriter;27import jdk.internal.org.objectweb.asm.ClassWriterExt;28import jdk.internal.org.objectweb.asm.MethodVisitor;29import jdk.internal.org.objectweb.asm.Opcodes;30import jdk.internal.org.objectweb.asm.Type;3132import vm.mlvm.share.ClassfileGenerator;33import vm.mlvm.share.Env;3435public abstract class GenFullCP extends ClassfileGenerator {3637/**38* Generate field description for object type from class name:39* return "L" + className + ";";40* @param className Class name41* @return field descriptor representing the class type42*/43protected static String fd(String className) {44return "L" + className + ";";45}4647// Universal constants48protected static final String JL_OBJECT = "java/lang/Object";49protected static final String JL_CLASS = "java/lang/Class";50protected static final String JL_CLASSLOADER = "java/lang/ClassLoader";51protected static final String JL_STRING = "java/lang/String";52protected static final String JL_RUNTIMEEXCEPTION = "java/lang/RuntimeException";53protected static final String JL_BOOTSTRAPMETHODERROR = "java/lang/BootstrapMethodError";54protected static final String JL_THROWABLE = "java/lang/Throwable";55protected static final String JLI_METHODTYPE = "java/lang/invoke/MethodType";56protected static final String JLI_METHODHANDLE = "java/lang/invoke/MethodHandle";57protected static final String JLI_METHODHANDLES = "java/lang/invoke/MethodHandles";58protected static final String JLI_METHODHANDLES_LOOKUP = "java/lang/invoke/MethodHandles$Lookup";59protected static final String JLI_CALLSITE = "java/lang/invoke/CallSite";60protected static final String JLI_CONSTANTCALLSITE = "java/lang/invoke/ConstantCallSite";6162protected static final String VOID_NO_ARG_METHOD_SIGNATURE = "()V";6364protected static final String NEW_INVOKE_SPECIAL_CLASS_NAME = "java/lang/invoke/NewInvokeSpecialCallSite";65protected static final String NEW_INVOKE_SPECIAL_BOOTSTRAP_METHOD_SIGNATURE = "(" + fd(JLI_METHODHANDLES_LOOKUP) + fd(JL_STRING) + fd(JLI_METHODTYPE) + ")V";6667protected static final String INIT_METHOD_NAME = "<init>";68protected static final String STATIC_INIT_METHOD_NAME = "<clinit>";6970// Generated class constants71protected static final int CLASSFILE_VERSION = 51;7273protected static final int CP_CONST_COUNT = 65400;74protected static final int MAX_METHOD_SIZE = 65400;75protected static final int BYTES_PER_LDC = 5;76protected static final int LDC_PER_METHOD = MAX_METHOD_SIZE / BYTES_PER_LDC;77protected static final int METHOD_COUNT = CP_CONST_COUNT / LDC_PER_METHOD;7879protected static final String PARENT_CLASS_NAME = JL_OBJECT;8081protected static final String INIT_METHOD_SIGNATURE = VOID_NO_ARG_METHOD_SIGNATURE;8283protected static final String MAIN_METHOD_NAME = "main";84protected static final String MAIN_METHOD_SIGNATURE = "(" + "[" + fd(JL_STRING) + ")V";8586protected static final String TEST_METHOD_NAME = "test";87protected static final String TEST_METHOD_SIGNATURE = VOID_NO_ARG_METHOD_SIGNATURE;8889protected static final String STATIC_FIELD_NAME = "testStatic";90protected static final String STATIC_FIELD_SIGNATURE = "Z";9192protected static final String INSTANCE_FIELD_NAME = "testInstance";93protected static final String INSTANCE_FIELD_SIGNATURE = "Z";9495protected static final String STATIC_BOOTSTRAP_FIELD_NAME = "testCSStatic";96protected static final String STATIC_BOOTSTRAP_FIELD_SIGNATURE = fd(JLI_CALLSITE);9798protected static final String INSTANCE_BOOTSTRAP_FIELD_NAME = "testCSInstance";99protected static final String INSTANCE_BOOTSTRAP_FIELD_SIGNATURE = fd(JLI_CALLSITE);100101protected static final String BOOTSTRAP_METHOD_NAME = "bootstrap";102protected static final String BOOTSTRAP_METHOD_SIGNATURE = "(" + fd(JLI_METHODHANDLES_LOOKUP) + fd(JL_STRING) + fd(JLI_METHODTYPE) + ")" + fd(JLI_CALLSITE);103104protected static final String INSTANCE_BOOTSTRAP_METHOD_NAME = "bootstrapInstance";105protected static final String INSTANCE_BOOTSTRAP_METHOD_SIGNATURE = BOOTSTRAP_METHOD_SIGNATURE;106107protected static final String TARGET_METHOD_NAME = "target";108protected static final String TARGET_METHOD_SIGNATURE = VOID_NO_ARG_METHOD_SIGNATURE;109110protected static final String INSTANCE_TARGET_METHOD_NAME = "targetInstance";111protected static final String INSTANCE_TARGET_METHOD_SIGNATURE = VOID_NO_ARG_METHOD_SIGNATURE;112113protected interface DummyInterface {114public void targetInstance();115}116117// Helper methods118119protected static String getDummyInterfaceClassName() {120return DummyInterface.class.getName().replace('.', '/');121}122123protected static void createLogMsgCode(MethodVisitor mv, String msg) {124mv.visitLdcInsn(msg);125mv.visitMethodInsn(Opcodes.INVOKESTATIC, "vm/mlvm/share/Env", "traceVerbose", "(Ljava/lang/String;)V");126}127128protected static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {129createThrowRuntimeExceptionCodeHelper(mv, msg, false);130}131132// Expects a throwable (the cause) to be on top of the stack when called.133protected static void createThrowRuntimeExceptionCodeWithCause(MethodVisitor mv, String msg) {134createThrowRuntimeExceptionCodeHelper(mv, msg, true);135}136137// If set_cause is true it expects a Throwable (the cause) to be on top of the stack when called.138protected static void createThrowRuntimeExceptionCodeHelper(MethodVisitor mv, String msg, boolean set_cause) {139mv.visitTypeInsn(Opcodes.NEW, JL_RUNTIMEEXCEPTION);140mv.visitInsn(Opcodes.DUP);141mv.visitLdcInsn(msg);142mv.visitMethodInsn(Opcodes.INVOKESPECIAL, JL_RUNTIMEEXCEPTION,143INIT_METHOD_NAME, "(" + fd(JL_STRING) + ")V");144if (set_cause) {145mv.visitInsn(Opcodes.SWAP);146mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, JL_RUNTIMEEXCEPTION,147"initCause", "(" + fd(JL_THROWABLE) + ")"+ fd(JL_THROWABLE));148}149mv.visitInsn(Opcodes.ATHROW);150}151152protected static void createThrowRuntimeExceptionMethod(ClassWriter cw, boolean isStatic, String methodName, String methodSignature) {153MethodVisitor mv = cw.visitMethod(154Opcodes.ACC_PUBLIC | (isStatic ? Opcodes.ACC_STATIC : 0),155methodName, methodSignature,156null,157new String[0]);158159createThrowRuntimeExceptionCode(mv, "Method " + methodName + methodSignature + " should not be called!");160161mv.visitMaxs(-1, -1);162mv.visitEnd();163}164165protected static void finishMethodCode(MethodVisitor mv) {166finishMethodCode(mv, Opcodes.RETURN);167}168169protected static void finishMethodCode(MethodVisitor mv, int returnOpcode) {170mv.visitInsn(returnOpcode);171mv.visitMaxs(-1, -1);172mv.visitEnd();173}174175protected void createClassInitMethod(ClassWriter cw) {176}177178protected void createInitMethod(ClassWriter cw) {179MethodVisitor mv = cw.visitMethod(180Opcodes.ACC_PUBLIC,181INIT_METHOD_NAME, INIT_METHOD_SIGNATURE,182null,183new String[0]);184185mv.visitIntInsn(Opcodes.ALOAD, 0);186mv.visitMethodInsn(Opcodes.INVOKESPECIAL,187PARENT_CLASS_NAME,188INIT_METHOD_NAME, INIT_METHOD_SIGNATURE);189190createLogMsgCode(mv, fullClassName + " constructor called");191192finishMethodCode(mv);193}194195protected void createTargetMethod(ClassWriter cw) {196MethodVisitor mv = cw.visitMethod(197Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,198TARGET_METHOD_NAME, TARGET_METHOD_SIGNATURE,199null,200new String[0]);201202createLogMsgCode(mv, fullClassName + "." + TARGET_METHOD_NAME + TARGET_METHOD_SIGNATURE + " called");203204finishMethodCode(mv);205}206207protected void createBootstrapMethod(ClassWriter cw) {208createBootstrapMethod(cw, true, BOOTSTRAP_METHOD_NAME, BOOTSTRAP_METHOD_SIGNATURE);209}210211protected void createBootstrapMethod(ClassWriter cw, boolean isStatic, String methodName, String methodSignature) {212MethodVisitor mv = cw.visitMethod(213(isStatic ? Opcodes.ACC_STATIC : 0) | Opcodes.ACC_PUBLIC,214methodName, methodSignature,215null, new String[0]);216217createLogMsgCode(mv, fullClassName + "." + BOOTSTRAP_METHOD_NAME + BOOTSTRAP_METHOD_SIGNATURE + " called");218219int argShift = isStatic ? 0 : 1;220221mv.visitTypeInsn(Opcodes.NEW, JLI_CONSTANTCALLSITE);222mv.visitInsn(Opcodes.DUP);223mv.visitVarInsn(Opcodes.ALOAD, 0 + argShift);224mv.visitLdcInsn(Type.getObjectType(fullClassName));225mv.visitVarInsn(Opcodes.ALOAD, 1 + argShift);226mv.visitVarInsn(Opcodes.ALOAD, 2 + argShift);227mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,228JLI_METHODHANDLES_LOOKUP, "findStatic",229"(" + fd(JL_CLASS) + fd(JL_STRING) + fd(JLI_METHODTYPE) + ")" + fd(JLI_METHODHANDLE));230mv.visitMethodInsn(Opcodes.INVOKESPECIAL, JLI_CONSTANTCALLSITE,231INIT_METHOD_NAME, "(" + fd(JLI_METHODHANDLE) + ")V");232233finishMethodCode(mv, Opcodes.ARETURN);234}235236@Override237public Klass[] generateBytecodes() {238239// COMPUTE_FRAMES were disabled due to JDK-8079697240ClassWriterExt cw = new ClassWriterExt(/*ClassWriter.COMPUTE_FRAMES |*/ ClassWriter.COMPUTE_MAXS);241242String[] interfaces = new String[1];243interfaces[0] = getDummyInterfaceClassName();244cw.visit(CLASSFILE_VERSION, Opcodes.ACC_PUBLIC, fullClassName, null, PARENT_CLASS_NAME, interfaces);245246generateCommonData(cw);247248MethodVisitor mainMV = cw.visitMethod(249Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,250MAIN_METHOD_NAME, MAIN_METHOD_SIGNATURE,251null, new String[0]);252253mainMV.visitTypeInsn(Opcodes.NEW, fullClassName);254mainMV.visitInsn(Opcodes.DUP);255mainMV.visitMethodInsn(Opcodes.INVOKESPECIAL, fullClassName, INIT_METHOD_NAME, INIT_METHOD_SIGNATURE);256257int constCount = 0;258int methodNum = 0;259260// TODO: check real CP size and also limit number of iterations in this cycle261while (constCount < CP_CONST_COUNT) {262final String methodName = TEST_METHOD_NAME + String.format("%02d", methodNum);263264MethodVisitor mw = cw.visitMethod(265Opcodes.ACC_PUBLIC,266methodName, TEST_METHOD_SIGNATURE,267null, new String[0]);268269generateTestMethodProlog(mw);270271// TODO: check real CP size and also limit number of iterations in this cycle272while (constCount < CP_CONST_COUNT && cw.getBytecodeLength(mw) < MAX_METHOD_SIZE) {273generateCPEntryData(cw, mw);274++constCount;275}276277generateTestMethodEpilog(mw);278279mw.visitMaxs(-1, -1);280mw.visitEnd();281282Env.traceNormal("Method " + fullClassName + "." + methodName + "(): "283+ constCount + " constants in CP, "284+ cw.getBytecodeLength(mw) + " bytes of code");285286mainMV.visitInsn(Opcodes.DUP);287mainMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, fullClassName, methodName, TEST_METHOD_SIGNATURE);288289++methodNum;290}291292mainMV.visitInsn(Opcodes.POP);293finishMethodCode(mainMV);294295cw.visitEnd();296return new Klass[] { new Klass(this.pkgName, this.shortClassName, MAIN_METHOD_NAME, MAIN_METHOD_SIGNATURE, cw.toByteArray()) };297}298299protected void generateCommonData(ClassWriterExt cw) {300createClassInitMethod(cw);301createInitMethod(cw);302createTargetMethod(cw);303createBootstrapMethod(cw);304}305306protected void generateTestMethodProlog(MethodVisitor mw) {307}308309protected abstract void generateCPEntryData(ClassWriter cw, MethodVisitor mw);310311protected void generateTestMethodEpilog(MethodVisitor mw) {312mw.visitInsn(Opcodes.RETURN);313}314315}316317318