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 CallSite
s, 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.
Bytecode StringBuilder strategy. |
Modifier and Type | Field and Description |
---|---|
private static final int | |
private static MethodHandle | |
private static final int | |
private static MethodHandle | |
private static final MethodHandle[][] | |
private static final MethodHandle[][] | |
private static MethodHandle | |
private static MethodHandle | |
private static final int | |
private static final long | |
private static final int | |
private static MethodHandle | |
private static final JavaLangAccess | |
private static final int | |
private static MethodHandle | |
private static final int | MAX_INDY_CONCAT_ARG_SLOTS
Maximum number of argument slots in String Concat call. |
private static final int[] | |
private static final int[] | |
private static final int[] | |
private static final MethodHandle[] | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static final MethodHandle[] | |
private static MethodHandle | OBJECT_STRINGIFIER
Public gateways to public "stringify" methods. |
private static MethodHandle | |
private static final int[] | |
private static final int[] | |
private static final int[] | |
private static final int[] | |
private static final int[] | |
private static final MethodHandle[] | |
private static MethodHandle | |
private static final int | |
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. |
private static final int |
Access | Constructor and Description |
---|---|
private |
Modifier and Type | Method and Description |
---|---|
private static StringConcatException | |
private static MethodHandle | |
private static MethodHandle | |
private static int | |
private static StringConcatException | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
pack-priv static int[] | |
pack-priv static int[] | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | generateMHInlineCopy(MethodType mt, String[] constants)
This strategy replicates what StringBuilders are doing: it builds the byte[] array on its own and passes that byte[] array to String constructor. |
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 MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static String[] | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static MethodHandle | |
private static Class | |
private static MethodHandle | |
private static MethodHandle | Returns: stringifier; null, if not availableclass to stringify t)Returns a stringifier for references and floats/doubles only. |
private static MethodHandle | |
private static MethodHandle |
BOOLEAN_IDX | back to summary |
---|---|
private static final int BOOLEAN_IDX |
BOOLEAN_STRINGIFIER | back to summary |
---|---|
private static MethodHandle BOOLEAN_STRINGIFIER
|
CHAR_IDX | back to summary |
---|---|
private static final int CHAR_IDX |
CHAR_STRINGIFIER | back to summary |
---|---|
private static MethodHandle CHAR_STRINGIFIER
|
DOUBLE_MIXERS | back to summary |
---|---|
private static final MethodHandle[][] DOUBLE_MIXERS
|
DOUBLE_PREPENDERS | back to summary |
---|---|
private static final MethodHandle[][] DOUBLE_PREPENDERS
|
DOUBLE_STRINGIFIER | back to summary |
---|---|
private static MethodHandle DOUBLE_STRINGIFIER
|
FLOAT_STRINGIFIER | back to summary |
---|---|
private static MethodHandle FLOAT_STRINGIFIER
|
HIGH_ARITY_THRESHOLD | back to summary |
---|---|
private static final int HIGH_ARITY_THRESHOLD |
INITIAL_CODER | back to summary |
---|---|
private static final long INITIAL_CODER |
INT_IDX | back to summary |
---|---|
private static final int INT_IDX |
INT_STRINGIFIER | back to summary |
---|---|
private static MethodHandle INT_STRINGIFIER
|
JLA | back to summary |
---|---|
private static final JavaLangAccess JLA |
LONG_IDX | back to summary |
---|---|
private static final int LONG_IDX |
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. |
MIX_FILTER_SECOND_ARGS | back to summary |
---|---|
private static final int[] MIX_FILTER_SECOND_ARGS |
MIX_FILTER_SECOND_PAIR_ARGS | back to summary |
---|---|
private static final int[] MIX_FILTER_SECOND_PAIR_ARGS |
MIX_FILTER_THIRD_ARGS | back to summary |
---|---|
private static final int[] MIX_FILTER_THIRD_ARGS |
MIXERS | back to summary |
---|---|
private static final MethodHandle[] MIXERS
|
NEW_ARRAY | back to summary |
---|---|
private static MethodHandle NEW_ARRAY
|
NEW_ARRAY_SUFFIX | back to summary |
---|---|
private static MethodHandle NEW_ARRAY_SUFFIX
|
NEW_STRING | back to summary |
---|---|
private static MethodHandle NEW_STRING
|
NEW_STRINGIFIER | back to summary |
---|---|
private static MethodHandle NEW_STRINGIFIER
|
NO_PREFIX_PREPENDERS | back to summary |
---|---|
private static final MethodHandle[] NO_PREFIX_PREPENDERS
|
OBJECT_STRINGIFIER | back to summary |
---|---|
private static MethodHandle OBJECT_STRINGIFIER Public gateways to public "stringify" methods. These methods have the
form String apply(T obj), and normally delegate to |
PREPEND_BASE | back to summary |
---|---|
private static MethodHandle PREPEND_BASE
|
PREPEND_FILTER_FIRST_ARGS | back to summary |
---|---|
private static final int[] PREPEND_FILTER_FIRST_ARGS |
PREPEND_FILTER_FIRST_PAIR_ARGS | back to summary |
---|---|
private static final int[] PREPEND_FILTER_FIRST_PAIR_ARGS |
PREPEND_FILTER_SECOND_ARGS | back to summary |
---|---|
private static final int[] PREPEND_FILTER_SECOND_ARGS |
PREPEND_FILTER_SECOND_PAIR_ARGS | back to summary |
---|---|
private static final int[] PREPEND_FILTER_SECOND_PAIR_ARGS |
PREPEND_FILTER_THIRD_ARGS | back to summary |
---|---|
private static final int[] PREPEND_FILTER_THIRD_ARGS |
PREPENDERS | back to summary |
---|---|
private static final MethodHandle[] PREPENDERS
|
SIMPLE_CONCAT | back to summary |
---|---|
private static MethodHandle SIMPLE_CONCAT
|
STRING_IDX | back to summary |
---|---|
private static final int STRING_IDX |
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. |
TYPE_COUNT | back to summary |
---|---|
private static final int TYPE_COUNT |
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() |
classIndex | back to summary |
---|---|
private static int classIndex(Class<?> cl) |
constantMismatch | back to summary |
---|---|
private static StringConcatException constantMismatch(Object[] constants, int cCount) |
doubleStringifier | back to summary |
---|---|
private static MethodHandle doubleStringifier() |
filterAndFoldInMixers | back to summary |
---|---|
private static MethodHandle filterAndFoldInMixers(MethodHandle mh, long initialLengthCoder, Class<?>[] ptypes) |
filterInPrependers | back to summary |
---|---|
private static MethodHandle filterInPrependers(MethodHandle mh, String[] constants, Class<?>[] ptypes) |
filterMixerArgPositions | back to summary |
---|---|
pack-priv static int[] filterMixerArgPositions(int[] argPositions, int pos, int count) |
filterPrependArgPositions | back to summary |
---|---|
pack-priv static int[] filterPrependArgPositions(int[] argPositions, int pos, int count) |
floatStringifier | back to summary |
---|---|
private static MethodHandle floatStringifier() |
foldInLastMixers | back to summary |
---|---|
private static MethodHandle foldInLastMixers(MethodHandle mh, long initialLengthCoder, int pos, Class<?>[] ptypes, int count) |
generateMHInlineCopy | back to summary |
---|---|
private static MethodHandle generateMHInlineCopy(MethodType mt, String[] constants) This strategy replicates 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. |
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.
|
mixer | back to summary |
---|---|
private static MethodHandle mixer(Class<?> cl) |
mixer | back to summary |
---|---|
private static MethodHandle mixer(Class<?> cl, Class<?> cl2) |
mixer | back to summary |
---|---|
private static MethodHandle mixer(Class<?> cl, Class<?> cl2, Class<?> cl3) |
mixer | back to summary |
---|---|
private static MethodHandle mixer(Class<?> cl, Class<?> cl2, Class<?> cl3, Class<?> cl4) |
newArray | back to summary |
---|---|
private static MethodHandle newArray() |
newArrayWithSuffix | back to summary |
---|---|
private static MethodHandle newArrayWithSuffix(String suffix) |
newString | back to summary |
---|---|
private static MethodHandle newString() |
newStringifier | back to summary |
---|---|
private static MethodHandle newStringifier() |
noPrefixPrepender | back to summary |
---|---|
private static MethodHandle noPrefixPrepender(Class<?> cl) |
objectStringifier | back to summary |
---|---|
private static MethodHandle objectStringifier() |
parseRecipe | back to summary |
---|---|
private static String[] parseRecipe(MethodType concatType, String recipe, Object[] constants) throws StringConcatException |
prependBase | back to summary |
---|---|
private static MethodHandle prependBase() |
prepender | back to summary |
---|---|
private static MethodHandle prepender(String prefix, Class<?> cl) |
prepender | back to summary |
---|---|
private static MethodHandle prepender(Class<?> cl) |
prepender | back to summary |
---|---|
private static MethodHandle prepender(String prefix, Class<?> cl, String prefix2, Class<?> cl2) |
prepender | back to summary |
---|---|
private static MethodHandle prepender(int pos, String[] constants, Class<?>[] ptypes, int count) |
promoteToIntType | back to summary |
---|---|
private static Class Promote integral types to int. |
simpleConcat | back to summary |
---|---|
private static MethodHandle simpleConcat() |
stringifierFor | back to summary |
---|---|
private static MethodHandle stringifierFor(Class<?> t) Returns a stringifier for references and floats/doubles only. Always returns null for other primitives.
|
stringValueOf | back to summary |
---|---|
private static MethodHandle stringValueOf(Class<?> ptype) |
unaryConcat | back to summary |
---|---|
private static MethodHandle unaryConcat(Class<?> cl) |
This strategy emits StringBuilder chains as similar as possible to what javac would. No exact sizing of parameters or estimates.
Modifier and Type | Field and Description |
---|---|
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 int | ARGUMENT_SIZE_FACTOR
Ensure a capacity in the initial StringBuilder to accommodate all constants plus this factor times the number of arguments. |
pack-priv static final ClassFileDumper | |
pack-priv static final MethodTypeDesc | |
pack-priv static final String | |
pack-priv static final Set | |
pack-priv static final ClassDesc | |
pack-priv static final MethodTypeDesc |
Access | Constructor and Description |
---|---|
private |
Modifier and Type | Method and Description |
---|---|
private static MethodHandle | |
private static Consumer | |
private static String | getClassName(Class<?> hostClass)
The generated class is in the same package as the host class as it's the implementation of the string concatenation for the host class. |
private static MethodTypeDesc |
APPEND_BOOLEAN_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_BOOLEAN_TYPE |
APPEND_CHAR_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_CHAR_TYPE |
APPEND_DOUBLE_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_DOUBLE_TYPE |
APPEND_FLOAT_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_FLOAT_TYPE |
APPEND_INT_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_INT_TYPE |
APPEND_LONG_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_LONG_TYPE |
APPEND_OBJECT_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_OBJECT_TYPE |
APPEND_STRING_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc APPEND_STRING_TYPE |
ARGUMENT_SIZE_FACTOR | back to summary |
---|---|
pack-priv static final int ARGUMENT_SIZE_FACTOR Ensure a capacity in the initial StringBuilder to accommodate all constants plus this factor times the number of arguments. |
DUMPER | back to summary |
---|---|
pack-priv static final ClassFileDumper DUMPER |
INT_CONSTRUCTOR_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc INT_CONSTRUCTOR_TYPE |
METHOD_NAME | back to summary |
---|---|
pack-priv static final String METHOD_NAME |
SET_OF_STRONG | back to summary |
---|---|
pack-priv static final Set<MethodHandles. |
STRING_BUILDER | back to summary |
---|---|
pack-priv static final ClassDesc STRING_BUILDER |
TO_STRING_TYPE | back to summary |
---|---|
pack-priv static final MethodTypeDesc TO_STRING_TYPE |
SimpleStringBuilderStrategy | back to summary |
---|---|
private SimpleStringBuilderStrategy() |
generate | back to summary |
---|---|
private static MethodHandle generate(MethodHandles. |
generateMethod | back to summary |
---|---|
private static Consumer |
getClassName | back to summary |
---|---|
private static String getClassName(Class<?> hostClass) The generated class is in the same package as the host class as it's the implementation of the string concatenation for the host class. |
getSBAppendDesc | back to summary |
---|---|
private static MethodTypeDesc getSBAppendDesc(Class<?> cl) |