/* * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang.invoke; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.vm.annotation.Stable; import sun.invoke.util.Wrapper; import java.lang.invoke.MethodHandles.Lookup; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; import static java.lang.invoke.MethodType.methodType; /** *
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 {@code * invokedynamic} call sites, to support the string concatenation * feature of the Java Programming Language. * *
Indirect access to the behavior specified by the provided {@code * MethodHandle} proceeds in order through two phases: * *
This class provides two forms of linkage methods: a simple version * ({@link #makeConcat(java.lang.invoke.MethodHandles.Lookup, String, * MethodType)}) using only the dynamic arguments, and an advanced version * ({@link #makeConcatWithConstants(java.lang.invoke.MethodHandles.Lookup, * String, MethodType, String, Object...)} 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. * * @author Aleksey Shipilev * @author Remi Forax * @author Peter Levart * * @apiNote *
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 {@code 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. * * @since 9 */ public final class StringConcatFactory { /** * Tag used to demarcate an ordinary argument. */ private static final char TAG_ARG = '\u0001'; /** * Tag used to demarcate a constant. */ private static final char TAG_CONST = '\u0002'; /** * 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. */ private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200; private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); // StringConcatFactory bootstrap methods are startup sensitive, and may be // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure // methods are invoked with exact type information to avoid generating // code for runtime checks. Take care any changes or additions here are // reflected there as appropriate. /** * 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 {@code * invokedynamic} call sites, to support the string concatenation * feature of the Java Programming Language. * *
When the target of the {@code CallSite} returned from this method is * invoked, it returns the result of String concatenation, taking all * function arguments passed to the linkage method as inputs for * concatenation. The target signature is given by {@code concatType}. * For a target accepting: *
Assume the linkage arguments are as follows: * *
Then the following linkage invariants must hold: * *
When the target of the {@code CallSite} returned from this method is * invoked, it returns the result of String concatenation, taking all * function arguments and constants passed to the linkage method as inputs for * concatenation. The target signature is given by {@code concatType}, and * does not include constants. * For a target accepting: *
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: * *
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.
*/
private static MethodHandle generateMHInlineCopy(MethodType mt, List