28 import jdk.internal.access.JavaLangAccess;
29 import jdk.internal.access.SharedSecrets;
30 import jdk.internal.misc.VM;
31 import jdk.internal.org.objectweb.asm.ClassWriter;
32 import jdk.internal.org.objectweb.asm.Label;
33 import jdk.internal.org.objectweb.asm.MethodVisitor;
34 import jdk.internal.org.objectweb.asm.Opcodes;
35 import sun.invoke.util.Wrapper;
36
37 import java.lang.invoke.MethodHandles.Lookup;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.concurrent.ConcurrentMap;
44 import java.util.function.Function;
45
46 import static java.lang.invoke.MethodHandles.lookup;
47 import static java.lang.invoke.MethodType.methodType;
48 import static java.lang.invoke.MethodHandleNatives.Constants.*;
49 import static jdk.internal.org.objectweb.asm.Opcodes.*;
50
51 /**
52 * <p>Methods to facilitate the creation of String concatenation methods, that
53 * can be used to efficiently concatenate a known number of arguments of known
54 * types, possibly after type adaptation and partial evaluation of arguments.
55 * These methods are typically used as <em>bootstrap methods</em> for {@code
56 * invokedynamic} call sites, to support the <em>string concatenation</em>
57 * feature of the Java Programming Language.
58 *
59 * <p>Indirect access to the behavior specified by the provided {@code
60 * MethodHandle} proceeds in order through two phases:
61 *
62 * <ol>
63 * <li><em>Linkage</em> occurs when the methods in this class are invoked.
64 * They take as arguments a method type describing the concatenated arguments
65 * count and types, and optionally the String <em>recipe</em>, plus the
66 * constants that participate in the String concatenation. The details on
67 * accepted recipe shapes are described further below. Linkage may involve
68 * dynamically loading a new class that implements the expected concatenation
1125
1126 mv.visitLabel(l0);
1127 }
1128
1129 mv.visitMethodInsn(
1130 INVOKEVIRTUAL,
1131 "java/lang/StringBuilder",
1132 "toString",
1133 "()Ljava/lang/String;",
1134 false
1135 );
1136
1137 mv.visitInsn(ARETURN);
1138
1139 mv.visitMaxs(-1, -1);
1140 mv.visitEnd();
1141 cw.visitEnd();
1142
1143 byte[] classBytes = cw.toByteArray();
1144 try {
1145 Class<?> innerClass = lookup.defineHiddenClass(classBytes,true).lookupClass();
1146 dumpIfEnabled(className, classBytes);
1147 return lookup.findStatic(innerClass, METHOD_NAME, args);
1148 } catch (Exception e) {
1149 dumpIfEnabled(className + "$$FAILED", classBytes);
1150 throw new StringConcatException("Exception while spinning the class", e);
1151 }
1152 }
1153
1154 private static void dumpIfEnabled(String name, byte[] bytes) {
1155 if (DUMPER != null) {
1156 DUMPER.dumpClass(name, bytes);
1157 }
1158 }
1159
1160 private static String getSBAppendDesc(Class<?> cl) {
1161 if (cl.isPrimitive()) {
1162 if (cl == Integer.TYPE || cl == Byte.TYPE || cl == Short.TYPE) {
1163 return "(I)Ljava/lang/StringBuilder;";
1164 } else if (cl == Boolean.TYPE) {
1165 return "(Z)Ljava/lang/StringBuilder;";
|
28 import jdk.internal.access.JavaLangAccess;
29 import jdk.internal.access.SharedSecrets;
30 import jdk.internal.misc.VM;
31 import jdk.internal.org.objectweb.asm.ClassWriter;
32 import jdk.internal.org.objectweb.asm.Label;
33 import jdk.internal.org.objectweb.asm.MethodVisitor;
34 import jdk.internal.org.objectweb.asm.Opcodes;
35 import sun.invoke.util.Wrapper;
36
37 import java.lang.invoke.MethodHandles.Lookup;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.concurrent.ConcurrentMap;
44 import java.util.function.Function;
45
46 import static java.lang.invoke.MethodHandles.lookup;
47 import static java.lang.invoke.MethodType.methodType;
48 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
49 import static jdk.internal.org.objectweb.asm.Opcodes.*;
50
51 /**
52 * <p>Methods to facilitate the creation of String concatenation methods, that
53 * can be used to efficiently concatenate a known number of arguments of known
54 * types, possibly after type adaptation and partial evaluation of arguments.
55 * These methods are typically used as <em>bootstrap methods</em> for {@code
56 * invokedynamic} call sites, to support the <em>string concatenation</em>
57 * feature of the Java Programming Language.
58 *
59 * <p>Indirect access to the behavior specified by the provided {@code
60 * MethodHandle} proceeds in order through two phases:
61 *
62 * <ol>
63 * <li><em>Linkage</em> occurs when the methods in this class are invoked.
64 * They take as arguments a method type describing the concatenated arguments
65 * count and types, and optionally the String <em>recipe</em>, plus the
66 * constants that participate in the String concatenation. The details on
67 * accepted recipe shapes are described further below. Linkage may involve
68 * dynamically loading a new class that implements the expected concatenation
1125
1126 mv.visitLabel(l0);
1127 }
1128
1129 mv.visitMethodInsn(
1130 INVOKEVIRTUAL,
1131 "java/lang/StringBuilder",
1132 "toString",
1133 "()Ljava/lang/String;",
1134 false
1135 );
1136
1137 mv.visitInsn(ARETURN);
1138
1139 mv.visitMaxs(-1, -1);
1140 mv.visitEnd();
1141 cw.visitEnd();
1142
1143 byte[] classBytes = cw.toByteArray();
1144 try {
1145 Class<?> innerClass = lookup.defineHiddenClass(classBytes, true, STRONG).lookupClass();
1146 dumpIfEnabled(className, classBytes);
1147 return lookup.findStatic(innerClass, METHOD_NAME, args);
1148 } catch (Exception e) {
1149 dumpIfEnabled(className + "$$FAILED", classBytes);
1150 throw new StringConcatException("Exception while spinning the class", e);
1151 }
1152 }
1153
1154 private static void dumpIfEnabled(String name, byte[] bytes) {
1155 if (DUMPER != null) {
1156 DUMPER.dumpClass(name, bytes);
1157 }
1158 }
1159
1160 private static String getSBAppendDesc(Class<?> cl) {
1161 if (cl.isPrimitive()) {
1162 if (cl == Integer.TYPE || cl == Byte.TYPE || cl == Short.TYPE) {
1163 return "(I)Ljava/lang/StringBuilder;";
1164 } else if (cl == Boolean.TYPE) {
1165 return "(Z)Ljava/lang/StringBuilder;";
|