< prev index next >

src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java

Print this page
rev 17627 : 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
Reviewed-by: TBD


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 

  28 import jdk.internal.org.objectweb.asm.ClassWriter;
  29 import jdk.internal.org.objectweb.asm.Label;
  30 import jdk.internal.org.objectweb.asm.MethodVisitor;
  31 import jdk.internal.org.objectweb.asm.Opcodes;
  32 import jdk.internal.vm.annotation.ForceInline;
  33 import jdk.internal.misc.Unsafe;

  34 
  35 import java.lang.invoke.MethodHandles.Lookup;
  36 import java.util.*;




  37 import java.util.concurrent.ConcurrentHashMap;
  38 import java.util.concurrent.ConcurrentMap;
  39 import java.util.function.Function;
  40 import sun.security.action.GetPropertyAction;
  41 
  42 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  43 
  44 /**
  45  * <p>Methods to facilitate the creation of String concatenation methods, that
  46  * can be used to efficiently concatenate a known number of arguments of known
  47  * types, possibly after type adaptation and partial evaluation of arguments.
  48  * These methods are typically used as <em>bootstrap methods</em> for {@code
  49  * invokedynamic} call sites, to support the <em>string concatenation</em>
  50  * feature of the Java Programming Language.
  51  *
  52  * <p>Indirect access to the behavior specified by the provided {@code
  53  * MethodHandle} proceeds in order through two phases:
  54  *
  55  * <ol>
  56  *     <li><em>Linkage</em> occurs when the methods in this class are invoked.
  57  * They take as arguments a method type describing the concatenated arguments
  58  * count and types, and optionally the String <em>recipe</em>, plus the
  59  * constants that participate in the String concatenation. The details on
  60  * accepted recipe shapes are described further below. Linkage may involve


1604         private static byte[] newArray(int length, byte coder) {
1605             return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, length << coder);
1606         }
1607 
1608         private static MethodHandle prepender(Class<?> cl) {
1609             return PREPENDERS.computeIfAbsent(cl, PREPEND);
1610         }
1611 
1612         private static MethodHandle coderMixer(Class<?> cl) {
1613             return CODER_MIXERS.computeIfAbsent(cl, CODER_MIX);
1614         }
1615 
1616         private static MethodHandle lengthMixer(Class<?> cl) {
1617             return LENGTH_MIXERS.computeIfAbsent(cl, LENGTH_MIX);
1618         }
1619 
1620         // This one is deliberately non-lambdified to optimize startup time:
1621         private static final Function<Class<?>, MethodHandle> PREPEND = new Function<Class<?>, MethodHandle>() {
1622             @Override
1623             public MethodHandle apply(Class<?> c) {
1624                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", int.class, int.class, byte[].class, byte.class, c);

1625             }
1626         };
1627 
1628         // This one is deliberately non-lambdified to optimize startup time:
1629         private static final Function<Class<?>, MethodHandle> CODER_MIX = new Function<Class<?>, MethodHandle>() {
1630             @Override
1631             public MethodHandle apply(Class<?> c) {
1632                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixCoder", byte.class, byte.class, c);

1633             }
1634         };
1635 
1636         // This one is deliberately non-lambdified to optimize startup time:
1637         private static final Function<Class<?>, MethodHandle> LENGTH_MIX = new Function<Class<?>, MethodHandle>() {
1638             @Override
1639             public MethodHandle apply(Class<?> c) {
1640                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixLen", int.class, int.class, c);

1641             }
1642         };
1643 
1644         private static final MethodHandle NEW_STRING;
1645         private static final MethodHandle NEW_ARRAY;
1646         private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
1647         private static final ConcurrentMap<Class<?>, MethodHandle> LENGTH_MIXERS;
1648         private static final ConcurrentMap<Class<?>, MethodHandle> CODER_MIXERS;
1649         private static final byte INITIAL_CODER;
1650         static final Class<?> STRING_HELPER;
1651 
1652         static {
1653             try {
1654                 STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
1655                 MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", byte.class);
1656                 INITIAL_CODER = (byte) initCoder.invoke();
1657             } catch (Throwable e) {
1658                 throw new AssertionError(e);
1659             }
1660 




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.misc.Unsafe;
  29 import jdk.internal.org.objectweb.asm.ClassWriter;
  30 import jdk.internal.org.objectweb.asm.Label;
  31 import jdk.internal.org.objectweb.asm.MethodVisitor;
  32 import jdk.internal.org.objectweb.asm.Opcodes;
  33 import jdk.internal.vm.annotation.ForceInline;
  34 import sun.invoke.util.Wrapper;
  35 import sun.security.action.GetPropertyAction;
  36 
  37 import java.lang.invoke.MethodHandles.Lookup;
  38 import java.util.ArrayList;
  39 import java.util.Arrays;
  40 import java.util.List;
  41 import java.util.Objects;
  42 import java.util.Properties;
  43 import java.util.concurrent.ConcurrentHashMap;
  44 import java.util.concurrent.ConcurrentMap;
  45 import java.util.function.Function;

  46 
  47 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  48 
  49 /**
  50  * <p>Methods to facilitate the creation of String concatenation methods, that
  51  * can be used to efficiently concatenate a known number of arguments of known
  52  * types, possibly after type adaptation and partial evaluation of arguments.
  53  * These methods are typically used as <em>bootstrap methods</em> for {@code
  54  * invokedynamic} call sites, to support the <em>string concatenation</em>
  55  * feature of the Java Programming Language.
  56  *
  57  * <p>Indirect access to the behavior specified by the provided {@code
  58  * MethodHandle} proceeds in order through two phases:
  59  *
  60  * <ol>
  61  *     <li><em>Linkage</em> occurs when the methods in this class are invoked.
  62  * They take as arguments a method type describing the concatenated arguments
  63  * count and types, and optionally the String <em>recipe</em>, plus the
  64  * constants that participate in the String concatenation. The details on
  65  * accepted recipe shapes are described further below. Linkage may involve


1609         private static byte[] newArray(int length, byte coder) {
1610             return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, length << coder);
1611         }
1612 
1613         private static MethodHandle prepender(Class<?> cl) {
1614             return PREPENDERS.computeIfAbsent(cl, PREPEND);
1615         }
1616 
1617         private static MethodHandle coderMixer(Class<?> cl) {
1618             return CODER_MIXERS.computeIfAbsent(cl, CODER_MIX);
1619         }
1620 
1621         private static MethodHandle lengthMixer(Class<?> cl) {
1622             return LENGTH_MIXERS.computeIfAbsent(cl, LENGTH_MIX);
1623         }
1624 
1625         // This one is deliberately non-lambdified to optimize startup time:
1626         private static final Function<Class<?>, MethodHandle> PREPEND = new Function<Class<?>, MethodHandle>() {
1627             @Override
1628             public MethodHandle apply(Class<?> c) {
1629                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", int.class, int.class, byte[].class, byte.class,
1630                         Wrapper.asPrimitiveType(c));
1631             }
1632         };
1633 
1634         // This one is deliberately non-lambdified to optimize startup time:
1635         private static final Function<Class<?>, MethodHandle> CODER_MIX = new Function<Class<?>, MethodHandle>() {
1636             @Override
1637             public MethodHandle apply(Class<?> c) {
1638                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixCoder", byte.class, byte.class,
1639                         Wrapper.asPrimitiveType(c));
1640             }
1641         };
1642 
1643         // This one is deliberately non-lambdified to optimize startup time:
1644         private static final Function<Class<?>, MethodHandle> LENGTH_MIX = new Function<Class<?>, MethodHandle>() {
1645             @Override
1646             public MethodHandle apply(Class<?> c) {
1647                 return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixLen", int.class, int.class,
1648                         Wrapper.asPrimitiveType(c));
1649             }
1650         };
1651 
1652         private static final MethodHandle NEW_STRING;
1653         private static final MethodHandle NEW_ARRAY;
1654         private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
1655         private static final ConcurrentMap<Class<?>, MethodHandle> LENGTH_MIXERS;
1656         private static final ConcurrentMap<Class<?>, MethodHandle> CODER_MIXERS;
1657         private static final byte INITIAL_CODER;
1658         static final Class<?> STRING_HELPER;
1659 
1660         static {
1661             try {
1662                 STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
1663                 MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", byte.class);
1664                 INITIAL_CODER = (byte) initCoder.invoke();
1665             } catch (Throwable e) {
1666                 throw new AssertionError(e);
1667             }
1668 


< prev index next >