src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
author mchung
Tue, 29 Oct 2019 12:52:03 -0700
changeset 58849 67a3f50b14ae
parent 54791 04f603ebb6c2
permissions -rw-r--r--
8173975: Lookup::in should not allow target class be primitive or array class Reviewed-by: alanb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     1
/*
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
     2
 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     4
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    10
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    15
 * accompanied this code).
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    16
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    20
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    23
 * questions.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    24
 */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    25
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    26
package java.lang.invoke;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    27
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
    28
import jdk.internal.misc.Unsafe;
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
    29
import jdk.internal.misc.VM;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    30
import jdk.internal.org.objectweb.asm.ClassWriter;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    31
import jdk.internal.org.objectweb.asm.Label;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    32
import jdk.internal.org.objectweb.asm.MethodVisitor;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    33
import jdk.internal.org.objectweb.asm.Opcodes;
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
    34
import sun.invoke.util.Wrapper;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    35
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    36
import java.lang.invoke.MethodHandles.Lookup;
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
    37
import java.util.ArrayList;
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
    38
import java.util.Arrays;
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
    39
import java.util.List;
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
    40
import java.util.Objects;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    41
import java.util.concurrent.ConcurrentHashMap;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    42
import java.util.concurrent.ConcurrentMap;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    43
import java.util.function.Function;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    44
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    45
import static jdk.internal.org.objectweb.asm.Opcodes.*;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    46
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    47
/**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    48
 * <p>Methods to facilitate the creation of String concatenation methods, that
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    49
 * can be used to efficiently concatenate a known number of arguments of known
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    50
 * types, possibly after type adaptation and partial evaluation of arguments.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    51
 * These methods are typically used as <em>bootstrap methods</em> for {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    52
 * invokedynamic} call sites, to support the <em>string concatenation</em>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    53
 * feature of the Java Programming Language.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    54
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    55
 * <p>Indirect access to the behavior specified by the provided {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    56
 * MethodHandle} proceeds in order through two phases:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    57
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    58
 * <ol>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    59
 *     <li><em>Linkage</em> occurs when the methods in this class are invoked.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    60
 * They take as arguments a method type describing the concatenated arguments
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    61
 * count and types, and optionally the String <em>recipe</em>, plus the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    62
 * constants that participate in the String concatenation. The details on
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    63
 * accepted recipe shapes are described further below. Linkage may involve
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    64
 * dynamically loading a new class that implements the expected concatenation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    65
 * behavior. The {@code CallSite} holds the {@code MethodHandle} pointing to the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    66
 * exact concatenation method. The concatenation methods may be shared among
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    67
 * different {@code CallSite}s, e.g. if linkage methods produce them as pure
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    68
 * functions.</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    69
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    70
 * <li><em>Invocation</em> occurs when a generated concatenation method is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    71
 * invoked with the exact dynamic arguments. This may occur many times for a
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    72
 * single concatenation method. The method referenced by the behavior {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    73
 * MethodHandle} is invoked with the static arguments and any additional dynamic
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    74
 * arguments provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    75
 * </ol>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    76
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    77
 * <p> This class provides two forms of linkage methods: a simple version
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    78
 * ({@link #makeConcat(java.lang.invoke.MethodHandles.Lookup, String,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    79
 * MethodType)}) using only the dynamic arguments, and an advanced version
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    80
 * ({@link #makeConcatWithConstants(java.lang.invoke.MethodHandles.Lookup,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    81
 * String, MethodType, String, Object...)} using the advanced forms of capturing
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    82
 * the constant arguments. The advanced strategy can produce marginally better
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    83
 * invocation bytecode, at the expense of exploding the number of shapes of
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    84
 * string concatenation methods present at runtime, because those shapes would
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    85
 * include constant static arguments as well.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    86
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    87
 * @author Aleksey Shipilev
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    88
 * @author Remi Forax
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    89
 * @author Peter Levart
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    90
 *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    91
 * @apiNote
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    92
 * <p>There is a JVM limit (classfile structural constraint): no method
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    93
 * can call with more than 255 slots. This limits the number of static and
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    94
 * dynamic arguments one can pass to bootstrap method. Since there are potential
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    95
 * concatenation strategies that use {@code MethodHandle} combinators, we need
36441
f40a48b83f57 8151063: Typo in java.lang.invoke.StringConcatFactory javadoc
rriggs
parents: 36001
diff changeset
    96
 * to reserve a few empty slots on the parameter lists to capture the
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    97
 * temporal results. This is why bootstrap methods in this factory do not accept
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    98
 * more than 200 argument slots. Users requiring more than 200 argument slots in
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    99
 * concatenation are expected to split the large concatenation in smaller
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   100
 * expressions.
35401
f57a51dbcc50 8148730: Add @since tags in new String concat APIs
shade
parents: 35388
diff changeset
   101
 *
f57a51dbcc50 8148730: Add @since tags in new String concat APIs
shade
parents: 35388
diff changeset
   102
 * @since 9
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   103
 */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   104
public final class StringConcatFactory {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   105
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   106
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   107
     * Tag used to demarcate an ordinary argument.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   108
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   109
    private static final char TAG_ARG = '\u0001';
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   110
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   111
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   112
     * Tag used to demarcate a constant.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   113
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   114
    private static final char TAG_CONST = '\u0002';
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   115
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   116
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   117
     * Maximum number of argument slots in String Concat call.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   118
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   119
     * While the maximum number of argument slots that indy call can handle is 253,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   120
     * we do not use all those slots, to let the strategies with MethodHandle
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   121
     * combinators to use some arguments.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   122
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   123
    private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   124
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   125
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   126
     * Concatenation strategy to use. See {@link Strategy} for possible options.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   127
     * This option is controllable with -Djava.lang.invoke.stringConcat JDK option.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   128
     */
37684
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   129
    private static Strategy STRATEGY;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   130
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   131
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   132
     * Default strategy to use for concatenation.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   133
     */
38428
0079e7d659db 8148604: JEP 280, Switch to more optimal concatenation strategy
shade
parents: 37781
diff changeset
   134
    private static final Strategy DEFAULT_STRATEGY = Strategy.MH_INLINE_SIZED_EXACT;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   135
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   136
    private enum Strategy {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   137
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   138
         * Bytecode generator, calling into {@link java.lang.StringBuilder}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   139
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   140
        BC_SB,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   141
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   142
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   143
         * Bytecode generator, calling into {@link java.lang.StringBuilder};
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   144
         * but trying to estimate the required storage.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   145
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   146
        BC_SB_SIZED,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   147
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   148
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   149
         * Bytecode generator, calling into {@link java.lang.StringBuilder};
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   150
         * but computing the required storage exactly.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   151
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   152
        BC_SB_SIZED_EXACT,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   153
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   154
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   155
         * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   156
         * This strategy also tries to estimate the required storage.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   157
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   158
        MH_SB_SIZED,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   159
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   160
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   161
         * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   162
         * This strategy also estimate the required storage exactly.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   163
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   164
        MH_SB_SIZED_EXACT,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   165
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   166
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   167
         * MethodHandle-based generator, that constructs its own byte[] array from
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   168
         * the arguments. It computes the required storage exactly.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   169
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   170
        MH_INLINE_SIZED_EXACT
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   171
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   172
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   173
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   174
     * Enables debugging: this may print debugging messages, perform additional (non-neutral for performance)
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   175
     * checks, etc.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   176
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   177
    private static final boolean DEBUG;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   178
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   179
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   180
     * Enables caching of strategy stubs. This may improve the linkage time by reusing the generated
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   181
     * code, at the expense of contaminating the profiles.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   182
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   183
    private static final boolean CACHE_ENABLE;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   184
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   185
    private static final ConcurrentMap<Key, MethodHandle> CACHE;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   186
35776
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   187
    /**
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   188
     * Dump generated classes to disk, for debugging purposes.
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   189
     */
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   190
    private static final ProxyClassesDumper DUMPER;
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   191
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   192
    private static final Class<?> STRING_HELPER;
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   193
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   194
    static {
37684
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   195
        // In case we need to double-back onto the StringConcatFactory during this
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   196
        // static initialization, make sure we have the reasonable defaults to complete
47478
438e0c9f2f17 8190382: fix small typographic errors in comments
smarks
parents: 47471
diff changeset
   197
        // the static initialization properly. After that, actual users would use
47471
304ef03403b1 8190323: "the the" typos
rriggs
parents: 47461
diff changeset
   198
        // the proper values we have read from the properties.
37684
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   199
        STRATEGY = DEFAULT_STRATEGY;
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   200
        // CACHE_ENABLE = false; // implied
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   201
        // CACHE = null;         // implied
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   202
        // DEBUG = false;        // implied
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   203
        // DUMPER = null;        // implied
38b7cb606a05 8155090: String concatenation fails with a custom SecurityManager that uses concatenation
shade
parents: 37593
diff changeset
   204
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   205
        try {
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   206
            STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   207
        } catch (Throwable e) {
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   208
            throw new AssertionError(e);
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   209
        }
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   210
37593
824750ada3d6 8154231: Simplify access to System properties from JDK code
redestad
parents: 37332
diff changeset
   211
        final String strategy =
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   212
                VM.getSavedProperty("java.lang.invoke.stringConcat");
37593
824750ada3d6 8154231: Simplify access to System properties from JDK code
redestad
parents: 37332
diff changeset
   213
        CACHE_ENABLE = Boolean.parseBoolean(
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   214
                VM.getSavedProperty("java.lang.invoke.stringConcat.cache"));
37593
824750ada3d6 8154231: Simplify access to System properties from JDK code
redestad
parents: 37332
diff changeset
   215
        DEBUG = Boolean.parseBoolean(
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   216
                VM.getSavedProperty("java.lang.invoke.stringConcat.debug"));
37593
824750ada3d6 8154231: Simplify access to System properties from JDK code
redestad
parents: 37332
diff changeset
   217
        final String dumpPath =
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
   218
                VM.getSavedProperty("java.lang.invoke.stringConcat.dumpClasses");
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   219
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   220
        STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   221
        CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
35776
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   222
        DUMPER = (dumpPath == null) ? null : ProxyClassesDumper.getInstance(dumpPath);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   223
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   224
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   225
    /**
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   226
     * Cache key is a composite of:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   227
     *   - class name, that lets to disambiguate stubs, to avoid excess sharing
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   228
     *   - method type, describing the dynamic arguments for concatenation
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   229
     *   - concat recipe, describing the constants and concat shape
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   230
     */
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   231
    private static final class Key {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   232
        final String className;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   233
        final MethodType mt;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   234
        final Recipe recipe;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   235
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   236
        public Key(String className, MethodType mt, Recipe recipe) {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   237
            this.className = className;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   238
            this.mt = mt;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   239
            this.recipe = recipe;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   240
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   241
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   242
        @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   243
        public boolean equals(Object o) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   244
            if (this == o) return true;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   245
            if (o == null || getClass() != o.getClass()) return false;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   246
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   247
            Key key = (Key) o;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   248
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   249
            if (!className.equals(key.className)) return false;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   250
            if (!mt.equals(key.mt)) return false;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   251
            if (!recipe.equals(key.recipe)) return false;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   252
            return true;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   253
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   254
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   255
        @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   256
        public int hashCode() {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   257
            int result = className.hashCode();
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   258
            result = 31 * result + mt.hashCode();
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   259
            result = 31 * result + recipe.hashCode();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   260
            return result;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   261
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   262
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   263
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   264
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   265
     * Parses the recipe string, and produces the traversable collection of
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   266
     * {@link java.lang.invoke.StringConcatFactory.RecipeElement}-s for generator
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   267
     * strategies. Notably, this class parses out the constants from the recipe
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   268
     * and from other static arguments.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   269
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   270
    private static final class Recipe {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   271
        private final List<RecipeElement> elements;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   272
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   273
        public Recipe(String src, Object[] constants) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   274
            List<RecipeElement> el = new ArrayList<>();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   275
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   276
            int constC = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   277
            int argC = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   278
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   279
            StringBuilder acc = new StringBuilder();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   280
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   281
            for (int i = 0; i < src.length(); i++) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   282
                char c = src.charAt(i);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   283
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   284
                if (c == TAG_CONST || c == TAG_ARG) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   285
                    // Detected a special tag, flush all accumulated characters
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   286
                    // as a constant first:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   287
                    if (acc.length() > 0) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   288
                        el.add(new RecipeElement(acc.toString()));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   289
                        acc.setLength(0);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   290
                    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   291
                    if (c == TAG_CONST) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   292
                        Object cnst = constants[constC++];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   293
                        el.add(new RecipeElement(cnst));
40256
c5e03eaf7ba2 8163370: Reduce number of classes loaded by common usage of java.lang.invoke
redestad
parents: 38868
diff changeset
   294
                    } else if (c == TAG_ARG) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   295
                        el.add(new RecipeElement(argC++));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   296
                    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   297
                } else {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   298
                    // Not a special character, this is a constant embedded into
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   299
                    // the recipe itself.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   300
                    acc.append(c);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   301
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   302
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   303
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   304
            // Flush the remaining characters as constant:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   305
            if (acc.length() > 0) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   306
                el.add(new RecipeElement(acc.toString()));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   307
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   308
36737
67b2804be5ab 8152951: Avoid calculating the reverse of StringConcatFactory$Recipe elements
redestad
parents: 36668
diff changeset
   309
            elements = el;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   310
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   311
36737
67b2804be5ab 8152951: Avoid calculating the reverse of StringConcatFactory$Recipe elements
redestad
parents: 36668
diff changeset
   312
        public List<RecipeElement> getElements() {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   313
            return elements;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   314
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   315
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   316
        @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   317
        public boolean equals(Object o) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   318
            if (this == o) return true;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   319
            if (o == null || getClass() != o.getClass()) return false;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   320
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   321
            Recipe recipe = (Recipe) o;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   322
            return elements.equals(recipe.elements);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   323
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   324
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   325
        @Override
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   326
        public String toString() {
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   327
            return "Recipe{" +
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   328
                    "elements=" + elements +
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   329
                    '}';
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   330
        }
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   331
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   332
        @Override
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   333
        public int hashCode() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   334
            return elements.hashCode();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   335
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   336
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   337
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   338
    private static final class RecipeElement {
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
   339
        private final String value;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   340
        private final int argPos;
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   341
        private final char tag;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   342
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   343
        public RecipeElement(Object cnst) {
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
   344
            this.value = String.valueOf(Objects.requireNonNull(cnst));
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   345
            this.argPos = -1;
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   346
            this.tag = TAG_CONST;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   347
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   348
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   349
        public RecipeElement(int arg) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   350
            this.value = null;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   351
            this.argPos = arg;
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   352
            this.tag = TAG_ARG;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   353
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   354
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
   355
        public String getValue() {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   356
            assert (tag == TAG_CONST);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   357
            return value;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   358
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   359
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   360
        public int getArgPos() {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   361
            assert (tag == TAG_ARG);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   362
            return argPos;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   363
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   364
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   365
        public char getTag() {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   366
            return tag;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   367
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   368
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   369
        @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   370
        public boolean equals(Object o) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   371
            if (this == o) return true;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   372
            if (o == null || getClass() != o.getClass()) return false;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   373
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   374
            RecipeElement that = (RecipeElement) o;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   375
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   376
            if (this.tag != that.tag) return false;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   377
            if (this.tag == TAG_CONST && (!value.equals(that.value))) return false;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   378
            if (this.tag == TAG_ARG && (argPos != that.argPos)) return false;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   379
            return true;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   380
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   381
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   382
        @Override
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   383
        public String toString() {
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   384
            return "RecipeElement{" +
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   385
                    "value='" + value + '\'' +
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   386
                    ", argPos=" + argPos +
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   387
                    ", tag=" + tag +
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   388
                    '}';
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   389
        }
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   390
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
   391
        @Override
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   392
        public int hashCode() {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   393
            return (int)tag;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   394
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   395
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   396
48930
b1a5b4ad7427 8198523: Refactor BootstrapMethodInvoker to further avoid runtime type checks
redestad
parents: 47985
diff changeset
   397
    // StringConcatFactory bootstrap methods are startup sensitive, and may be
b1a5b4ad7427 8198523: Refactor BootstrapMethodInvoker to further avoid runtime type checks
redestad
parents: 47985
diff changeset
   398
    // special cased in java.lang.invokeBootstrapMethodInvoker to ensure
b1a5b4ad7427 8198523: Refactor BootstrapMethodInvoker to further avoid runtime type checks
redestad
parents: 47985
diff changeset
   399
    // methods are invoked with exact type information to avoid generating
b1a5b4ad7427 8198523: Refactor BootstrapMethodInvoker to further avoid runtime type checks
redestad
parents: 47985
diff changeset
   400
    // code for runtime checks. Take care any changes or additions here are
b1a5b4ad7427 8198523: Refactor BootstrapMethodInvoker to further avoid runtime type checks
redestad
parents: 47985
diff changeset
   401
    // reflected there as appropriate.
b1a5b4ad7427 8198523: Refactor BootstrapMethodInvoker to further avoid runtime type checks
redestad
parents: 47985
diff changeset
   402
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   403
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   404
     * Facilitates the creation of optimized String concatenation methods, that
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   405
     * can be used to efficiently concatenate a known number of arguments of
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   406
     * known types, possibly after type adaptation and partial evaluation of
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   407
     * arguments. Typically used as a <em>bootstrap method</em> for {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   408
     * invokedynamic} call sites, to support the <em>string concatenation</em>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   409
     * feature of the Java Programming Language.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   410
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   411
     * <p>When the target of the {@code CallSite} returned from this method is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   412
     * invoked, it returns the result of String concatenation, taking all
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   413
     * function arguments passed to the linkage method as inputs for
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   414
     * concatenation. The target signature is given by {@code concatType}.
47985
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   415
     * For a target accepting:
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   416
     * <ul>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   417
     *     <li>zero inputs, concatenation results in an empty string;</li>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   418
     *     <li>one input, concatenation results in the single
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   419
     *     input converted as per JLS 5.1.11 "String Conversion"; otherwise</li>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   420
     *     <li>two or more inputs, the inputs are concatenated as per
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   421
     *     requirements stated in JLS 15.18.1 "String Concatenation Operator +".
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   422
     *     The inputs are converted as per JLS 5.1.11 "String Conversion",
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   423
     *     and combined from left to right.</li>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   424
     * </ul>
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   425
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   426
     * <p>Assume the linkage arguments are as follows:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   427
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   428
     * <ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   429
     *     <li>{@code concatType}, describing the {@code CallSite} signature</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   430
     * </ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   431
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   432
     * <p>Then the following linkage invariants must hold:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   433
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   434
     * <ul>
47461
60a5d9c77c4c 8187089: StringConcatFactory.makeConcat & makeConcatWithConstants should throw StringConcatException if parameter slot count is over 200
mchung
parents: 47216
diff changeset
   435
     *     <li>The number of parameter slots in {@code concatType} is
60a5d9c77c4c 8187089: StringConcatFactory.makeConcat & makeConcatWithConstants should throw StringConcatException if parameter slot count is over 200
mchung
parents: 47216
diff changeset
   436
     *         less than or equal to 200</li>
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   437
     *     <li>The return type in {@code concatType} is assignable from {@link java.lang.String}</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   438
     * </ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   439
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   440
     * @param lookup   Represents a lookup context with the accessibility
47985
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   441
     *                 privileges of the caller. Specifically, the lookup
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   442
     *                 context must have
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   443
     *                 <a href="MethodHandles.Lookup.html#privacc">private access</a>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   444
     *                 privileges.
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   445
     *                 When used with {@code invokedynamic}, this is stacked
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   446
     *                 automatically by the VM.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   447
     * @param name     The name of the method to implement. This name is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   448
     *                 arbitrary, and has no meaning for this linkage method.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   449
     *                 When used with {@code invokedynamic}, this is provided by
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   450
     *                 the {@code NameAndType} of the {@code InvokeDynamic}
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   451
     *                 structure and is stacked automatically by the VM.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   452
     * @param concatType The expected signature of the {@code CallSite}.  The
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   453
     *                   parameter types represent the types of concatenation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   454
     *                   arguments; the return type is always assignable from {@link
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   455
     *                   java.lang.String}.  When used with {@code invokedynamic},
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   456
     *                   this is provided by the {@code NameAndType} of the {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   457
     *                   InvokeDynamic} structure and is stacked automatically by
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   458
     *                   the VM.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   459
     * @return a CallSite whose target can be used to perform String
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   460
     * concatenation, with dynamic concatenation arguments described by the given
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   461
     * {@code concatType}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   462
     * @throws StringConcatException If any of the linkage invariants described
47985
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   463
     *                               here are violated, or the lookup context
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   464
     *                               does not have private access privileges.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   465
     * @throws NullPointerException If any of the incoming arguments is null.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   466
     *                              This will never happen when a bootstrap method
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   467
     *                              is called with invokedynamic.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   468
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   469
     * @jls  5.1.11 String Conversion
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   470
     * @jls 15.18.1 String Concatenation Operator +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   471
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   472
    public static CallSite makeConcat(MethodHandles.Lookup lookup,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   473
                                      String name,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   474
                                      MethodType concatType) throws StringConcatException {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   475
        if (DEBUG) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   476
            System.out.println("StringConcatFactory " + STRATEGY + " is here for " + concatType);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   477
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   478
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   479
        return doStringConcat(lookup, name, concatType, true, null);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   480
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   481
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   482
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   483
     * Facilitates the creation of optimized String concatenation methods, that
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   484
     * can be used to efficiently concatenate a known number of arguments of
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   485
     * known types, possibly after type adaptation and partial evaluation of
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   486
     * arguments. Typically used as a <em>bootstrap method</em> for {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   487
     * invokedynamic} call sites, to support the <em>string concatenation</em>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   488
     * feature of the Java Programming Language.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   489
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   490
     * <p>When the target of the {@code CallSite} returned from this method is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   491
     * invoked, it returns the result of String concatenation, taking all
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   492
     * function arguments and constants passed to the linkage method as inputs for
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   493
     * concatenation. The target signature is given by {@code concatType}, and
47985
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   494
     * does not include constants.
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   495
     * For a target accepting:
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   496
     * <ul>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   497
     *     <li>zero inputs, concatenation results in an empty string;</li>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   498
     *     <li>one input, concatenation results in the single
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   499
     *     input converted as per JLS 5.1.11 "String Conversion"; otherwise</li>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   500
     *     <li>two or more inputs, the inputs are concatenated as per
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   501
     *     requirements stated in JLS 15.18.1 "String Concatenation Operator +".
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   502
     *     The inputs are converted as per JLS 5.1.11 "String Conversion",
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   503
     *     and combined from left to right.</li>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   504
     * </ul>
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   505
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   506
     * <p>The concatenation <em>recipe</em> is a String description for the way to
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   507
     * construct a concatenated String from the arguments and constants. The
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   508
     * recipe is processed from left to right, and each character represents an
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   509
     * input to concatenation. Recipe characters mean:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   510
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   511
     * <ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   512
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   513
     *   <li><em>\1 (Unicode point 0001)</em>: an ordinary argument. This
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   514
     *   input is passed through dynamic argument, and is provided during the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   515
     *   concatenation method invocation. This input can be null.</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   516
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   517
     *   <li><em>\2 (Unicode point 0002):</em> a constant. This input passed
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   518
     *   through static bootstrap argument. This constant can be any value
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   519
     *   representable in constant pool. If necessary, the factory would call
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   520
     *   {@code toString} to perform a one-time String conversion.</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   521
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   522
     *   <li><em>Any other char value:</em> a single character constant.</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   523
     * </ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   524
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   525
     * <p>Assume the linkage arguments are as follows:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   526
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   527
     * <ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   528
     *   <li>{@code concatType}, describing the {@code CallSite} signature</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   529
     *   <li>{@code recipe}, describing the String recipe</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   530
     *   <li>{@code constants}, the vararg array of constants</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   531
     * </ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   532
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   533
     * <p>Then the following linkage invariants must hold:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   534
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   535
     * <ul>
47461
60a5d9c77c4c 8187089: StringConcatFactory.makeConcat & makeConcatWithConstants should throw StringConcatException if parameter slot count is over 200
mchung
parents: 47216
diff changeset
   536
     *   <li>The number of parameter slots in {@code concatType} is less than
60a5d9c77c4c 8187089: StringConcatFactory.makeConcat & makeConcatWithConstants should throw StringConcatException if parameter slot count is over 200
mchung
parents: 47216
diff changeset
   537
     *       or equal to 200</li>
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   538
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   539
     *   <li>The parameter count in {@code concatType} equals to number of \1 tags
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   540
     *   in {@code recipe}</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   541
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   542
     *   <li>The return type in {@code concatType} is assignable
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   543
     *   from {@link java.lang.String}, and matches the return type of the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   544
     *   returned {@link MethodHandle}</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   545
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   546
     *   <li>The number of elements in {@code constants} equals to number of \2
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   547
     *   tags in {@code recipe}</li>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   548
     * </ul>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   549
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   550
     * @param lookup    Represents a lookup context with the accessibility
47985
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   551
     *                  privileges of the caller. Specifically, the lookup
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   552
     *                  context must have
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   553
     *                  <a href="MethodHandles.Lookup.html#privacc">private access</a>
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   554
     *                  privileges.
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   555
     *                  When used with {@code invokedynamic}, this is stacked
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   556
     *                  automatically by the VM.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   557
     * @param name      The name of the method to implement. This name is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   558
     *                  arbitrary, and has no meaning for this linkage method.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   559
     *                  When used with {@code invokedynamic}, this is provided
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   560
     *                  by the {@code NameAndType} of the {@code InvokeDynamic}
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   561
     *                  structure and is stacked automatically by the VM.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   562
     * @param concatType The expected signature of the {@code CallSite}.  The
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   563
     *                  parameter types represent the types of dynamic concatenation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   564
     *                  arguments; the return type is always assignable from {@link
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   565
     *                  java.lang.String}.  When used with {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   566
     *                  invokedynamic}, this is provided by the {@code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   567
     *                  NameAndType} of the {@code InvokeDynamic} structure and
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   568
     *                  is stacked automatically by the VM.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   569
     * @param recipe    Concatenation recipe, described above.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   570
     * @param constants A vararg parameter representing the constants passed to
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   571
     *                  the linkage method.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   572
     * @return a CallSite whose target can be used to perform String
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   573
     * concatenation, with dynamic concatenation arguments described by the given
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   574
     * {@code concatType}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   575
     * @throws StringConcatException If any of the linkage invariants described
47985
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   576
     *                               here are violated, or the lookup context
80a058c0f993 8187237: Need to define the behaviour for 0 and 1 argument method type in StringConcatFactory.makeConcat
psandoz
parents: 47478
diff changeset
   577
     *                               does not have private access privileges.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   578
     * @throws NullPointerException If any of the incoming arguments is null, or
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   579
     *                              any constant in {@code recipe} is null.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   580
     *                              This will never happen when a bootstrap method
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   581
     *                              is called with invokedynamic.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   582
     * @apiNote Code generators have three distinct ways to process a constant
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   583
     * string operand S in a string concatenation expression.  First, S can be
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   584
     * materialized as a reference (using ldc) and passed as an ordinary argument
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   585
     * (recipe '\1'). Or, S can be stored in the constant pool and passed as a
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   586
     * constant (recipe '\2') . Finally, if S contains neither of the recipe
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   587
     * tag characters ('\1', '\2') then S can be interpolated into the recipe
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   588
     * itself, causing its characters to be inserted into the result.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   589
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   590
     * @jls  5.1.11 String Conversion
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   591
     * @jls 15.18.1 String Concatenation Operator +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   592
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   593
    public static CallSite makeConcatWithConstants(MethodHandles.Lookup lookup,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   594
                                                   String name,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   595
                                                   MethodType concatType,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   596
                                                   String recipe,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   597
                                                   Object... constants) throws StringConcatException {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   598
        if (DEBUG) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   599
            System.out.println("StringConcatFactory " + STRATEGY + " is here for " + concatType + ", {" + recipe + "}, " + Arrays.toString(constants));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   600
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   601
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   602
        return doStringConcat(lookup, name, concatType, false, recipe, constants);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   603
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   604
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   605
    private static CallSite doStringConcat(MethodHandles.Lookup lookup,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   606
                                           String name,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   607
                                           MethodType concatType,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   608
                                           boolean generateRecipe,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   609
                                           String recipe,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   610
                                           Object... constants) throws StringConcatException {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   611
        Objects.requireNonNull(lookup, "Lookup is null");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   612
        Objects.requireNonNull(name, "Name is null");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   613
        Objects.requireNonNull(concatType, "Concat type is null");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   614
        Objects.requireNonNull(constants, "Constants are null");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   615
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   616
        for (Object o : constants) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   617
            Objects.requireNonNull(o, "Cannot accept null constants");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   618
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   619
35776
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   620
        if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
   621
            throw new StringConcatException("Invalid caller: " +
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
   622
                    lookup.lookupClass().getName());
35776
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   623
        }
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
   624
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   625
        int cCount = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   626
        int oCount = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   627
        if (generateRecipe) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   628
            // Mock the recipe to reuse the concat generator code
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   629
            char[] value = new char[concatType.parameterCount()];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   630
            Arrays.fill(value, TAG_ARG);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   631
            recipe = new String(value);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   632
            oCount = concatType.parameterCount();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   633
        } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   634
            Objects.requireNonNull(recipe, "Recipe is null");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   635
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   636
            for (int i = 0; i < recipe.length(); i++) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   637
                char c = recipe.charAt(i);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   638
                if (c == TAG_CONST) cCount++;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   639
                if (c == TAG_ARG)   oCount++;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   640
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   641
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   642
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   643
        if (oCount != concatType.parameterCount()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   644
            throw new StringConcatException(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   645
                    "Mismatched number of concat arguments: recipe wants " +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   646
                            oCount +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   647
                            " arguments, but signature provides " +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   648
                            concatType.parameterCount());
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   649
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   650
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   651
        if (cCount != constants.length) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   652
            throw new StringConcatException(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   653
                    "Mismatched number of concat constants: recipe wants " +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   654
                            cCount +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   655
                            " constants, but only " +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   656
                            constants.length +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   657
                            " are passed");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   658
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   659
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   660
        if (!concatType.returnType().isAssignableFrom(String.class)) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   661
            throw new StringConcatException(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   662
                    "The return type should be compatible with String, but it is " +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   663
                            concatType.returnType());
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   664
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   665
47461
60a5d9c77c4c 8187089: StringConcatFactory.makeConcat & makeConcatWithConstants should throw StringConcatException if parameter slot count is over 200
mchung
parents: 47216
diff changeset
   666
        if (concatType.parameterSlotCount() > MAX_INDY_CONCAT_ARG_SLOTS) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   667
            throw new StringConcatException("Too many concat argument slots: " +
47461
60a5d9c77c4c 8187089: StringConcatFactory.makeConcat & makeConcatWithConstants should throw StringConcatException if parameter slot count is over 200
mchung
parents: 47216
diff changeset
   668
                    concatType.parameterSlotCount() +
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   669
                    ", can only accept " +
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   670
                    MAX_INDY_CONCAT_ARG_SLOTS);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   671
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   672
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   673
        String className = getClassName(lookup.lookupClass());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   674
        MethodType mt = adaptType(concatType);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   675
        Recipe rec = new Recipe(recipe, constants);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   676
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   677
        MethodHandle mh;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   678
        if (CACHE_ENABLE) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   679
            Key key = new Key(className, mt, rec);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   680
            mh = CACHE.get(key);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   681
            if (mh == null) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   682
                mh = generate(lookup, className, mt, rec);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   683
                CACHE.put(key, mh);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   684
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   685
        } else {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   686
            mh = generate(lookup, className, mt, rec);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   687
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   688
        return new ConstantCallSite(mh.asType(concatType));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   689
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   690
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   691
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   692
     * Adapt method type to an API we are going to use.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   693
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   694
     * This strips the concrete classes from the signatures, thus preventing
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   695
     * class leakage when we cache the concatenation stubs.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   696
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   697
     * @param args actual argument types
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   698
     * @return argument types the strategy is going to use
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   699
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   700
    private static MethodType adaptType(MethodType args) {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   701
        Class<?>[] ptypes = null;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   702
        for (int i = 0; i < args.parameterCount(); i++) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   703
            Class<?> ptype = args.parameterType(i);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   704
            if (!ptype.isPrimitive() &&
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   705
                    ptype != String.class &&
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   706
                    ptype != Object.class) { // truncate to Object
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   707
                if (ptypes == null) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   708
                    ptypes = args.parameterArray();
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   709
                }
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   710
                ptypes[i] = Object.class;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   711
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   712
            // else other primitives or String or Object (unchanged)
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   713
        }
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   714
        return (ptypes != null)
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   715
                ? MethodType.methodType(args.returnType(), ptypes)
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   716
                : args;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   717
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   718
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   719
    private static String getClassName(Class<?> hostClass) throws StringConcatException {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   720
        /*
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   721
          When cache is enabled, we want to cache as much as we can.
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   722
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   723
          However, there are two peculiarities:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   724
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   725
           a) The generated class should stay within the same package as the
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   726
              host class, to allow Unsafe.defineAnonymousClass access controls
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   727
              to work properly. JDK may choose to fail with IllegalAccessException
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   728
              when accessing a VM anonymous class with non-privileged callers,
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   729
              see JDK-8058575.
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   730
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   731
           b) If we mark the stub with some prefix, say, derived from the package
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   732
              name because of (a), we can technically use that stub in other packages.
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   733
              But the call stack traces would be extremely puzzling to unsuspecting users
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   734
              and profiling tools: whatever stub wins the race, would be linked in all
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   735
              similar callsites.
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   736
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   737
           Therefore, we set the class prefix to match the host class package, and use
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   738
           the prefix as the cache key too. This only affects BC_* strategies, and only when
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   739
           cache is enabled.
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   740
         */
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   741
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   742
        switch (STRATEGY) {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   743
            case BC_SB:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   744
            case BC_SB_SIZED:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   745
            case BC_SB_SIZED_EXACT: {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   746
                if (CACHE_ENABLE) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 36441
diff changeset
   747
                    String pkgName = hostClass.getPackageName();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 36441
diff changeset
   748
                    return (pkgName != null && !pkgName.isEmpty() ? pkgName.replace('.', '/') + "/" : "") + "Stubs$$StringConcat";
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   749
                } else {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   750
                    return hostClass.getName().replace('.', '/') + "$$StringConcat";
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   751
                }
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   752
            }
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   753
            case MH_SB_SIZED:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   754
            case MH_SB_SIZED_EXACT:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   755
            case MH_INLINE_SIZED_EXACT:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   756
                // MethodHandle strategies do not need a class name.
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   757
                return "";
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   758
            default:
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   759
                throw new StringConcatException("Concatenation strategy " + STRATEGY + " is not implemented");
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   760
        }
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   761
    }
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   762
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   763
    private static MethodHandle generate(Lookup lookup, String className, MethodType mt, Recipe recipe) throws StringConcatException {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   764
        try {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   765
            switch (STRATEGY) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   766
                case BC_SB:
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   767
                    return BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, Mode.DEFAULT);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   768
                case BC_SB_SIZED:
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   769
                    return BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, Mode.SIZED);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   770
                case BC_SB_SIZED_EXACT:
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   771
                    return BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, Mode.SIZED_EXACT);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   772
                case MH_SB_SIZED:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   773
                    return MethodHandleStringBuilderStrategy.generate(mt, recipe, Mode.SIZED);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   774
                case MH_SB_SIZED_EXACT:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   775
                    return MethodHandleStringBuilderStrategy.generate(mt, recipe, Mode.SIZED_EXACT);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   776
                case MH_INLINE_SIZED_EXACT:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   777
                    return MethodHandleInlineCopyStrategy.generate(mt, recipe);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   778
                default:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   779
                    throw new StringConcatException("Concatenation strategy " + STRATEGY + " is not implemented");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   780
            }
42105
d04ede5f10e7 8163553: java.lang.LinkageError from test java/lang/ThreadGroup/Stop.java
psandoz
parents: 40810
diff changeset
   781
        } catch (Error | StringConcatException e) {
d04ede5f10e7 8163553: java.lang.LinkageError from test java/lang/ThreadGroup/Stop.java
psandoz
parents: 40810
diff changeset
   782
            // Pass through any error or existing StringConcatException
d04ede5f10e7 8163553: java.lang.LinkageError from test java/lang/ThreadGroup/Stop.java
psandoz
parents: 40810
diff changeset
   783
            throw e;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   784
        } catch (Throwable t) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   785
            throw new StringConcatException("Generator failed", t);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   786
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   787
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   788
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   789
    private enum Mode {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   790
        DEFAULT(false, false),
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   791
        SIZED(true, false),
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   792
        SIZED_EXACT(true, true);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   793
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   794
        private final boolean sized;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   795
        private final boolean exact;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   796
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   797
        Mode(boolean sized, boolean exact) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   798
            this.sized = sized;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   799
            this.exact = exact;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   800
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   801
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   802
        boolean isSized() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   803
            return sized;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   804
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   805
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   806
        boolean isExact() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   807
            return exact;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   808
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   809
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   810
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   811
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   812
     * Bytecode StringBuilder strategy.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   813
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   814
     * <p>This strategy operates in three modes, gated by {@link Mode}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   815
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   816
     * <p><b>{@link Strategy#BC_SB}: "bytecode StringBuilder".</b>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   817
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   818
     * <p>This strategy spins up the bytecode that has the same StringBuilder
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   819
     * chain javac would otherwise emit. This strategy uses only the public API,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   820
     * and comes as the baseline for the current JDK behavior. On other words,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   821
     * this strategy moves the javac generated bytecode to runtime. The
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   822
     * generated bytecode is loaded via Unsafe.defineAnonymousClass, but with
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   823
     * the caller class coming from the BSM -- in other words, the protection
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   824
     * guarantees are inherited from the method where invokedynamic was
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   825
     * originally called. This means, among other things, that the bytecode is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   826
     * verified for all non-JDK uses.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   827
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   828
     * <p><b>{@link Strategy#BC_SB_SIZED}: "bytecode StringBuilder, but
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   829
     * sized".</b>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   830
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   831
     * <p>This strategy acts similarly to {@link Strategy#BC_SB}, but it also
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   832
     * tries to guess the capacity required for StringBuilder to accept all
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   833
     * arguments without resizing. This strategy only makes an educated guess:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   834
     * it only guesses the space required for known types (e.g. primitives and
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   835
     * Strings), but does not otherwise convert arguments. Therefore, the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   836
     * capacity estimate may be wrong, and StringBuilder may have to
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   837
     * transparently resize or trim when doing the actual concatenation. While
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   838
     * this does not constitute a correctness issue (in the end, that what BC_SB
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   839
     * has to do anyway), this does pose a potential performance problem.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   840
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   841
     * <p><b>{@link Strategy#BC_SB_SIZED_EXACT}: "bytecode StringBuilder, but
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   842
     * sized exactly".</b>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   843
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   844
     * <p>This strategy improves on @link Strategy#BC_SB_SIZED}, by first
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   845
     * converting all arguments to String in order to get the exact capacity
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   846
     * StringBuilder should have. The conversion is done via the public
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   847
     * String.valueOf and/or Object.toString methods, and does not touch any
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   848
     * private String API.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   849
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   850
    private static final class BytecodeStringBuilderStrategy {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   851
        static final Unsafe UNSAFE = Unsafe.getUnsafe();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   852
        static final int CLASSFILE_VERSION = 52;
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   853
        static final String METHOD_NAME = "concat";
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   854
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   855
        private BytecodeStringBuilderStrategy() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   856
            // no instantiation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   857
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   858
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   859
        private static MethodHandle generate(Lookup lookup, String className, MethodType args, Recipe recipe, Mode mode) throws Exception {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   860
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   861
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   862
            cw.visit(CLASSFILE_VERSION,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   863
                    ACC_SUPER + ACC_PUBLIC + ACC_FINAL + ACC_SYNTHETIC,
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   864
                    className,  // Unsafe.defineAnonymousClass would append an unique ID
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   865
                    null,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   866
                    "java/lang/Object",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   867
                    null
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   868
            );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   869
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   870
            MethodVisitor mv = cw.visitMethod(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   871
                    ACC_PUBLIC + ACC_STATIC + ACC_FINAL,
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
   872
                    METHOD_NAME,
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   873
                    args.toMethodDescriptorString(),
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   874
                    null,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   875
                    null);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   876
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   877
            mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   878
            mv.visitCode();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   879
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   880
            Class<?>[] arr = args.parameterArray();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   881
            boolean[] guaranteedNonNull = new boolean[arr.length];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   882
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   883
            if (mode.isExact()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   884
                /*
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   885
                    In exact mode, we need to convert all arguments to their String representations,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   886
                    as this allows to compute their String sizes exactly. We cannot use private
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   887
                    methods for primitives in here, therefore we need to convert those as well.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   888
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   889
                    We also record what arguments are guaranteed to be non-null as the result
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   890
                    of the conversion. String.valueOf does the null checks for us. The only
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   891
                    corner case to take care of is String.valueOf(Object) returning null itself.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   892
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   893
                    Also, if any conversion happened, then the slot indices in the incoming
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   894
                    arguments are not equal to the final local maps. The only case this may break
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   895
                    is when converting 2-slot long/double argument to 1-slot String. Therefore,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   896
                    we get away with tracking modified offset, since no conversion can overwrite
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   897
                    the upcoming the argument.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   898
                 */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   899
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   900
                int off = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   901
                int modOff = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   902
                for (int c = 0; c < arr.length; c++) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   903
                    Class<?> cl = arr[c];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   904
                    if (cl == String.class) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   905
                        if (off != modOff) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   906
                            mv.visitIntInsn(getLoadOpcode(cl), off);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   907
                            mv.visitIntInsn(ASTORE, modOff);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   908
                        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   909
                    } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   910
                        mv.visitIntInsn(getLoadOpcode(cl), off);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   911
                        mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   912
                                INVOKESTATIC,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   913
                                "java/lang/String",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   914
                                "valueOf",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   915
                                getStringValueOfDesc(cl),
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   916
                                false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   917
                        );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   918
                        mv.visitIntInsn(ASTORE, modOff);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   919
                        arr[c] = String.class;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   920
                        guaranteedNonNull[c] = cl.isPrimitive();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   921
                    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   922
                    off += getParameterSize(cl);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   923
                    modOff += getParameterSize(String.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   924
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   925
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   926
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   927
            if (mode.isSized()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   928
                /*
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   929
                    When operating in sized mode (this includes exact mode), it makes sense to make
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   930
                    StringBuilder append chains look familiar to OptimizeStringConcat. For that, we
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   931
                    need to do null-checks early, not make the append chain shape simpler.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   932
                 */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   933
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   934
                int off = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   935
                for (RecipeElement el : recipe.getElements()) {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   936
                    switch (el.getTag()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   937
                        case TAG_CONST:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   938
                            // Guaranteed non-null, no null check required.
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   939
                            break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   940
                        case TAG_ARG:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   941
                            // Null-checks are needed only for String arguments, and when a previous stage
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   942
                            // did not do implicit null-checks. If a String is null, we eagerly replace it
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   943
                            // with "null" constant. Note, we omit Objects here, because we don't call
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   944
                            // .length() on them down below.
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   945
                            int ac = el.getArgPos();
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   946
                            Class<?> cl = arr[ac];
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   947
                            if (cl == String.class && !guaranteedNonNull[ac]) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   948
                                Label l0 = new Label();
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   949
                                mv.visitIntInsn(ALOAD, off);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   950
                                mv.visitJumpInsn(IFNONNULL, l0);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   951
                                mv.visitLdcInsn("null");
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   952
                                mv.visitIntInsn(ASTORE, off);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   953
                                mv.visitLabel(l0);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   954
                            }
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   955
                            off += getParameterSize(cl);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   956
                            break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   957
                        default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   958
                            throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   959
                    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   960
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   961
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   962
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   963
            // Prepare StringBuilder instance
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   964
            mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   965
            mv.visitInsn(DUP);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   966
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   967
            if (mode.isSized()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   968
                /*
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   969
                    Sized mode requires us to walk through the arguments, and estimate the final length.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   970
                    In exact mode, this will operate on Strings only. This code would accumulate the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   971
                    final length on stack.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   972
                 */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   973
                int len = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   974
                int off = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   975
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   976
                mv.visitInsn(ICONST_0);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   977
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   978
                for (RecipeElement el : recipe.getElements()) {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   979
                    switch (el.getTag()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   980
                        case TAG_CONST:
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
   981
                            len += el.getValue().length();
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   982
                            break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   983
                        case TAG_ARG:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   984
                            /*
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   985
                                If an argument is String, then we can call .length() on it. Sized/Exact modes have
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   986
                                converted arguments for us. If an argument is primitive, we can provide a guess
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   987
                                for its String representation size.
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   988
                            */
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   989
                            Class<?> cl = arr[el.getArgPos()];
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   990
                            if (cl == String.class) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   991
                                mv.visitIntInsn(ALOAD, off);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   992
                                mv.visitMethodInsn(
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   993
                                        INVOKEVIRTUAL,
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   994
                                        "java/lang/String",
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   995
                                        "length",
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   996
                                        "()I",
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   997
                                        false
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   998
                                );
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
   999
                                mv.visitInsn(IADD);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1000
                            } else if (cl.isPrimitive()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1001
                                len += estimateSize(cl);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1002
                            }
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1003
                            off += getParameterSize(cl);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1004
                            break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1005
                        default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1006
                            throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1007
                    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1008
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1009
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1010
                // Constants have non-zero length, mix in
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1011
                if (len > 0) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1012
                    iconst(mv, len);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1013
                    mv.visitInsn(IADD);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1014
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1015
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1016
                mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1017
                        INVOKESPECIAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1018
                        "java/lang/StringBuilder",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1019
                        "<init>",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1020
                        "(I)V",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1021
                        false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1022
                );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1023
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1024
                mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1025
                        INVOKESPECIAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1026
                        "java/lang/StringBuilder",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1027
                        "<init>",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1028
                        "()V",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1029
                        false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1030
                );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1031
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1032
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1033
            // At this point, we have a blank StringBuilder on stack, fill it in with .append calls.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1034
            {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1035
                int off = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1036
                for (RecipeElement el : recipe.getElements()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1037
                    String desc;
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1038
                    switch (el.getTag()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1039
                        case TAG_CONST:
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
  1040
                            mv.visitLdcInsn(el.getValue());
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
  1041
                            desc = getSBAppendDesc(String.class);
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1042
                            break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1043
                        case TAG_ARG:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1044
                            Class<?> cl = arr[el.getArgPos()];
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1045
                            mv.visitVarInsn(getLoadOpcode(cl), off);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1046
                            off += getParameterSize(cl);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1047
                            desc = getSBAppendDesc(cl);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1048
                            break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1049
                        default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1050
                            throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1051
                    }
40256
c5e03eaf7ba2 8163370: Reduce number of classes loaded by common usage of java.lang.invoke
redestad
parents: 38868
diff changeset
  1052
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1053
                    mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1054
                            INVOKEVIRTUAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1055
                            "java/lang/StringBuilder",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1056
                            "append",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1057
                            desc,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1058
                            false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1059
                    );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1060
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1061
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1062
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1063
            if (DEBUG && mode.isExact()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1064
                /*
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1065
                    Exactness checks compare the final StringBuilder.capacity() with a resulting
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1066
                    String.length(). If these values disagree, that means StringBuilder had to perform
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1067
                    storage trimming, which defeats the purpose of exact strategies.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1068
                 */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1069
35639
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1070
                /*
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1071
                   The logic for this check is as follows:
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1072
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1073
                     Stack before:     Op:
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1074
                      (SB)              dup, dup
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1075
                      (SB, SB, SB)      capacity()
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1076
                      (int, SB, SB)     swap
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1077
                      (SB, int, SB)     toString()
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1078
                      (S, int, SB)      length()
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1079
                      (int, int, SB)    if_icmpeq
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1080
                      (SB)              <end>
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1081
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1082
                   Note that it leaves the same StringBuilder on exit, like the one on enter.
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1083
                 */
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1084
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1085
                mv.visitInsn(DUP);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1086
                mv.visitInsn(DUP);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1087
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1088
                mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1089
                        INVOKEVIRTUAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1090
                        "java/lang/StringBuilder",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1091
                        "capacity",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1092
                        "()I",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1093
                        false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1094
                );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1095
35639
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1096
                mv.visitInsn(SWAP);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1097
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1098
                mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1099
                        INVOKEVIRTUAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1100
                        "java/lang/StringBuilder",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1101
                        "toString",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1102
                        "()Ljava/lang/String;",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1103
                        false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1104
                );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1105
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1106
                mv.visitMethodInsn(
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1107
                        INVOKEVIRTUAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1108
                        "java/lang/String",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1109
                        "length",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1110
                        "()I",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1111
                        false
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1112
                );
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1113
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1114
                Label l0 = new Label();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1115
                mv.visitJumpInsn(IF_ICMPEQ, l0);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1116
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1117
                mv.visitTypeInsn(NEW, "java/lang/AssertionError");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1118
                mv.visitInsn(DUP);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1119
                mv.visitLdcInsn("Failed exactness check");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1120
                mv.visitMethodInsn(INVOKESPECIAL,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1121
                        "java/lang/AssertionError",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1122
                        "<init>",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1123
                        "(Ljava/lang/Object;)V",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1124
                        false);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1125
                mv.visitInsn(ATHROW);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1126
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1127
                mv.visitLabel(l0);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1128
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1129
35639
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1130
            mv.visitMethodInsn(
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1131
                    INVOKEVIRTUAL,
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1132
                    "java/lang/StringBuilder",
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1133
                    "toString",
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1134
                    "()Ljava/lang/String;",
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1135
                    false
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1136
            );
f34e7e8b4eac 8148787: StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested
shade
parents: 35401
diff changeset
  1137
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1138
            mv.visitInsn(ARETURN);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1139
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1140
            mv.visitMaxs(-1, -1);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1141
            mv.visitEnd();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1142
            cw.visitEnd();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1143
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1144
            byte[] classBytes = cw.toByteArray();
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1145
            try {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1146
                Class<?> hostClass = lookup.lookupClass();
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1147
                Class<?> innerClass = UNSAFE.defineAnonymousClass(hostClass, classBytes, null);
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1148
                UNSAFE.ensureClassInitialized(innerClass);
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1149
                dumpIfEnabled(innerClass.getName(), classBytes);
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1150
                return Lookup.IMPL_LOOKUP.findStatic(innerClass, METHOD_NAME, args);
42105
d04ede5f10e7 8163553: java.lang.LinkageError from test java/lang/ThreadGroup/Stop.java
psandoz
parents: 40810
diff changeset
  1151
            } catch (Exception e) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1152
                dumpIfEnabled(className + "$$FAILED", classBytes);
42105
d04ede5f10e7 8163553: java.lang.LinkageError from test java/lang/ThreadGroup/Stop.java
psandoz
parents: 40810
diff changeset
  1153
                throw new StringConcatException("Exception while spinning the class", e);
35776
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
  1154
            }
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1155
        }
35776
dd5df83fcc0d 8149459: StringConcatFactory should be synced up with LambdaMetafactory
shade
parents: 35700
diff changeset
  1156
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1157
        private static void dumpIfEnabled(String name, byte[] bytes) {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1158
            if (DUMPER != null) {
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1159
                DUMPER.dumpClass(name, bytes);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1160
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1161
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1162
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1163
        private static String getSBAppendDesc(Class<?> cl) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1164
            if (cl.isPrimitive()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1165
                if (cl == Integer.TYPE || cl == Byte.TYPE || cl == Short.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1166
                    return "(I)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1167
                } else if (cl == Boolean.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1168
                    return "(Z)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1169
                } else if (cl == Character.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1170
                    return "(C)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1171
                } else if (cl == Double.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1172
                    return "(D)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1173
                } else if (cl == Float.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1174
                    return "(F)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1175
                } else if (cl == Long.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1176
                    return "(J)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1177
                } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1178
                    throw new IllegalStateException("Unhandled primitive StringBuilder.append: " + cl);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1179
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1180
            } else if (cl == String.class) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1181
                return "(Ljava/lang/String;)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1182
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1183
                return "(Ljava/lang/Object;)Ljava/lang/StringBuilder;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1184
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1185
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1186
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1187
        private static String getStringValueOfDesc(Class<?> cl) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1188
            if (cl.isPrimitive()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1189
                if (cl == Integer.TYPE || cl == Byte.TYPE || cl == Short.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1190
                    return "(I)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1191
                } else if (cl == Boolean.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1192
                    return "(Z)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1193
                } else if (cl == Character.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1194
                    return "(C)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1195
                } else if (cl == Double.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1196
                    return "(D)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1197
                } else if (cl == Float.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1198
                    return "(F)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1199
                } else if (cl == Long.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1200
                    return "(J)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1201
                } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1202
                    throw new IllegalStateException("Unhandled String.valueOf: " + cl);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1203
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1204
            } else if (cl == String.class) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1205
                return "(Ljava/lang/String;)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1206
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1207
                return "(Ljava/lang/Object;)Ljava/lang/String;";
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1208
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1209
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1210
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1211
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1212
         * The following method is copied from
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1213
         * org.objectweb.asm.commons.InstructionAdapter. Part of ASM: a very small
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1214
         * and fast Java bytecode manipulation framework.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1215
         * Copyright (c) 2000-2005 INRIA, France Telecom All rights reserved.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1216
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1217
        private static void iconst(MethodVisitor mv, final int cst) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1218
            if (cst >= -1 && cst <= 5) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1219
                mv.visitInsn(Opcodes.ICONST_0 + cst);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1220
            } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1221
                mv.visitIntInsn(Opcodes.BIPUSH, cst);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1222
            } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1223
                mv.visitIntInsn(Opcodes.SIPUSH, cst);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1224
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1225
                mv.visitLdcInsn(cst);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1226
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1227
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1228
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1229
        private static int getLoadOpcode(Class<?> c) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1230
            if (c == Void.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1231
                throw new InternalError("Unexpected void type of load opcode");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1232
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1233
            return ILOAD + getOpcodeOffset(c);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1234
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1235
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1236
        private static int getOpcodeOffset(Class<?> c) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1237
            if (c.isPrimitive()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1238
                if (c == Long.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1239
                    return 1;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1240
                } else if (c == Float.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1241
                    return 2;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1242
                } else if (c == Double.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1243
                    return 3;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1244
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1245
                return 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1246
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1247
                return 4;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1248
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1249
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1250
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1251
        private static int getParameterSize(Class<?> c) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1252
            if (c == Void.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1253
                return 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1254
            } else if (c == Long.TYPE || c == Double.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1255
                return 2;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1256
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1257
            return 1;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1258
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1259
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1260
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1261
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1262
     * MethodHandle StringBuilder strategy.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1263
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1264
     * <p>This strategy operates in two modes, gated by {@link Mode}.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1265
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1266
     * <p><b>{@link Strategy#MH_SB_SIZED}: "MethodHandles StringBuilder,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1267
     * sized".</b>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1268
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1269
     * <p>This strategy avoids spinning up the bytecode by building the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1270
     * computation on MethodHandle combinators. The computation is built with
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1271
     * public MethodHandle APIs, resolved from a public Lookup sequence, and
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1272
     * ends up calling the public StringBuilder API. Therefore, this strategy
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1273
     * does not use any private API at all, even the Unsafe.defineAnonymousClass,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1274
     * since everything is handled under cover by java.lang.invoke APIs.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1275
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1276
     * <p><b>{@link Strategy#MH_SB_SIZED_EXACT}: "MethodHandles StringBuilder,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1277
     * sized exactly".</b>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1278
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1279
     * <p>This strategy improves on @link Strategy#MH_SB_SIZED}, by first
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1280
     * converting all arguments to String in order to get the exact capacity
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1281
     * StringBuilder should have. The conversion is done via the public
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1282
     * String.valueOf and/or Object.toString methods, and does not touch any
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1283
     * private String API.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1284
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1285
    private static final class MethodHandleStringBuilderStrategy {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1286
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1287
        private MethodHandleStringBuilderStrategy() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1288
            // no instantiation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1289
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1290
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1291
        private static MethodHandle generate(MethodType mt, Recipe recipe, Mode mode) throws Exception {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1292
            int pc = mt.parameterCount();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1293
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1294
            Class<?>[] ptypes = mt.parameterArray();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1295
            MethodHandle[] filters = new MethodHandle[ptypes.length];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1296
            for (int i = 0; i < ptypes.length; i++) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1297
                MethodHandle filter;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1298
                switch (mode) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1299
                    case SIZED:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1300
                        // In sized mode, we convert all references and floats/doubles
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1301
                        // to String: there is no specialization for different
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1302
                        // classes in StringBuilder API, and it will convert to
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1303
                        // String internally anyhow.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1304
                        filter = Stringifiers.forMost(ptypes[i]);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1305
                        break;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1306
                    case SIZED_EXACT:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1307
                        // In exact mode, we convert everything to String:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1308
                        // this helps to compute the storage exactly.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1309
                        filter = Stringifiers.forAny(ptypes[i]);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1310
                        break;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1311
                    default:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1312
                        throw new StringConcatException("Not supported");
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1313
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1314
                if (filter != null) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1315
                    filters[i] = filter;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1316
                    ptypes[i] = filter.type().returnType();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1317
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1318
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1319
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1320
            MethodHandle[] lengthers = new MethodHandle[pc];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1321
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1322
            // Figure out lengths: constants' lengths can be deduced on the spot.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1323
            // All reference arguments were filtered to String in the combinators below, so we can
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1324
            // call the usual String.length(). Primitive values string sizes can be estimated.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1325
            int initial = 0;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1326
            for (RecipeElement el : recipe.getElements()) {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1327
                switch (el.getTag()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1328
                    case TAG_CONST:
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
  1329
                        initial += el.getValue().length();
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1330
                        break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1331
                    case TAG_ARG:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1332
                        final int i = el.getArgPos();
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1333
                        Class<?> type = ptypes[i];
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1334
                        if (type.isPrimitive()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1335
                            MethodHandle est = MethodHandles.constant(int.class, estimateSize(type));
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1336
                            est = MethodHandles.dropArguments(est, 0, type);
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1337
                            lengthers[i] = est;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1338
                        } else {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1339
                            lengthers[i] = STRING_LENGTH;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1340
                        }
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1341
                        break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1342
                    default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1343
                        throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1344
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1345
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1346
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1347
            // Create (StringBuilder, <args>) shape for appending:
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1348
            MethodHandle builder = MethodHandles.dropArguments(MethodHandles.identity(StringBuilder.class), 1, ptypes);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1349
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1350
            // Compose append calls. This is done in reverse because the application order is
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1351
            // reverse as well.
36737
67b2804be5ab 8152951: Avoid calculating the reverse of StringConcatFactory$Recipe elements
redestad
parents: 36668
diff changeset
  1352
            List<RecipeElement> elements = recipe.getElements();
67b2804be5ab 8152951: Avoid calculating the reverse of StringConcatFactory$Recipe elements
redestad
parents: 36668
diff changeset
  1353
            for (int i = elements.size() - 1; i >= 0; i--) {
67b2804be5ab 8152951: Avoid calculating the reverse of StringConcatFactory$Recipe elements
redestad
parents: 36668
diff changeset
  1354
                RecipeElement el = elements.get(i);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1355
                MethodHandle appender;
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1356
                switch (el.getTag()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1357
                    case TAG_CONST:
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
  1358
                        MethodHandle mh = appender(adaptToStringBuilder(String.class));
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
  1359
                        appender = MethodHandles.insertArguments(mh, 1, el.getValue());
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1360
                        break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1361
                    case TAG_ARG:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1362
                        int ac = el.getArgPos();
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1363
                        appender = appender(ptypes[ac]);
40256
c5e03eaf7ba2 8163370: Reduce number of classes loaded by common usage of java.lang.invoke
redestad
parents: 38868
diff changeset
  1364
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1365
                        // Insert dummy arguments to match the prefix in the signature.
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1366
                        // The actual appender argument will be the ac-ith argument.
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1367
                        if (ac != 0) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1368
                            appender = MethodHandles.dropArguments(appender, 1, Arrays.copyOf(ptypes, ac));
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1369
                        }
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1370
                        break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1371
                    default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1372
                        throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1373
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1374
                builder = MethodHandles.foldArguments(builder, appender);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1375
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1376
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1377
            // Build the sub-tree that adds the sizes and produces a StringBuilder:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1378
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1379
            // a) Start with the reducer that accepts all arguments, plus one
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1380
            //    slot for the initial value. Inject the initial value right away.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1381
            //    This produces (<ints>)int shape:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1382
            MethodHandle sum = getReducerFor(pc + 1);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1383
            MethodHandle adder = MethodHandles.insertArguments(sum, 0, initial);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1384
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1385
            // b) Apply lengthers to transform arguments to lengths, producing (<args>)int
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1386
            adder = MethodHandles.filterArguments(adder, 0, lengthers);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1387
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1388
            // c) Instantiate StringBuilder (<args>)int -> (<args>)StringBuilder
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1389
            MethodHandle newBuilder = MethodHandles.filterReturnValue(adder, NEW_STRING_BUILDER);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1390
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1391
            // d) Fold in StringBuilder constructor, this produces (<args>)StringBuilder
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1392
            MethodHandle mh = MethodHandles.foldArguments(builder, newBuilder);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1393
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1394
            // Convert non-primitive arguments to Strings
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1395
            mh = MethodHandles.filterArguments(mh, 0, filters);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1396
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1397
            // Convert (<args>)StringBuilder to (<args>)String
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1398
            if (DEBUG && mode.isExact()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1399
                mh = MethodHandles.filterReturnValue(mh, BUILDER_TO_STRING_CHECKED);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1400
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1401
                mh = MethodHandles.filterReturnValue(mh, BUILDER_TO_STRING);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1402
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1403
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1404
            return mh;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1405
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1406
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1407
        private static MethodHandle getReducerFor(int cnt) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1408
            return SUMMERS.computeIfAbsent(cnt, SUMMER);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1409
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1410
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1411
        private static MethodHandle appender(Class<?> appendType) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1412
            MethodHandle appender = lookupVirtual(MethodHandles.publicLookup(), StringBuilder.class, "append",
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1413
                    StringBuilder.class, adaptToStringBuilder(appendType));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1414
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1415
            // appenders should return void, this would not modify the target signature during folding
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1416
            MethodType nt = MethodType.methodType(void.class, StringBuilder.class, appendType);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1417
            return appender.asType(nt);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1418
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1419
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1420
        private static String toStringChecked(StringBuilder sb) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1421
            String s = sb.toString();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1422
            if (s.length() != sb.capacity()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1423
                throw new AssertionError("Exactness check failed: result length = " + s.length() + ", buffer capacity = " + sb.capacity());
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1424
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1425
            return s;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1426
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1427
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1428
        private static int sum(int v1, int v2) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1429
            return v1 + v2;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1430
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1431
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1432
        private static int sum(int v1, int v2, int v3) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1433
            return v1 + v2 + v3;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1434
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1435
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1436
        private static int sum(int v1, int v2, int v3, int v4) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1437
            return v1 + v2 + v3 + v4;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1438
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1439
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1440
        private static int sum(int v1, int v2, int v3, int v4, int v5) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1441
            return v1 + v2 + v3 + v4 + v5;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1442
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1443
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1444
        private static int sum(int v1, int v2, int v3, int v4, int v5, int v6) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1445
            return v1 + v2 + v3 + v4 + v5 + v6;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1446
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1447
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1448
        private static int sum(int v1, int v2, int v3, int v4, int v5, int v6, int v7) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1449
            return v1 + v2 + v3 + v4 + v5 + v6 + v7;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1450
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1451
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1452
        private static int sum(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1453
            return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1454
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1455
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1456
        private static int sum(int initial, int[] vs) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1457
            int sum = initial;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1458
            for (int v : vs) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1459
                sum += v;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1460
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1461
            return sum;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1462
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1463
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1464
        private static final ConcurrentMap<Integer, MethodHandle> SUMMERS;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1465
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1466
        // This one is deliberately non-lambdified to optimize startup time:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1467
        private static final Function<Integer, MethodHandle> SUMMER = new Function<Integer, MethodHandle>() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1468
            @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1469
            public MethodHandle apply(Integer cnt) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1470
                if (cnt == 1) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1471
                    return MethodHandles.identity(int.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1472
                } else if (cnt <= 8) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1473
                    // Variable-arity collectors are not as efficient as small-count methods,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1474
                    // unroll some initial sizes.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1475
                    Class<?>[] cls = new Class<?>[cnt];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1476
                    Arrays.fill(cls, int.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1477
                    return lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleStringBuilderStrategy.class, "sum", int.class, cls);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1478
                } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1479
                    return lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleStringBuilderStrategy.class, "sum", int.class, int.class, int[].class)
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1480
                            .asCollector(int[].class, cnt - 1);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1481
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1482
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1483
        };
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1484
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1485
        private static final MethodHandle NEW_STRING_BUILDER, STRING_LENGTH, BUILDER_TO_STRING, BUILDER_TO_STRING_CHECKED;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1486
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1487
        static {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1488
            SUMMERS = new ConcurrentHashMap<>();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1489
            Lookup publicLookup = MethodHandles.publicLookup();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1490
            NEW_STRING_BUILDER = lookupConstructor(publicLookup, StringBuilder.class, int.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1491
            STRING_LENGTH = lookupVirtual(publicLookup, String.class, "length", int.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1492
            BUILDER_TO_STRING = lookupVirtual(publicLookup, StringBuilder.class, "toString", String.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1493
            if (DEBUG) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1494
                BUILDER_TO_STRING_CHECKED = lookupStatic(MethodHandles.Lookup.IMPL_LOOKUP,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1495
                        MethodHandleStringBuilderStrategy.class, "toStringChecked", String.class, StringBuilder.class);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1496
            } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1497
                BUILDER_TO_STRING_CHECKED = null;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1498
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1499
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1500
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1501
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1502
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1503
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1504
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1505
     * <p><b>{@link Strategy#MH_INLINE_SIZED_EXACT}: "MethodHandles inline,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1506
     * sized exactly".</b>
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1507
     *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1508
     * <p>This strategy replicates what StringBuilders are doing: it builds the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1509
     * byte[] array on its own and passes that byte[] array to String
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1510
     * constructor. This strategy requires access to some private APIs in JDK,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1511
     * most notably, the read-only Integer/Long.stringSize methods that measure
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1512
     * the character length of the integers, and the private String constructor
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1513
     * that accepts byte[] arrays without copying. While this strategy assumes a
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1514
     * particular implementation details for String, this opens the door for
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1515
     * building a very optimal concatenation sequence. This is the only strategy
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1516
     * that requires porting if there are private JDK changes occur.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1517
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1518
    private static final class MethodHandleInlineCopyStrategy {
36668
ceb837301c53 8150463: StringConcat MH_INLINE_SIZED_EXACT should skip storage initialization
shade
parents: 36511
diff changeset
  1519
        static final Unsafe UNSAFE = Unsafe.getUnsafe();
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1520
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1521
        private MethodHandleInlineCopyStrategy() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1522
            // no instantiation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1523
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1524
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1525
        static MethodHandle generate(MethodType mt, Recipe recipe) throws Throwable {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1526
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1527
            // Fast-path two-argument Object + Object concatenations
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1528
            if (recipe.getElements().size() == 2) {
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1529
                // Two object arguments
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1530
                if (mt.parameterCount() == 2 &&
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1531
                    !mt.parameterType(0).isPrimitive() &&
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1532
                    !mt.parameterType(1).isPrimitive() &&
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1533
                    recipe.getElements().get(0).getTag() == TAG_ARG &&
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1534
                    recipe.getElements().get(1).getTag() == TAG_ARG) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1535
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1536
                    return SIMPLE;
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1537
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1538
                } else if (mt.parameterCount() == 1 &&
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1539
                           !mt.parameterType(0).isPrimitive()) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1540
                    // One Object argument, one constant
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1541
                    MethodHandle mh = SIMPLE;
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1542
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1543
                    if (recipe.getElements().get(0).getTag() == TAG_CONST &&
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1544
                        recipe.getElements().get(1).getTag() == TAG_ARG) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1545
                        // First recipe element is a constant
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1546
                        return MethodHandles.insertArguments(mh, 0,
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1547
                                recipe.getElements().get(0).getValue());
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1548
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1549
                    } else if (recipe.getElements().get(1).getTag() == TAG_CONST &&
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1550
                               recipe.getElements().get(0).getTag() == TAG_ARG) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1551
                        // Second recipe element is a constant
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1552
                        return MethodHandles.insertArguments(mh, 1,
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1553
                                recipe.getElements().get(1).getValue());
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1554
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1555
                    }
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1556
                }
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1557
                // else... fall-through to slow-path
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1558
            }
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1559
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1560
            // Create filters and obtain filtered parameter types. Filters would be used in the beginning
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1561
            // to convert the incoming arguments into the arguments we can process (e.g. Objects -> Strings).
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1562
            // The filtered argument type list is used all over in the combinators below.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1563
            Class<?>[] ptypes = mt.parameterArray();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1564
            MethodHandle[] filters = null;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1565
            for (int i = 0; i < ptypes.length; i++) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1566
                MethodHandle filter = Stringifiers.forMost(ptypes[i]);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1567
                if (filter != null) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1568
                    if (filters == null) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1569
                        filters = new MethodHandle[ptypes.length];
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1570
                    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1571
                    filters[i] = filter;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1572
                    ptypes[i] = filter.type().returnType();
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1573
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1574
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1575
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1576
            // Start building the combinator tree. The tree "starts" with (<parameters>)String, and "finishes"
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1577
            // with the (byte[], long)String shape to invoke newString in StringConcatHelper. The combinators are
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1578
            // assembled bottom-up, which makes the code arguably hard to read.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1579
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1580
            // Drop all remaining parameter types, leave only helper arguments:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1581
            MethodHandle mh;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1582
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1583
            mh = MethodHandles.dropArguments(NEW_STRING, 2, ptypes);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1584
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1585
            long initialLengthCoder = INITIAL_CODER;
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1586
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1587
            // Mix in prependers. This happens when (byte[], long) = (storage, indexCoder) is already
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1588
            // known from the combinators below. We are assembling the string backwards, so the index coded
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1589
            // into indexCoder is the *ending* index.
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1590
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1591
            // We need one prepender per argument, but also need to fold in constants. We do so by greedily
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1592
            // create prependers that fold in surrounding constants into the argument prepender. This reduces
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1593
            // the number of unique MH combinator tree shapes we'll create in an application.
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1594
            String prefixConstant = null, suffixConstant = null;
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1595
            int pos = -1;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1596
            for (RecipeElement el : recipe.getElements()) {
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1597
                // Do the prepend, and put "new" index at index 1
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1598
                switch (el.getTag()) {
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1599
                    case TAG_CONST: {
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1600
                        String constantValue = el.getValue();
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1601
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1602
                        // Eagerly update the initialLengthCoder value
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1603
                        initialLengthCoder = (long)mixer(String.class).invoke(initialLengthCoder, constantValue);
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1604
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1605
                        if (pos < 0) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1606
                            // Collecting into prefixConstant
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1607
                            prefixConstant = prefixConstant == null ? constantValue : prefixConstant + constantValue;
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1608
                        } else {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1609
                            // Collecting into suffixConstant
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1610
                            suffixConstant = suffixConstant == null ? constantValue : suffixConstant + constantValue;
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1611
                        }
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1612
                        break;
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1613
                    }
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1614
                    case TAG_ARG: {
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1615
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1616
                        if (pos >= 0) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1617
                            // Flush the previous non-constant arg with any prefix/suffix constant
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1618
                            mh = MethodHandles.filterArgumentsWithCombiner(
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1619
                                mh, 1,
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1620
                                prepender(prefixConstant, ptypes[pos], suffixConstant),
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1621
                                1, 0, // indexCoder, storage
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1622
                                2 + pos  // selected argument
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1623
                            );
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1624
                            prefixConstant = suffixConstant = null;
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1625
                        }
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1626
                        // Mark the pos of next non-constant arg
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1627
                        pos = el.getArgPos();
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1628
                        break;
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1629
                    }
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1630
                    default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1631
                        throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1632
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1633
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1634
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1635
            // Insert any trailing args, constants
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1636
            if (pos >= 0) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1637
                mh = MethodHandles.filterArgumentsWithCombiner(
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1638
                    mh, 1,
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1639
                    prepender(prefixConstant, ptypes[pos], suffixConstant),
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1640
                    1, 0, // indexCoder, storage
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1641
                    2 + pos  // selected argument
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1642
                );
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1643
            } else if (prefixConstant != null) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1644
                assert (suffixConstant == null);
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1645
                // Sole prefixConstant can only happen if there were no non-constant arguments
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1646
                mh = MethodHandles.filterArgumentsWithCombiner(
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1647
                    mh, 1,
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1648
                    MethodHandles.insertArguments(prepender(null, String.class, null), 2, prefixConstant),
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1649
                    1, 0 // indexCoder, storage
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1650
                );
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1651
            }
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1652
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1653
            // Fold in byte[] instantiation at argument 0
52226
b4b932c6001f 8212726: Replace some use of drop- and foldArguments with filtering argument combinator in StringConcatFactory
redestad
parents: 52177
diff changeset
  1654
            mh = MethodHandles.foldArgumentsWithCombiner(mh, 0, NEW_ARRAY,
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1655
                    1 // index
40810
b88d5910ea1e 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy
redestad
parents: 40272
diff changeset
  1656
            );
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1657
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1658
            // Start combining length and coder mixers.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1659
            //
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1660
            // Length is easy: constant lengths can be computed on the spot, and all non-constant
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1661
            // shapes have been either converted to Strings, or explicit methods for getting the
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1662
            // string length out of primitives are provided.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1663
            //
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1664
            // Coders are more interesting. Only Object, String and char arguments (and constants)
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1665
            // can have non-Latin1 encoding. It is easier to blindly convert constants to String,
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1666
            // and deduce the coder from there. Arguments would be either converted to Strings
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1667
            // during the initial filtering, or handled by specializations in MIXERS.
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1668
            //
54791
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1669
            // The method handle shape before all mixers are combined in is:
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1670
            //   (long, <args>)String = ("indexCoder", <args>)
54791
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1671
            //
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1672
            // We will bind the initialLengthCoder value to the last mixer (the one that will be
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1673
            // executed first), then fold that in. This leaves the shape after all mixers are
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1674
            // combined in as:
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1675
            //   (<args>)String = (<args>)
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1676
54791
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1677
            int ac = -1;
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1678
            MethodHandle mix = null;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1679
            for (RecipeElement el : recipe.getElements()) {
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1680
                switch (el.getTag()) {
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1681
                    case TAG_CONST:
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1682
                        // Constants already handled in the code above
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1683
                        break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1684
                    case TAG_ARG:
54791
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1685
                        if (ac >= 0) {
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1686
                            // Compute new "index" in-place using old value plus the appropriate argument.
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1687
                            mh = MethodHandles.filterArgumentsWithCombiner(mh, 0, mix,
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1688
                                    0, // old-index
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1689
                                    1 + ac // selected argument
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1690
                            );
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1691
                        }
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1692
54791
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1693
                        ac = el.getArgPos();
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1694
                        Class<?> argClass = ptypes[ac];
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1695
                        mix = mixer(argClass);
52177
430e6421d503 8212597: Optimize String concatenation setup when using primitive operands
redestad
parents: 48930
diff changeset
  1696
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1697
                        break;
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1698
                    default:
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1699
                        throw new StringConcatException("Unhandled tag: " + el.getTag());
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1700
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1701
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1702
54791
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1703
            // Insert the initialLengthCoder value into the final mixer, then
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1704
            // fold that into the base method handle
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1705
            if (ac >= 0) {
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1706
                mix = MethodHandles.insertArguments(mix, 0, initialLengthCoder);
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1707
                mh = MethodHandles.foldArgumentsWithCombiner(mh, 0, mix,
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1708
                        1 + ac // selected argument
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1709
                );
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1710
            } else {
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1711
                // No mixer (constants only concat), insert initialLengthCoder directly
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1712
                mh = MethodHandles.insertArguments(mh, 0, initialLengthCoder);
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1713
            }
04f603ebb6c2 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer
redestad
parents: 54652
diff changeset
  1714
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1715
            // The method handle shape here is (<args>).
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1716
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1717
            // Apply filters, converting the arguments:
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1718
            if (filters != null) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1719
                mh = MethodHandles.filterArguments(mh, 0, filters);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1720
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1721
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1722
            return mh;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1723
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1724
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1725
        private static MethodHandle prepender(String prefix, Class<?> cl, String suffix) {
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1726
            return MethodHandles.insertArguments(
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1727
                    MethodHandles.insertArguments(
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1728
                        PREPENDERS.computeIfAbsent(cl, PREPEND),2, prefix), 3, suffix);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1729
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1730
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1731
        private static MethodHandle mixer(Class<?> cl) {
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1732
            return MIXERS.computeIfAbsent(cl, MIX);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1733
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1734
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1735
        // This one is deliberately non-lambdified to optimize startup time:
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1736
        private static final Function<Class<?>, MethodHandle> PREPEND = new Function<>() {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1737
            @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1738
            public MethodHandle apply(Class<?> c) {
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1739
                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", long.class, long.class, byte[].class,
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1740
                        String.class, Wrapper.asPrimitiveType(c), String.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1741
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1742
        };
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1743
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1744
        // This one is deliberately non-lambdified to optimize startup time:
54652
1cb0306f16d1 8222852: Reduce String concat combinator tree shapes by folding constants into prependers
redestad
parents: 54550
diff changeset
  1745
        private static final Function<Class<?>, MethodHandle> MIX = new Function<>() {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1746
            @Override
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1747
            public MethodHandle apply(Class<?> c) {
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1748
                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mix", long.class, long.class,
46902
c6cefe631b18 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
redestad
parents: 42105
diff changeset
  1749
                        Wrapper.asPrimitiveType(c));
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1750
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1751
        };
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1752
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1753
        private static final MethodHandle SIMPLE;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1754
        private static final MethodHandle NEW_STRING;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1755
        private static final MethodHandle NEW_ARRAY;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1756
        private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1757
        private static final ConcurrentMap<Class<?>, MethodHandle> MIXERS;
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1758
        private static final long INITIAL_CODER;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1759
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1760
        static {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1761
            try {
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1762
                MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", long.class);
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1763
                INITIAL_CODER = (long) initCoder.invoke();
35700
b933119b8f84 8148869: StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings
shade
parents: 35639
diff changeset
  1764
            } catch (Throwable e) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1765
                throw new AssertionError(e);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1766
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1767
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1768
            PREPENDERS = new ConcurrentHashMap<>();
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1769
            MIXERS = new ConcurrentHashMap<>();
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1770
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1771
            SIMPLE     = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "simpleConcat", String.class, Object.class, Object.class);
52326
77018c2b97df 8213035: Pack MethodHandleInlineStrategy coder and length into a long
redestad
parents: 52226
diff changeset
  1772
            NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, long.class);
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1773
            NEW_ARRAY  = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newArray", byte[].class, long.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1774
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1775
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1776
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1777
    /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1778
     * Public gateways to public "stringify" methods. These methods have the form String apply(T obj), and normally
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1779
     * delegate to {@code String.valueOf}, depending on argument's type.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1780
     */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1781
    private static final class Stringifiers {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1782
        private Stringifiers() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1783
            // no instantiation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1784
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1785
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1786
        private static final MethodHandle OBJECT_INSTANCE =
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1787
            lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "stringOf", String.class, Object.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1788
52497
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1789
        private static class FloatStringifiers {
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1790
            private static final MethodHandle FLOAT_INSTANCE =
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1791
                    lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, float.class);
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1792
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1793
            private static final MethodHandle DOUBLE_INSTANCE =
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1794
                    lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, double.class);
38868
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1795
        }
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1796
38868
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1797
        private static class StringifierAny extends ClassValue<MethodHandle> {
52497
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1798
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1799
            private static final ClassValue<MethodHandle> INSTANCE = new StringifierAny();
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1800
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1801
            @Override
38868
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1802
            protected MethodHandle computeValue(Class<?> cl) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1803
                if (cl == byte.class || cl == short.class || cl == int.class) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1804
                    return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, int.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1805
                } else if (cl == boolean.class) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1806
                    return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, boolean.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1807
                } else if (cl == char.class) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1808
                    return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, char.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1809
                } else if (cl == long.class) {
36001
5f0acf0668e0 8149835: StringConcatFactory should emit classes with the same package as the host class
shade
parents: 35776
diff changeset
  1810
                    return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, long.class);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1811
                } else {
52497
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1812
                    MethodHandle mh = forMost(cl);
38868
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1813
                    if (mh != null) {
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1814
                        return mh;
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1815
                    } else {
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1816
                        throw new IllegalStateException("Unknown class: " + cl);
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1817
                    }
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1818
                }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1819
            }
38868
f353ab3063f8 8158933: String concat stringifiers setup should avoid unnecessary lookups
redestad
parents: 38428
diff changeset
  1820
        }
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1821
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1822
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1823
         * Returns a stringifier for references and floats/doubles only.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1824
         * Always returns null for other primitives.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1825
         *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1826
         * @param t class to stringify
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1827
         * @return stringifier; null, if not available
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1828
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1829
        static MethodHandle forMost(Class<?> t) {
52497
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1830
            if (!t.isPrimitive()) {
54550
5fa7fbddfe9d 8222484: Specialize generation of simple String concatenation expressions
redestad
parents: 52497
diff changeset
  1831
                return OBJECT_INSTANCE;
52497
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1832
            } else if (t == float.class) {
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1833
                return FloatStringifiers.FLOAT_INSTANCE;
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1834
            } else if (t == double.class) {
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1835
                return FloatStringifiers.DOUBLE_INSTANCE;
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1836
            }
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1837
            return null;
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1838
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1839
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1840
        /**
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1841
         * Returns a stringifier for any type. Never returns null.
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1842
         *
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1843
         * @param t class to stringify
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1844
         * @return stringifier
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1845
         */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1846
        static MethodHandle forAny(Class<?> t) {
52497
34510f65fb58 8213741: Consolidate Object and String Stringifiers
redestad
parents: 52326
diff changeset
  1847
            return StringifierAny.INSTANCE.get(t);
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1848
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1849
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1850
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1851
    /* ------------------------------- Common utilities ------------------------------------ */
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1852
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1853
    static MethodHandle lookupStatic(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1854
        try {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1855
            return lookup.findStatic(refc, name, MethodType.methodType(rtype, ptypes));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1856
        } catch (NoSuchMethodException | IllegalAccessException e) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1857
            throw new AssertionError(e);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1858
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1859
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1860
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1861
    static MethodHandle lookupVirtual(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1862
        try {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1863
            return lookup.findVirtual(refc, name, MethodType.methodType(rtype, ptypes));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1864
        } catch (NoSuchMethodException | IllegalAccessException e) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1865
            throw new AssertionError(e);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1866
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1867
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1868
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1869
    static MethodHandle lookupConstructor(Lookup lookup, Class<?> refc, Class<?> ptypes) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1870
        try {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1871
            return lookup.findConstructor(refc, MethodType.methodType(void.class, ptypes));
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1872
        } catch (NoSuchMethodException | IllegalAccessException e) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1873
            throw new AssertionError(e);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1874
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1875
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1876
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1877
    static int estimateSize(Class<?> cl) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1878
        if (cl == Integer.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1879
            return 11; // "-2147483648"
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1880
        } else if (cl == Boolean.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1881
            return 5; // "false"
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1882
        } else if (cl == Byte.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1883
            return 4; // "-128"
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1884
        } else if (cl == Character.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1885
            return 1; // duh
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1886
        } else if (cl == Short.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1887
            return 6; // "-32768"
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1888
        } else if (cl == Double.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1889
            return 26; // apparently, no larger than this, see FloatingDecimal.BinaryToASCIIBuffer.buffer
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1890
        } else if (cl == Float.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1891
            return 26; // apparently, no larger than this, see FloatingDecimal.BinaryToASCIIBuffer.buffer
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1892
        } else if (cl == Long.TYPE)  {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1893
            return 20; // "-9223372036854775808"
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1894
        } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1895
            throw new IllegalArgumentException("Cannot estimate the size for " + cl);
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1896
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1897
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1898
40272
6af4511ee5a4 8163878: Remove unnecessary bridge methods, allocations in java.lang.invoke
redestad
parents: 40256
diff changeset
  1899
    static Class<?> adaptToStringBuilder(Class<?> c) {
35388
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1900
        if (c.isPrimitive()) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1901
            if (c == Byte.TYPE || c == Short.TYPE) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1902
                return int.class;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1903
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1904
        } else {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1905
            if (c != String.class) {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1906
                return Object.class;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1907
            }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1908
        }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1909
        return c;
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1910
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1911
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1912
    private StringConcatFactory() {
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1913
        // no instantiation
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1914
    }
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1915
a33a232cf7b7 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
  1916
}