src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Cdiff src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

Print this page
rev 9490 : 8037210: Get rid of char-based descriptions 'J' of basic types
Reviewed-by: jrose, ?
rev 9491 : [mq]: meth-btype.1

*** 24,34 **** */ package java.lang.invoke; import sun.invoke.util.VerifyAccess; ! import java.lang.invoke.LambdaForm.Name; import sun.invoke.util.Wrapper; import java.io.*; import java.util.*; --- 24,34 ---- */ package java.lang.invoke; import sun.invoke.util.VerifyAccess; ! import static java.lang.invoke.LambdaForm.*; import sun.invoke.util.Wrapper; import java.io.*; import java.util.*;
*** 36,45 **** --- 36,46 ---- import jdk.internal.org.objectweb.asm.*; import java.lang.reflect.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; + import static java.lang.invoke.LambdaForm.BasicType.*; import sun.invoke.util.VerifyType; /** * Code generation backend for LambdaForm. * <p>
*** 113,123 **** className, form.debugName, invokerType); // Create an array to map name indexes to locals indexes. Name[] names = form.names; for (int i = 0, index = 0; i < localsMap.length; i++) { localsMap[i] = index; ! index += Wrapper.forBasicType(names[i].type).stackSlots(); } } /** instance counters for dumped classes */ --- 114,124 ---- className, form.debugName, invokerType); // Create an array to map name indexes to locals indexes. Name[] names = form.names; for (int i = 0, index = 0; i < localsMap.length; i++) { localsMap[i] = index; ! index += names[i].type.basicTypeSlots(); } } /** instance counters for dumped classes */
*** 355,418 **** } /* * NOTE: These load/store methods use the localsMap to find the correct index! */ ! private void emitLoadInsn(char type, int index) { ! int opcode; switch (type) { ! case 'I': opcode = Opcodes.ILOAD; break; ! case 'J': opcode = Opcodes.LLOAD; break; ! case 'F': opcode = Opcodes.FLOAD; break; ! case 'D': opcode = Opcodes.DLOAD; break; ! case 'L': opcode = Opcodes.ALOAD; break; default: throw new InternalError("unknown type: " + type); } - mv.visitVarInsn(opcode, localsMap[index]); } private void emitAloadInsn(int index) { ! emitLoadInsn('L', index); } ! private void emitStoreInsn(char type, int index) { ! int opcode; switch (type) { ! case 'I': opcode = Opcodes.ISTORE; break; ! case 'J': opcode = Opcodes.LSTORE; break; ! case 'F': opcode = Opcodes.FSTORE; break; ! case 'D': opcode = Opcodes.DSTORE; break; ! case 'L': opcode = Opcodes.ASTORE; break; default: throw new InternalError("unknown type: " + type); } - mv.visitVarInsn(opcode, localsMap[index]); } private void emitAstoreInsn(int index) { ! emitStoreInsn('L', index); } /** * Emit a boxing call. * ! * @param type primitive type class to box. */ ! private void emitBoxing(Class<?> type) { ! Wrapper wrapper = Wrapper.forPrimitiveType(type); String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = "valueOf"; String desc = "(" + wrapper.basicTypeChar() + ")L" + owner + ";"; mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); } /** * Emit an unboxing call (plus preceding checkcast). * ! * @param type wrapper type class to unbox. */ ! private void emitUnboxing(Class<?> type) { ! Wrapper wrapper = Wrapper.forWrapperType(type); String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = wrapper.primitiveSimpleName() + "Value"; String desc = "()" + wrapper.basicTypeChar(); mv.visitTypeInsn(Opcodes.CHECKCAST, owner); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false); --- 356,423 ---- } /* * NOTE: These load/store methods use the localsMap to find the correct index! */ ! private void emitLoadInsn(BasicType type, int index) { ! int opcode = loadInsnOpcode(type); ! mv.visitVarInsn(opcode, localsMap[index]); ! } ! ! private int loadInsnOpcode(BasicType type) throws InternalError { switch (type) { ! case I_TYPE: return Opcodes.ILOAD; ! case J_TYPE: return Opcodes.LLOAD; ! case F_TYPE: return Opcodes.FLOAD; ! case D_TYPE: return Opcodes.DLOAD; ! case L_TYPE: return Opcodes.ALOAD; default: throw new InternalError("unknown type: " + type); } } private void emitAloadInsn(int index) { ! emitLoadInsn(L_TYPE, index); } ! private void emitStoreInsn(BasicType type, int index) { ! int opcode = storeInsnOpcode(type); ! mv.visitVarInsn(opcode, localsMap[index]); ! } ! ! private int storeInsnOpcode(BasicType type) throws InternalError { switch (type) { ! case I_TYPE: return Opcodes.ISTORE; ! case J_TYPE: return Opcodes.LSTORE; ! case F_TYPE: return Opcodes.FSTORE; ! case D_TYPE: return Opcodes.DSTORE; ! case L_TYPE: return Opcodes.ASTORE; default: throw new InternalError("unknown type: " + type); } } private void emitAstoreInsn(int index) { ! emitStoreInsn(L_TYPE, index); } /** * Emit a boxing call. * ! * @param wrapper primitive type class to box. */ ! private void emitBoxing(Wrapper wrapper) { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = "valueOf"; String desc = "(" + wrapper.basicTypeChar() + ")L" + owner + ";"; mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); } /** * Emit an unboxing call (plus preceding checkcast). * ! * @param wrapper wrapper type class to unbox. */ ! private void emitUnboxing(Wrapper wrapper) { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = wrapper.primitiveSimpleName() + "Value"; String desc = "()" + wrapper.basicTypeChar(); mv.visitTypeInsn(Opcodes.CHECKCAST, owner); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false);
*** 422,434 **** * Emit an implicit conversion. * * @param ptype type of value present on stack * @param pclass type of value required on stack */ ! private void emitImplicitConversion(char ptype, Class<?> pclass) { switch (ptype) { ! case 'L': if (VerifyType.isNullConversion(Object.class, pclass)) return; if (isStaticallyNameable(pclass)) { mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass)); } else { --- 427,442 ---- * Emit an implicit conversion. * * @param ptype type of value present on stack * @param pclass type of value required on stack */ ! private void emitImplicitConversion(BasicType ptype, Class<?> pclass) { ! assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller ! if (pclass == ptype.basicTypeClass() && ptype != L_TYPE) ! return; // nothing to do switch (ptype) { ! case L_TYPE: if (VerifyType.isNullConversion(Object.class, pclass)) return; if (isStaticallyNameable(pclass)) { mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass)); } else {
*** 438,476 **** mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); if (pclass.isArray()) mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); } return; ! case 'I': if (!VerifyType.isNullConversion(int.class, pclass)) ! emitPrimCast(ptype, Wrapper.basicTypeChar(pclass)); ! return; ! case 'J': ! assert(pclass == long.class); ! return; ! case 'F': ! assert(pclass == float.class); ! return; ! case 'D': ! assert(pclass == double.class); return; } throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass); } /** * Emits an actual return instruction conforming to the given return type. */ ! private void emitReturnInsn(Class<?> type) { int opcode; ! switch (Wrapper.basicTypeChar(type)) { ! case 'I': opcode = Opcodes.IRETURN; break; ! case 'J': opcode = Opcodes.LRETURN; break; ! case 'F': opcode = Opcodes.FRETURN; break; ! case 'D': opcode = Opcodes.DRETURN; break; ! case 'L': opcode = Opcodes.ARETURN; break; ! case 'V': opcode = Opcodes.RETURN; break; default: throw new InternalError("unknown return type: " + type); } mv.visitInsn(opcode); } --- 446,475 ---- mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); if (pclass.isArray()) mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); } return; ! case I_TYPE: if (!VerifyType.isNullConversion(int.class, pclass)) ! emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); return; } throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass); } /** * Emits an actual return instruction conforming to the given return type. */ ! private void emitReturnInsn(BasicType type) { int opcode; ! switch (type) { ! case I_TYPE: opcode = Opcodes.IRETURN; break; ! case J_TYPE: opcode = Opcodes.LRETURN; break; ! case F_TYPE: opcode = Opcodes.FRETURN; break; ! case D_TYPE: opcode = Opcodes.DRETURN; break; ! case L_TYPE: opcode = Opcodes.ARETURN; break; ! case V_TYPE: opcode = Opcodes.RETURN; break; default: throw new InternalError("unknown return type: " + type); } mv.visitInsn(opcode); }
*** 528,538 **** // store the result from evaluating to the target name in a local if required // (if this is the last value, i.e., the one that is going to be returned, // avoid store/load/return and just return) if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) { // return value - do nothing ! } else if (name.type != 'V') { // non-void: actually assign emitStoreInsn(name.type, name.index()); } } --- 527,537 ---- // store the result from evaluating to the target name in a local if required // (if this is the last value, i.e., the one that is going to be returned, // avoid store/load/return and just return) if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) { // return value - do nothing ! } else if (name.type != V_TYPE) { // non-void: actually assign emitStoreInsn(name.type, name.index()); } }
*** 862,940 **** } } private void emitPushArgument(Name name, int paramIndex) { Object arg = name.arguments[paramIndex]; ! char ptype = name.function.parameterType(paramIndex); ! MethodType mtype = name.function.methodType(); if (arg instanceof Name) { Name n = (Name) arg; emitLoadInsn(n.type, n.index()); ! emitImplicitConversion(n.type, mtype.parameterType(paramIndex)); ! } else if ((arg == null || arg instanceof String) && ptype == 'L') { emitConst(arg); } else { ! if (Wrapper.isWrapperType(arg.getClass()) && ptype != 'L') { emitConst(arg); } else { mv.visitLdcInsn(constantPlaceholder(arg)); ! emitImplicitConversion('L', mtype.parameterType(paramIndex)); } } } /** * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type. */ private void emitReturn() { // return statement ! if (lambdaForm.result == -1) { // void mv.visitInsn(Opcodes.RETURN); } else { LambdaForm.Name rn = lambdaForm.names[lambdaForm.result]; - char rtype = Wrapper.basicTypeChar(invokerType.returnType()); // put return value on the stack if it is not already there ! if (lambdaForm.result != lambdaForm.names.length - 1) { emitLoadInsn(rn.type, lambdaForm.result); } ! // potentially generate cast ! // rtype is the return type of the invoker - generated code must conform to this ! // rn.type is the type of the result Name in the LF ! if (rtype != rn.type) { ! // need cast ! if (rtype == 'L') { ! // possibly cast the primitive to the correct type for boxing ! char boxedType = Wrapper.forWrapperType(invokerType.returnType()).basicTypeChar(); ! if (boxedType != rn.type) { ! emitPrimCast(rn.type, boxedType); ! } ! // cast primitive to reference ("boxing") ! emitBoxing(invokerType.returnType()); ! } else { ! // to-primitive cast ! if (rn.type != 'L') { ! // prim-to-prim cast ! emitPrimCast(rn.type, rtype); ! } else { ! // ref-to-prim cast ("unboxing") ! throw new InternalError("no ref-to-prim (unboxing) casts supported right now"); ! } ! } ! } // generate actual return statement ! emitReturnInsn(invokerType.returnType()); } } /** * Emit a type conversion bytecode casting from "from" to "to". */ ! private void emitPrimCast(char from, char to) { // Here's how. // - indicates forbidden // <-> indicates implicit // to ----> boolean byte short char int long float double // from boolean <-> - - - - - - - --- 861,924 ---- } } private void emitPushArgument(Name name, int paramIndex) { Object arg = name.arguments[paramIndex]; ! Class<?> ptype = name.function.methodType().parameterType(paramIndex); ! emitPushArgument(ptype, arg); ! } ! ! private void emitPushArgument(Class<?> ptype, Object arg) { ! BasicType bptype = basicType(ptype); if (arg instanceof Name) { Name n = (Name) arg; emitLoadInsn(n.type, n.index()); ! emitImplicitConversion(n.type, ptype); ! } else if ((arg == null || arg instanceof String) && bptype == L_TYPE) { emitConst(arg); } else { ! if (Wrapper.isWrapperType(arg.getClass()) && bptype != L_TYPE) { emitConst(arg); } else { mv.visitLdcInsn(constantPlaceholder(arg)); ! emitImplicitConversion(L_TYPE, ptype); } } } /** * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type. */ private void emitReturn() { // return statement ! Class<?> rclass = invokerType.returnType(); ! BasicType rtype = lambdaForm.returnType(); ! assert(rtype == basicType(rclass)); // must agree ! if (rtype == V_TYPE) { // void mv.visitInsn(Opcodes.RETURN); + // it doesn't matter what rclass is; the JVM will discard any value } else { LambdaForm.Name rn = lambdaForm.names[lambdaForm.result]; // put return value on the stack if it is not already there ! if (lambdaForm.result != lambdaForm.names.length - 1 || ! lambdaForm.result < lambdaForm.arity) { emitLoadInsn(rn.type, lambdaForm.result); } ! emitImplicitConversion(rtype, rclass); // generate actual return statement ! emitReturnInsn(rtype); } } /** * Emit a type conversion bytecode casting from "from" to "to". */ ! private void emitPrimCast(Wrapper from, Wrapper to) { // Here's how. // - indicates forbidden // <-> indicates implicit // to ----> boolean byte short char int long float double // from boolean <-> - - - - - - -
*** 947,988 **** // double - d2i,i2b d2i,i2s d2i,i2c d2i d2l d2f <-> if (from == to) { // no cast required, should be dead code anyway return; } ! Wrapper wfrom = Wrapper.forBasicType(from); ! Wrapper wto = Wrapper.forBasicType(to); ! if (wfrom.isSubwordOrInt()) { // cast from {byte,short,char,int} to anything emitI2X(to); } else { // cast from {long,float,double} to anything ! if (wto.isSubwordOrInt()) { // cast to {byte,short,char,int} emitX2I(from); ! if (wto.bitWidth() < 32) { // targets other than int require another conversion emitI2X(to); } } else { // cast to {long,float,double} - this is verbose boolean error = false; switch (from) { ! case 'J': ! if (to == 'F') { mv.visitInsn(Opcodes.L2F); } ! else if (to == 'D') { mv.visitInsn(Opcodes.L2D); } ! else error = true; break; ! case 'F': ! if (to == 'J') { mv.visitInsn(Opcodes.F2L); } ! else if (to == 'D') { mv.visitInsn(Opcodes.F2D); } ! else error = true; break; ! case 'D': ! if (to == 'J') { mv.visitInsn(Opcodes.D2L); } ! else if (to == 'F') { mv.visitInsn(Opcodes.D2F); } ! else error = true; break; default: error = true; break; } --- 931,976 ---- // double - d2i,i2b d2i,i2s d2i,i2c d2i d2l d2f <-> if (from == to) { // no cast required, should be dead code anyway return; } ! if (from.isSubwordOrInt()) { // cast from {byte,short,char,int} to anything emitI2X(to); } else { // cast from {long,float,double} to anything ! if (to.isSubwordOrInt()) { // cast to {byte,short,char,int} emitX2I(from); ! if (to.bitWidth() < 32) { // targets other than int require another conversion emitI2X(to); } } else { // cast to {long,float,double} - this is verbose boolean error = false; switch (from) { ! case LONG: ! switch (to) { ! case FLOAT: mv.visitInsn(Opcodes.L2F); break; ! case DOUBLE: mv.visitInsn(Opcodes.L2D); break; ! default: error = true; break; ! } break; ! case FLOAT: ! switch (to) { ! case LONG : mv.visitInsn(Opcodes.F2L); break; ! case DOUBLE: mv.visitInsn(Opcodes.F2D); break; ! default: error = true; break; ! } break; ! case DOUBLE: ! switch (to) { ! case LONG : mv.visitInsn(Opcodes.D2L); break; ! case FLOAT: mv.visitInsn(Opcodes.D2F); break; ! default: error = true; break; ! } break; default: error = true; break; }
*** 991,1051 **** } } } } ! private void emitI2X(char type) { switch (type) { ! case 'B': mv.visitInsn(Opcodes.I2B); break; ! case 'S': mv.visitInsn(Opcodes.I2S); break; ! case 'C': mv.visitInsn(Opcodes.I2C); break; ! case 'I': /* naught */ break; ! case 'J': mv.visitInsn(Opcodes.I2L); break; ! case 'F': mv.visitInsn(Opcodes.I2F); break; ! case 'D': mv.visitInsn(Opcodes.I2D); break; ! case 'Z': // For compatibility with ValueConversions and explicitCastArguments: mv.visitInsn(Opcodes.ICONST_1); mv.visitInsn(Opcodes.IAND); break; default: throw new InternalError("unknown type: " + type); } } ! private void emitX2I(char type) { switch (type) { ! case 'J': mv.visitInsn(Opcodes.L2I); break; ! case 'F': mv.visitInsn(Opcodes.F2I); break; ! case 'D': mv.visitInsn(Opcodes.D2I); break; default: throw new InternalError("unknown type: " + type); } } - private static String basicTypeCharSignature(String prefix, MethodType type) { - StringBuilder buf = new StringBuilder(prefix); - for (Class<?> ptype : type.parameterList()) - buf.append(Wrapper.forBasicType(ptype).basicTypeChar()); - buf.append('_').append(Wrapper.forBasicType(type.returnType()).basicTypeChar()); - return buf.toString(); - } - /** * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments. */ static MemberName generateLambdaFormInterpreterEntryPoint(String sig) { ! assert(LambdaForm.isValidSignature(sig)); ! //System.out.println("generateExactInvoker "+sig); ! // compute method type ! // first parameter and return type ! char tret = LambdaForm.signatureReturn(sig); ! MethodType type = MethodType.methodType(LambdaForm.typeClass(tret), MethodHandle.class); ! // other parameter types ! int arity = LambdaForm.signatureArity(sig); ! for (int i = 1; i < arity; i++) { ! type = type.appendParameterTypes(LambdaForm.typeClass(sig.charAt(i))); ! } ! InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", "interpret_"+tret, type); return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } private byte[] generateLambdaFormInterpreterEntryPointBytes() { classFilePrologue(); --- 979,1024 ---- } } } } ! private void emitI2X(Wrapper type) { switch (type) { ! case BYTE: mv.visitInsn(Opcodes.I2B); break; ! case SHORT: mv.visitInsn(Opcodes.I2S); break; ! case CHAR: mv.visitInsn(Opcodes.I2C); break; ! case INT: /* naught */ break; ! case LONG: mv.visitInsn(Opcodes.I2L); break; ! case FLOAT: mv.visitInsn(Opcodes.I2F); break; ! case DOUBLE: mv.visitInsn(Opcodes.I2D); break; ! case BOOLEAN: // For compatibility with ValueConversions and explicitCastArguments: mv.visitInsn(Opcodes.ICONST_1); mv.visitInsn(Opcodes.IAND); break; default: throw new InternalError("unknown type: " + type); } } ! private void emitX2I(Wrapper type) { switch (type) { ! case LONG: mv.visitInsn(Opcodes.L2I); break; ! case FLOAT: mv.visitInsn(Opcodes.F2I); break; ! case DOUBLE: mv.visitInsn(Opcodes.D2I); break; default: throw new InternalError("unknown type: " + type); } } /** * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments. */ static MemberName generateLambdaFormInterpreterEntryPoint(String sig) { ! assert(isValidSignature(sig)); ! String name = "interpret_"+signatureReturn(sig).basicTypeChar(); ! MethodType type = signatureType(sig); // sig includes leading argument ! type = type.changeParameterType(0, MethodHandle.class); ! InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", name, type); return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } private byte[] generateLambdaFormInterpreterEntryPointBytes() { classFilePrologue();
*** 1063,1076 **** // fill parameter array for (int i = 0; i < invokerType.parameterCount(); i++) { Class<?> ptype = invokerType.parameterType(i); mv.visitInsn(Opcodes.DUP); emitIconstInsn(i); ! emitLoadInsn(Wrapper.basicTypeChar(ptype), i); // box if primitive type if (ptype.isPrimitive()) { ! emitBoxing(ptype); } mv.visitInsn(Opcodes.AASTORE); } // invoke emitAloadInsn(0); --- 1036,1049 ---- // fill parameter array for (int i = 0; i < invokerType.parameterCount(); i++) { Class<?> ptype = invokerType.parameterType(i); mv.visitInsn(Opcodes.DUP); emitIconstInsn(i); ! emitLoadInsn(basicType(ptype), i); // box if primitive type if (ptype.isPrimitive()) { ! emitBoxing(Wrapper.forPrimitiveType(ptype)); } mv.visitInsn(Opcodes.AASTORE); } // invoke emitAloadInsn(0);
*** 1079,1093 **** mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;", false); // maybe unbox Class<?> rtype = invokerType.returnType(); if (rtype.isPrimitive() && rtype != void.class) { ! emitUnboxing(Wrapper.asWrapperType(rtype)); } // return statement ! emitReturnInsn(rtype); classFileEpilogue(); bogusMethod(invokerType); final byte[] classFile = cw.toByteArray(); --- 1052,1066 ---- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;", false); // maybe unbox Class<?> rtype = invokerType.returnType(); if (rtype.isPrimitive() && rtype != void.class) { ! emitUnboxing(Wrapper.forPrimitiveType(rtype)); } // return statement ! emitReturnInsn(basicType(rtype)); classFileEpilogue(); bogusMethod(invokerType); final byte[] classFile = cw.toByteArray();
*** 1097,1114 **** /** * Generate bytecode for a NamedFunction invoker. */ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { ! MethodType invokerType = LambdaForm.NamedFunction.INVOKER_METHOD_TYPE; ! String invokerName = basicTypeCharSignature("invoke_", typeForm.erasedType()); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType); return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm)); } - static int nfi = 0; - private byte[] generateNamedFunctionInvokerImpl(MethodTypeForm typeForm) { MethodType dstType = typeForm.erasedType(); classFilePrologue(); // Suppress this method in backtraces displayed to the user. --- 1070,1085 ---- /** * Generate bytecode for a NamedFunction invoker. */ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { ! MethodType invokerType = NamedFunction.INVOKER_METHOD_TYPE; ! String invokerName = "invoke_" + shortenSignature(basicTypeSignature(typeForm.erasedType())); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType); return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm)); } private byte[] generateNamedFunctionInvokerImpl(MethodTypeForm typeForm) { MethodType dstType = typeForm.erasedType(); classFilePrologue(); // Suppress this method in backtraces displayed to the user.
*** 1130,1141 **** Class<?> dptype = dstType.parameterType(i); if (dptype.isPrimitive()) { Class<?> sptype = dstType.basicType().wrap().parameterType(i); Wrapper dstWrapper = Wrapper.forBasicType(dptype); Wrapper srcWrapper = dstWrapper.isSubwordOrInt() ? Wrapper.INT : dstWrapper; // narrow subword from int ! emitUnboxing(srcWrapper.wrapperType()); ! emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar()); } } // Invoke String targetDesc = dstType.basicType().toMethodDescriptorString(); --- 1101,1112 ---- Class<?> dptype = dstType.parameterType(i); if (dptype.isPrimitive()) { Class<?> sptype = dstType.basicType().wrap().parameterType(i); Wrapper dstWrapper = Wrapper.forBasicType(dptype); Wrapper srcWrapper = dstWrapper.isSubwordOrInt() ? Wrapper.INT : dstWrapper; // narrow subword from int ! emitUnboxing(srcWrapper); ! emitPrimCast(srcWrapper, dstWrapper); } } // Invoke String targetDesc = dstType.basicType().toMethodDescriptorString();
*** 1145,1163 **** Class<?> rtype = dstType.returnType(); if (rtype != void.class && rtype.isPrimitive()) { Wrapper srcWrapper = Wrapper.forBasicType(rtype); Wrapper dstWrapper = srcWrapper.isSubwordOrInt() ? Wrapper.INT : srcWrapper; // widen subword to int // boolean casts not allowed ! emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar()); ! emitBoxing(dstWrapper.primitiveType()); } // If the return type is void we return a null reference. if (rtype == void.class) { mv.visitInsn(Opcodes.ACONST_NULL); } ! emitReturnInsn(Object.class); // NOTE: NamedFunction invokers always return a reference value. classFileEpilogue(); bogusMethod(dstType); final byte[] classFile = cw.toByteArray(); --- 1116,1134 ---- Class<?> rtype = dstType.returnType(); if (rtype != void.class && rtype.isPrimitive()) { Wrapper srcWrapper = Wrapper.forBasicType(rtype); Wrapper dstWrapper = srcWrapper.isSubwordOrInt() ? Wrapper.INT : srcWrapper; // widen subword to int // boolean casts not allowed ! emitPrimCast(srcWrapper, dstWrapper); ! emitBoxing(dstWrapper); } // If the return type is void we return a null reference. if (rtype == void.class) { mv.visitInsn(Opcodes.ACONST_NULL); } ! emitReturnInsn(L_TYPE); // NOTE: NamedFunction invokers always return a reference value. classFileEpilogue(); bogusMethod(dstType); final byte[] classFile = cw.toByteArray();
src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File