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
|