Methods to facilitate the creation of String concatenation methods, that
can be used to efficiently concatenate a known number of arguments of known
types, possibly after type adaptation and partial evaluation of arguments.
These methods are typically used as bootstrap methods for invokedynamic call sites, to support the string concatenation
feature of the Java Programming Language.
Indirect access to the behavior specified by the provided MethodHandle proceeds in order through two phases:
CallSite holds the MethodHandle pointing to the
exact concatenation method. The concatenation methods may be shared among
different CallSites, e.g. if linkage methods produce them as pure
functions.MethodHandle is invoked with the static arguments and any additional dynamic
arguments provided on invocation, as if by MethodHandle#invoke(Object...) . This class provides two forms of linkage methods: a simple version
(makeConcat(java.) using only the dynamic arguments, and an advanced version
(makeConcatWithConstants(java. using the advanced forms of capturing
the constant arguments. The advanced strategy can produce marginally better
invocation bytecode, at the expense of exploding the number of shapes of
string concatenation methods present at runtime, because those shapes would
include constant static arguments as well.
API Note
There is a JVM limit (classfile structural constraint): no method
can call with more than 255 slots. This limits the number of static and
dynamic arguments one can pass to bootstrap method. Since there are potential
concatenation strategies that use MethodHandle combinators, we need
to reserve a few empty slots on the parameter lists to capture the
temporal results. This is why bootstrap methods in this factory do not accept
more than 200 argument slots. Users requiring more than 200 argument slots in
concatenation are expected to split the large concatenation in smaller
expressions.
| Modifier and Type | Class and Description |
|---|---|
| private static class | StringConcatFactory.
Implement efficient hidden class strategy for String concatenation This strategy replicates based on the bytecode what StringBuilders are doing: it builds the byte[] array on its own and passes that byte[] array to String constructor. |
| Modifier and Type | Field and Description |
|---|---|
| private static MethodHandle | |
| private static final int | |
| private static MethodHandle | |
| private static MethodHandle | |
| private static MethodHandle | FLOAT_STRINGIFIER
Public gateways to public "stringify" methods. |
| private static final int | |
| private static MethodHandle | |
| private static final JavaLangAccess | |
| private static MethodHandle | |
| private static final int | MAX_INDY_CONCAT_ARG_SLOTS
Maximum number of argument slots in String Concat call. |
| private static MethodHandle | |
| private static MethodHandle | |
| private static final char | TAG_ARG
Tag used to demarcate an ordinary argument. |
| private static final char | TAG_CONST
Tag used to demarcate a constant. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| private static StringConcatException | |
| private static MethodHandle | |
| private static MethodHandle | |
| private static StringConcatException | |
| private static MethodHandle | |
| private static MethodHandle | |
| private static MethodHandle | |
| private static MethodHandle | |
| public static CallSite | Returns: a CallSite whose target can be used to perform String concatenation, with dynamic concatenation arguments described by the givenconcatType.Represents a lookup context with the accessibility
privileges of the caller. Specifically, the lookup
context must have
full privilege access.
When used with lookup,invokedynamic, this is stacked
automatically by the VM.The name of the method to implement. This name is
arbitrary, and has no meaning for this linkage method.
When used with name, MethodType invokedynamic, this is provided by
the NameAndType of the InvokeDynamic
structure and is stacked automatically by the VM.The expected signature of the concatType)CallSite. The
parameter types represent the types of concatenation
arguments; the return type is always assignable from java.. When used with invokedynamic,
this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by
the VM.Facilitates the creation of optimized String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments. |
| public static CallSite | Returns: a CallSite whose target can be used to perform String concatenation, with dynamic concatenation arguments described by the givenconcatType.Represents a lookup context with the accessibility
privileges of the caller. Specifically, the lookup
context must have
full privilege access.
When used with lookup,invokedynamic, this is stacked
automatically by the VM.The name of the method to implement. This name is
arbitrary, and has no meaning for this linkage method.
When used with name, MethodType invokedynamic, this is provided
by the NameAndType of the InvokeDynamic
structure and is stacked automatically by the VM.The expected signature of the concatType, String CallSite. The
parameter types represent the types of dynamic concatenation
arguments; the return type is always assignable from java.. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and
is stacked automatically by the VM.Concatenation recipe, described above. recipe, Object... A vararg parameter representing the constants passed to
the linkage method. constants)Facilitates the creation of optimized String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments. |
| private static MethodHandle | |
| private static MethodHandle | |
| private static String[] | |
| private static MethodHandle | |
| private static MethodHandle | |
| private static MethodHandle |
| BOOLEAN_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle BOOLEAN_STRINGIFIER
| |
| CACHE_THRESHOLD | back to summary |
|---|---|
| private static final int CACHE_THRESHOLD | |
| CHAR_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle CHAR_STRINGIFIER
| |
| DOUBLE_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle DOUBLE_STRINGIFIER
| |
| FLOAT_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle FLOAT_STRINGIFIER Public gateways to public "stringify" methods. These methods have the
form String apply(T obj), and normally delegate to | |
| FORCE_INLINE_THRESHOLD | back to summary |
|---|---|
| private static final int FORCE_INLINE_THRESHOLD | |
| INT_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle INT_STRINGIFIER
| |
| JLA | back to summary |
|---|---|
| private static final JavaLangAccess JLA | |
| LONG_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle LONG_STRINGIFIER
| |
| MAX_INDY_CONCAT_ARG_SLOTS | back to summary |
|---|---|
| private static final int MAX_INDY_CONCAT_ARG_SLOTS Maximum number of argument slots in String Concat call. While the maximum number of argument slots that indy call can handle is 253, we do not use all those slots, to let the strategies with MethodHandle combinators to use some arguments. | |
| NEW_STRINGIFIER | back to summary |
|---|---|
| private static MethodHandle NEW_STRINGIFIER
| |
| SIMPLE_CONCAT | back to summary |
|---|---|
| private static MethodHandle SIMPLE_CONCAT
| |
| TAG_ARG | back to summary |
|---|---|
| private static final char TAG_ARG Tag used to demarcate an ordinary argument. | |
| TAG_CONST | back to summary |
|---|---|
| private static final char TAG_CONST Tag used to demarcate a constant. | |
| StringConcatFactory | back to summary |
|---|---|
| private StringConcatFactory() | |
| argumentMismatch | back to summary |
|---|---|
| private static StringConcatException argumentMismatch(MethodType concatType, int oCount) | |
| booleanStringifier | back to summary |
|---|---|
| private static MethodHandle booleanStringifier() | |
| charStringifier | back to summary |
|---|---|
| private static MethodHandle charStringifier() | |
| constantMismatch | back to summary |
|---|---|
| private static StringConcatException constantMismatch(Object[] constants, int cCount) | |
| doubleStringifier | back to summary |
|---|---|
| private static MethodHandle doubleStringifier() | |
| floatStringifier | back to summary |
|---|---|
| private static MethodHandle floatStringifier() | |
| intStringifier | back to summary |
|---|---|
| private static MethodHandle intStringifier() | |
| longStringifier | back to summary |
|---|---|
| private static MethodHandle longStringifier() | |
| makeConcat | back to summary |
|---|---|
| public static CallSite makeConcat(MethodHandles. Facilitates the creation of optimized String concatenation methods, that
can be used to efficiently concatenate a known number of arguments of
known types, possibly after type adaptation and partial evaluation of
arguments. Typically used as a bootstrap method for When the target of the
Assume the linkage arguments are as follows:
Then the following linkage invariants must hold:
| |
| makeConcatWithConstants | back to summary |
|---|---|
| public static CallSite makeConcatWithConstants(MethodHandles. Facilitates the creation of optimized String concatenation methods, that
can be used to efficiently concatenate a known number of arguments of
known types, possibly after type adaptation and partial evaluation of
arguments. Typically used as a bootstrap method for When the target of the
The concatenation recipe is a String description for the way to construct a concatenated String from the arguments and constants. The recipe is processed from left to right, and each character represents an input to concatenation. Recipe characters mean:
Assume the linkage arguments are as follows:
Then the following linkage invariants must hold:
API Note Code generators have three distinct ways to process a constant string operand S in a string concatenation expression. First, S can be materialized as a reference (using ldc) and passed as an ordinary argument (recipe '\1'). Or, S can be stored in the constant pool and passed as a constant (recipe '\2') . Finally, if S contains neither of the recipe tag characters ('\1', '\2') then S can be interpolated into the recipe itself, causing its characters to be inserted into the result.
| |
| makeSimpleConcat | back to summary |
|---|---|
| private static MethodHandle makeSimpleConcat(MethodType mt, String[] constants) | |
| newStringifier | back to summary |
|---|---|
| private static MethodHandle newStringifier() | |
| parseRecipe | back to summary |
|---|---|
| private static String[] parseRecipe(MethodType concatType, String recipe, Object[] constants) throws StringConcatException | |
| simpleConcat | back to summary |
|---|---|
| private static MethodHandle simpleConcat() | |
| stringValueOf | back to summary |
|---|---|
| private static MethodHandle stringValueOf(Class<?> ptype) | |
| unaryConcat | back to summary |
|---|---|
| private static MethodHandle unaryConcat(Class<?> cl) | |
This strategy replicates based on the bytecode what StringBuilders are doing: it builds the byte[] array on its own and passes that byte[] array to String constructor. This strategy requires access to some private APIs in JDK, most notably, the private String constructor that accepts byte[] arrays without copying.
| Modifier and Type | Class and Description |
|---|---|
| private static record |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv static final ReferencedKeyMap | |
| pack-priv static final ClassDesc | |
| pack-priv static final ClassDesc | |
| pack-priv static final ClassDesc | |
| pack-priv static final ClassDesc | |
| pack-priv static final ClassDesc | |
| pack-priv static final String | |
| pack-priv static final Consumer | |
| pack-priv static final MethodType | |
| pack-priv static final ClassFileDumper | |
| pack-priv static final RuntimeVisibleAnnotationsAttribute | |
| pack-priv static final String | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodTypeDesc | |
| pack-priv static final MethodHandles. |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| private static MethodTypeDesc | |
| private static MethodType | erasedArgs(MethodType args)
The parameter types are normalized into 7 types: int,long,boolean,char,float,double,Object |
| private static MethodHandle | |
| private static Consumer | |
| private static Consumer | generateConcatMethod(boolean staticConcat, String[] constants, ClassDesc concatClass, MethodType concatArgs, MethodTypeDesc lengthArgs, MethodTypeDesc coderArgs, MethodTypeDesc prependArgs)
Generate InlineCopy-based code. |
| private static Consumer | |
| private static Consumer | generatePrependMethod(MethodTypeDesc prependArgs, boolean staticConcat, String[] constants)
Generate prepend method. |
| private static MethodTypeDesc | lengthArgs(MethodType concatArgs)
Construct the MethodType of the length method, The first parameter is the initialized length |
| pack-priv static boolean | |
| pack-priv static boolean | |
| private static MethodTypeDesc | prependArgs(MethodType concatArgs, boolean staticConcat)
Construct the MethodType of the prepend method, The parameters only support 5 types: int/long/char/boolean/String. |
| CACHE | back to summary |
|---|---|
| pack-priv static final ReferencedKeyMap<MethodType, SoftReference<StringConcatFactory. | |
| CD_Array_byte | back to summary |
|---|---|
| pack-priv static final ClassDesc CD_Array_byte | |
| CD_Array_String | back to summary |
|---|---|
| pack-priv static final ClassDesc CD_Array_String | |
| CD_CONCAT | back to summary |
|---|---|
| pack-priv static final ClassDesc CD_CONCAT | |
| CD_StringConcatBase | back to summary |
|---|---|
| pack-priv static final ClassDesc CD_StringConcatBase | |
| CD_StringConcatHelper | back to summary |
|---|---|
| pack-priv static final ClassDesc CD_StringConcatHelper | |
| CLASS_NAME | back to summary |
|---|---|
| pack-priv static final String CLASS_NAME | |
| CONSTRUCTOR_BUILDER | back to summary |
|---|---|
| pack-priv static final Consumer<CodeBuilder> CONSTRUCTOR_BUILDER | |
| CONSTRUCTOR_METHOD_TYPE | back to summary |
|---|---|
| pack-priv static final MethodType CONSTRUCTOR_METHOD_TYPE | |
| DUMPER | back to summary |
|---|---|
| pack-priv static final ClassFileDumper DUMPER | |
| FORCE_INLINE | back to summary |
|---|---|
| pack-priv static final RuntimeVisibleAnnotationsAttribute FORCE_INLINE | |
| METHOD_NAME | back to summary |
|---|---|
| pack-priv static final String METHOD_NAME | |
| MTD_byte | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_byte | |
| MTD_byte_char | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_byte_char | |
| MTD_INIT | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_INIT | |
| MTD_int | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_int | |
| MTD_int_int_boolean | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_int_int_boolean | |
| MTD_int_int_char | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_int_int_char | |
| MTD_int_int_int | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_int_int_int | |
| MTD_int_int_long | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_int_int_long | |
| MTD_int_int_String | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_int_int_String | |
| MTD_NEW_ARRAY_SUFFIX | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_NEW_ARRAY_SUFFIX | |
| MTD_String_double | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_String_double | |
| MTD_String_float | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_String_float | |
| MTD_STRING_INIT | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_STRING_INIT | |
| MTD_String_Object | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc MTD_String_Object | |
| PREPEND_boolean | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc PREPEND_boolean | |
| PREPEND_char | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc PREPEND_char | |
| PREPEND_int | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc PREPEND_int | |
| PREPEND_long | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc PREPEND_long | |
| PREPEND_String | back to summary |
|---|---|
| pack-priv static final MethodTypeDesc PREPEND_String | |
| STR_LOOKUP | back to summary |
|---|---|
| pack-priv static final MethodHandles. | |
| InlineHiddenClassStrategy | back to summary |
|---|---|
| private InlineHiddenClassStrategy() | |
| coderArgsIfMaybeUTF16 | back to summary |
|---|---|
| private static MethodTypeDesc coderArgsIfMaybeUTF16(MethodType concatArgs) Construct the MethodType of the coder method. The first parameter is the initialized coder. Only parameter types which can be UTF16 are added. Returns null if no such parameter exists or CompactStrings is off. | |
| erasedArgs | back to summary |
|---|---|
| private static MethodType erasedArgs(MethodType args) The parameter types are normalized into 7 types: int,long,boolean,char,float,double,Object | |
| generate | back to summary |
|---|---|
| private static MethodHandle generate(MethodHandles. | |
| generateCoderMethod | back to summary |
|---|---|
| private static Consumer Generate coder method. The following is an example of the generated target code:
| |
| generateConcatMethod | back to summary |
|---|---|
| private static Consumer Generate InlineCopy-based code. The following is an example of the generated target code:
| |
| generateLengthMethod | back to summary |
|---|---|
| private static Consumer Generate length method. The following is an example of the generated target code:
| |
| generatePrependMethod | back to summary |
|---|---|
| private static Consumer Generate prepend method. The following is an example of the generated target code:
| |
| lengthArgs | back to summary |
|---|---|
| private static MethodTypeDesc lengthArgs(MethodType concatArgs) Construct the MethodType of the length method, The first parameter is the initialized length | |
| maybeUTF16 | back to summary |
|---|---|
| pack-priv static boolean maybeUTF16(Class<?> cl) | |
| needStringOf | back to summary |
|---|---|
| pack-priv static boolean needStringOf(Class<?> cl) | |
| prependArgs | back to summary |
|---|---|
| private static MethodTypeDesc prependArgs(MethodType concatArgs, boolean staticConcat) Construct the MethodType of the prepend method, The parameters only support 5 types: int/long/char/boolean/String. Not int/long/char/boolean type, use String type The following is an example of the generated target code:
| |
| Modifier and Type | Field and Description |
|---|---|
| private final MethodHandle | concatenator
Record Component accessed by concatenator(). |
| private final MethodHandle | constructor
Record Component accessed by constructor(). |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| public MethodHandle | |
| public MethodHandle | |
| public final boolean | equals(Object o)
Implements abstract java. Indicates whether some other object is "equal to" this one. |
| public final int | |
| public final String | toString()
Implements abstract java. Returns a string representation of the record. |
| concatenator | back to summary |
|---|---|
| private final MethodHandle concatenator Record Component accessed by concatenator(). | |
| constructor | back to summary |
|---|---|
| private final MethodHandle constructor Record Component accessed by constructor(). | |
| MethodHandlePair | back to summary |
|---|---|
| private MethodHandlePair(MethodHandle constructor, MethodHandle concatenator) | |
| concatenator | back to summary |
|---|---|
| public MethodHandle concatenator() Record Component getter of concatenator. | |
| constructor | back to summary |
|---|---|
| public MethodHandle constructor() Record Component getter of constructor. | |
| equals | back to summary |
|---|---|
| public final boolean equals(Object o) Implements abstract java. Doc from java. Indicates whether some other object is "equal to" this one. In addition
to the general contract of
R copy = new R(r.c1(), r.c2(), ..., r.cn());
then it must be the case that r.equals(copy).
| |
| hashCode | back to summary |
|---|---|
| public final int hashCode() Implements abstract java. Doc from java. Returns a hash code value for the record.
Obeys the general contract of | |
| toString | back to summary |
|---|---|
| public final String toString() Implements abstract java. Doc from java. Returns a string representation of the record.
In accordance with the general contract of In addition to this general contract, record classes must further participate in the invariant that any two records which are equal must produce equal strings. This invariant is necessarily relaxed in the rare case where corresponding equal component values might fail to produce equal strings for themselves. | |