langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
author mcimadamore
Fri, 16 Dec 2016 15:27:47 +0000
changeset 42828 cce89649f958
parent 39920 4923274643f2
permissions -rw-r--r--
8171371: Remove redundant type-arguments from generic method calls Reviewed-by: jjg, rfield, mchung
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     1
/*
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     2
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     4
 *
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    10
 *
96661d1df628 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
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
96661d1df628 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
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    15
 * accompanied this code).
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    16
 *
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    20
 *
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    23
 * questions.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    24
 */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    25
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    26
package com.sun.tools.javac.jvm;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    27
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    28
import com.sun.tools.javac.code.*;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    29
import com.sun.tools.javac.comp.Resolve;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    30
import com.sun.tools.javac.tree.JCTree;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    31
import com.sun.tools.javac.tree.TreeInfo;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    32
import com.sun.tools.javac.tree.TreeMaker;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    33
import com.sun.tools.javac.util.*;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    34
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    35
import static com.sun.tools.javac.code.Kinds.Kind.MTH;
36495
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
    36
import static com.sun.tools.javac.code.TypeTag.*;
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    37
import static com.sun.tools.javac.jvm.ByteCodes.*;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    38
import static com.sun.tools.javac.tree.JCTree.Tag.PLUS;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    39
import com.sun.tools.javac.jvm.Items.*;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    40
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    41
import java.util.HashMap;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    42
import java.util.Map;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    43
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    44
/** This lowers the String concatenation to something that JVM can understand.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    45
 *
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    46
 *  <p><b>This is NOT part of any supported API.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    47
 *  If you write code that depends on this, you do so at your own risk.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    48
 *  This code and its internal interfaces are subject to change or
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    49
 *  deletion without notice.</b>
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    50
 */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    51
public abstract class StringConcat {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    52
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    53
    /**
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    54
     * Maximum number of slots for String Concat call.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    55
     * JDK's StringConcatFactory does not support more than that.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    56
     */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    57
    private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    58
    private static final char TAG_ARG   = '\u0001';
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    59
    private static final char TAG_CONST = '\u0002';
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    60
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    61
    protected final Gen gen;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    62
    protected final Symtab syms;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    63
    protected final Names names;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    64
    protected final TreeMaker make;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    65
    protected final Types types;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    66
    protected final Map<Type, Symbol> sbAppends;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    67
    protected final Resolve rs;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    68
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    69
    protected static final Context.Key<StringConcat> concatKey = new Context.Key<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    70
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    71
    public static StringConcat instance(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    72
        StringConcat instance = context.get(concatKey);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    73
        if (instance == null) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    74
            instance = makeConcat(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    75
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    76
        return instance;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    77
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    78
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    79
    private static StringConcat makeConcat(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    80
        Target target = Target.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    81
        String opt = Options.instance(context).get("stringConcat");
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    82
        if (target.hasStringConcatFactory()) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    83
            if (opt == null) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    84
                opt = "indyWithConstants";
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    85
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    86
        } else {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    87
            if (opt != null && !"inline".equals(opt)) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    88
                Assert.error("StringConcatFactory-based string concat is requested on a platform that does not support it.");
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    89
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    90
            opt = "inline";
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    91
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    92
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    93
        switch (opt) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    94
            case "inline":
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    95
                return new Inline(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    96
            case "indy":
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    97
                return new IndyPlain(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    98
            case "indyWithConstants":
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
    99
                return new IndyConstants(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   100
            default:
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   101
                Assert.error("Unknown stringConcat: " + opt);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   102
                throw new IllegalStateException("Unknown stringConcat: " + opt);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   103
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   104
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   105
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   106
    protected StringConcat(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   107
        context.put(concatKey, this);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   108
        gen = Gen.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   109
        syms = Symtab.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   110
        types = Types.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   111
        names = Names.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   112
        make = TreeMaker.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   113
        rs = Resolve.instance(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   114
        sbAppends = new HashMap<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   115
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   116
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   117
    public abstract Item makeConcat(JCTree.JCAssignOp tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   118
    public abstract Item makeConcat(JCTree.JCBinary tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   119
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   120
    protected List<JCTree> collectAll(JCTree tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   121
        return collect(tree, List.nil());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   122
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   123
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   124
    protected List<JCTree> collectAll(JCTree.JCExpression lhs, JCTree.JCExpression rhs) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   125
        return List.<JCTree>nil()
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   126
                .appendList(collectAll(lhs))
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   127
                .appendList(collectAll(rhs));
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   128
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   129
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   130
    private List<JCTree> collect(JCTree tree, List<JCTree> res) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   131
        tree = TreeInfo.skipParens(tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   132
        if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   133
            JCTree.JCBinary op = (JCTree.JCBinary) tree;
39920
4923274643f2 8161708: javac, consider a different way to handle access code for operators
vromero
parents: 36495
diff changeset
   134
            if (op.operator.kind == MTH && op.operator.opcode == string_add) {
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   135
                return res
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   136
                        .appendList(collect(op.lhs, res))
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   137
                        .appendList(collect(op.rhs, res));
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   138
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   139
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   140
        return res.append(tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   141
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   142
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   143
    /**
36495
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   144
     * If the type is not accessible from current context, try to figure out the
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   145
     * sharpest accessible supertype.
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   146
     *
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   147
     * @param originalType type to sharpen
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   148
     * @return sharped type
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   149
     */
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   150
    Type sharpestAccessible(Type originalType) {
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   151
        if (originalType.hasTag(ARRAY)) {
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   152
            return types.makeArrayType(sharpestAccessible(types.elemtype(originalType)));
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   153
        }
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   154
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   155
        Type type = originalType;
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   156
        while (!rs.isAccessible(gen.getAttrEnv(), type.asElement())) {
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   157
            type = types.supertype(type);
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   158
        }
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   159
        return type;
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   160
    }
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   161
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   162
    /**
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   163
     * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   164
     * concatenation.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   165
     */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   166
    private static class Inline extends StringConcat {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   167
        public Inline(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   168
            super(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   169
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   170
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   171
        @Override
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   172
        public Item makeConcat(JCTree.JCAssignOp tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   173
            // Generate code to make a string builder
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   174
            JCDiagnostic.DiagnosticPosition pos = tree.pos();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   175
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   176
            // Create a string builder.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   177
            newStringBuilder(tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   178
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   179
            // Generate code for first string, possibly save one
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   180
            // copy under builder
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   181
            Item l = gen.genExpr(tree.lhs, tree.lhs.type);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   182
            if (l.width() > 0) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   183
                gen.getCode().emitop0(dup_x1 + 3 * (l.width() - 1));
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   184
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   185
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   186
            // Load first string and append to builder.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   187
            l.load();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   188
            appendString(tree.lhs);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   189
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   190
            // Append all other strings to builder.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   191
            List<JCTree> args = collectAll(tree.rhs);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   192
            for (JCTree t : args) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   193
                gen.genExpr(t, t.type).load();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   194
                appendString(t);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   195
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   196
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   197
            // Convert builder to string.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   198
            builderToString(pos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   199
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   200
            return l;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   201
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   202
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   203
        @Override
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   204
        public Item makeConcat(JCTree.JCBinary tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   205
            JCDiagnostic.DiagnosticPosition pos = tree.pos();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   206
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   207
            // Create a string builder.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   208
            newStringBuilder(tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   209
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   210
            // Append all strings to builder.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   211
            List<JCTree> args = collectAll(tree);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   212
            for (JCTree t : args) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   213
                gen.genExpr(t, t.type).load();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   214
                appendString(t);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   215
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   216
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   217
            // Convert builder to string.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   218
            builderToString(pos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   219
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   220
            return gen.getItems().makeStackItem(syms.stringType);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   221
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   222
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   223
        private JCDiagnostic.DiagnosticPosition newStringBuilder(JCTree tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   224
            JCDiagnostic.DiagnosticPosition pos = tree.pos();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   225
            gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType));
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   226
            gen.getCode().emitop0(dup);
42828
cce89649f958 8171371: Remove redundant type-arguments from generic method calls
mcimadamore
parents: 39920
diff changeset
   227
            gen.callMethod(pos, syms.stringBuilderType, names.init, List.nil(), false);
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   228
            return pos;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   229
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   230
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   231
        private void appendString(JCTree tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   232
            Type t = tree.type.baseType();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   233
            if (!t.isPrimitive() && t.tsym != syms.stringType.tsym) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   234
                t = syms.objectType;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   235
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   236
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   237
            Assert.checkNull(t.constValue());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   238
            Symbol method = sbAppends.get(t);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   239
            if (method == null) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   240
                method = rs.resolveInternalMethod(tree.pos(), gen.getAttrEnv(), syms.stringBuilderType, names.append, List.of(t), null);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   241
                sbAppends.put(t, method);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   242
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   243
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   244
            gen.getItems().makeMemberItem(method, false).invoke();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   245
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   246
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   247
        private void builderToString(JCDiagnostic.DiagnosticPosition pos) {
42828
cce89649f958 8171371: Remove redundant type-arguments from generic method calls
mcimadamore
parents: 39920
diff changeset
   248
            gen.callMethod(pos, syms.stringBuilderType, names.toString, List.nil(), false);
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   249
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   250
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   251
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   252
    /**
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   253
     * Base class for indified concatenation bytecode flavors.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   254
     */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   255
    private static abstract class Indy extends StringConcat {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   256
        public Indy(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   257
            super(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   258
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   259
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   260
        @Override
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   261
        public Item makeConcat(JCTree.JCAssignOp tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   262
            List<JCTree> args = collectAll(tree.lhs, tree.rhs);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   263
            Item l = gen.genExpr(tree.lhs, tree.lhs.type);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   264
            emit(args, tree.type, tree.pos());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   265
            return l;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   266
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   267
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   268
        @Override
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   269
        public Item makeConcat(JCTree.JCBinary tree) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   270
            List<JCTree> args = collectAll(tree.lhs, tree.rhs);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   271
            emit(args, tree.type, tree.pos());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   272
            return gen.getItems().makeStackItem(syms.stringType);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   273
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   274
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   275
        protected abstract void emit(List<JCTree> args, Type type, JCDiagnostic.DiagnosticPosition pos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   276
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   277
        /** Peel the argument list into smaller chunks. */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   278
        protected List<List<JCTree>> split(List<JCTree> args) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   279
            ListBuffer<List<JCTree>> splits = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   280
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   281
            int slots = 0;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   282
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   283
            // Need to peel, so that neither call has more than acceptable number
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   284
            // of slots for the arguments.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   285
            ListBuffer<JCTree> cArgs = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   286
            for (JCTree t : args) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   287
                int needSlots = (t.type.getTag() == LONG || t.type.getTag() == DOUBLE) ? 2 : 1;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   288
                if (slots + needSlots >= MAX_INDY_CONCAT_ARG_SLOTS) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   289
                    splits.add(cArgs.toList());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   290
                    cArgs.clear();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   291
                    slots = 0;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   292
                }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   293
                cArgs.add(t);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   294
                slots += needSlots;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   295
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   296
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   297
            // Flush the tail slice
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   298
            if (!cArgs.isEmpty()) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   299
                splits.add(cArgs.toList());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   300
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   301
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   302
            return splits.toList();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   303
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   304
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   305
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   306
    /**
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   307
     * Emits the invokedynamic call to JDK java.lang.invoke.StringConcatFactory,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   308
     * without handling constants specially.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   309
     *
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   310
     * We bypass empty strings, because they have no meaning at this level. This
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   311
     * captures the Java language trick to force String concat with e.g. ("" + int)-like
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   312
     * expression. Down here, we already know we are in String concat business, and do
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   313
     * not require these markers.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   314
     */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   315
    private static class IndyPlain extends Indy {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   316
        public IndyPlain(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   317
            super(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   318
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   319
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   320
        /** Emit the indy concat for all these arguments, possibly peeling along the way */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   321
        protected void emit(List<JCTree> args, Type type, JCDiagnostic.DiagnosticPosition pos) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   322
            List<List<JCTree>> split = split(args);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   323
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   324
            for (List<JCTree> t : split) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   325
                Assert.check(!t.isEmpty(), "Arguments list is empty");
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   326
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   327
                ListBuffer<Type> dynamicArgs = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   328
                for (JCTree arg : t) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   329
                    Object constVal = arg.type.constValue();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   330
                    if ("".equals(constVal)) continue;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   331
                    if (arg.type == syms.botType) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   332
                        dynamicArgs.add(types.boxedClass(syms.voidType).type);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   333
                    } else {
36495
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   334
                        dynamicArgs.add(sharpestAccessible(arg.type));
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   335
                    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   336
                    gen.genExpr(arg, arg.type).load();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   337
                }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   338
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   339
                doCall(type, pos, dynamicArgs.toList());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   340
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   341
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   342
            // More that one peel slice produced: concatenate the results
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   343
            if (split.size() > 1) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   344
                ListBuffer<Type> argTypes = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   345
                for (int c = 0; c < split.size(); c++) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   346
                    argTypes.append(syms.stringType);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   347
                }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   348
                doCall(type, pos, argTypes.toList());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   349
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   350
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   351
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   352
        /** Produce the actual invokedynamic call to StringConcatFactory */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   353
        private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, List<Type> dynamicArgTypes) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   354
            Type.MethodType indyType = new Type.MethodType(dynamicArgTypes,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   355
                    type,
42828
cce89649f958 8171371: Remove redundant type-arguments from generic method calls
mcimadamore
parents: 39920
diff changeset
   356
                    List.nil(),
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   357
                    syms.methodClass);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   358
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   359
            int prevPos = make.pos;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   360
            try {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   361
                make.at(pos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   362
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   363
                List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   364
                        syms.stringType,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   365
                        syms.methodTypeType);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   366
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   367
                Symbol bsm = rs.resolveInternalMethod(pos,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   368
                        gen.getAttrEnv(),
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   369
                        syms.stringConcatFactory,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   370
                        names.makeConcat,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   371
                        bsm_staticArgs,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   372
                        null);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   373
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   374
                Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcat,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   375
                        syms.noSymbol,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   376
                        ClassFile.REF_invokeStatic,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   377
                        (Symbol.MethodSymbol)bsm,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   378
                        indyType,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   379
                        List.nil().toArray());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   380
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   381
                Items.Item item = gen.getItems().makeDynamicItem(dynSym);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   382
                item.invoke();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   383
            } finally {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   384
                make.at(prevPos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   385
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   386
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   387
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   388
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   389
    /**
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   390
     * Emits the invokedynamic call to JDK java.lang.invoke.StringConcatFactory.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   391
     * This code concatenates all known constants into the recipe, possibly escaping
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   392
     * some constants separately.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   393
     *
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   394
     * We also bypass empty strings, because they have no meaning at this level. This
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   395
     * captures the Java language trick to force String concat with e.g. ("" + int)-like
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   396
     * expression. Down here, we already know we are in String concat business, and do
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   397
     * not require these markers.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   398
     */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   399
    private static final class IndyConstants extends Indy {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   400
        public IndyConstants(Context context) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   401
            super(context);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   402
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   403
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   404
        @Override
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   405
        protected void emit(List<JCTree> args, Type type, JCDiagnostic.DiagnosticPosition pos) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   406
            List<List<JCTree>> split = split(args);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   407
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   408
            for (List<JCTree> t : split) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   409
                Assert.check(!t.isEmpty(), "Arguments list is empty");
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   410
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   411
                StringBuilder recipe = new StringBuilder(t.size());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   412
                ListBuffer<Type> dynamicArgs = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   413
                ListBuffer<Object> staticArgs = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   414
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   415
                for (JCTree arg : t) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   416
                    Object constVal = arg.type.constValue();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   417
                    if ("".equals(constVal)) continue;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   418
                    if (arg.type == syms.botType) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   419
                        // Concat the null into the recipe right away
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   420
                        recipe.append((String) null);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   421
                    } else if (constVal != null) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   422
                        // Concat the String representation of the constant, except
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   423
                        // for the case it contains special tags, which requires us
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   424
                        // to expose it as detached constant.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   425
                        String a = arg.type.stringValue();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   426
                        if (a.indexOf(TAG_CONST) != -1 || a.indexOf(TAG_ARG) != -1) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   427
                            recipe.append(TAG_CONST);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   428
                            staticArgs.add(a);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   429
                        } else {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   430
                            recipe.append(a);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   431
                        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   432
                    } else {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   433
                        // Ordinary arguments come through the dynamic arguments.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   434
                        recipe.append(TAG_ARG);
36495
dd9141ca331a 8151223: String concatenation fails with implicit toString() on package-private class
shade
parents: 35424
diff changeset
   435
                        dynamicArgs.add(sharpestAccessible(arg.type));
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   436
                        gen.genExpr(arg, arg.type).load();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   437
                    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   438
                }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   439
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   440
                doCall(type, pos, recipe.toString(), staticArgs.toList(), dynamicArgs.toList());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   441
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   442
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   443
            // More that one peel slice produced: concatenate the results
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   444
            // All arguments are assumed to be non-constant Strings.
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   445
            if (split.size() > 1) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   446
                ListBuffer<Type> argTypes = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   447
                StringBuilder recipe = new StringBuilder();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   448
                for (int c = 0; c < split.size(); c++) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   449
                    argTypes.append(syms.stringType);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   450
                    recipe.append(TAG_ARG);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   451
                }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   452
                doCall(type, pos, recipe.toString(), List.nil(), argTypes.toList());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   453
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   454
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   455
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   456
        /** Produce the actual invokedynamic call to StringConcatFactory */
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   457
        private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<Object> staticArgs, List<Type> dynamicArgTypes) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   458
            Type.MethodType indyType = new Type.MethodType(dynamicArgTypes,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   459
                    type,
42828
cce89649f958 8171371: Remove redundant type-arguments from generic method calls
mcimadamore
parents: 39920
diff changeset
   460
                    List.nil(),
35424
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   461
                    syms.methodClass);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   462
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   463
            int prevPos = make.pos;
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   464
            try {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   465
                make.at(pos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   466
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   467
                ListBuffer<Type> constTypes = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   468
                ListBuffer<Object> constants = new ListBuffer<>();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   469
                for (Object t : staticArgs) {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   470
                    constants.add(t);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   471
                    constTypes.add(syms.stringType);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   472
                }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   473
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   474
                List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   475
                        syms.stringType,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   476
                        syms.methodTypeType)
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   477
                        .append(syms.stringType)
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   478
                        .appendList(constTypes);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   479
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   480
                Symbol bsm = rs.resolveInternalMethod(pos,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   481
                        gen.getAttrEnv(),
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   482
                        syms.stringConcatFactory,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   483
                        names.makeConcatWithConstants,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   484
                        bsm_staticArgs,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   485
                        null);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   486
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   487
                Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcatWithConstants,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   488
                        syms.noSymbol,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   489
                        ClassFile.REF_invokeStatic,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   490
                        (Symbol.MethodSymbol)bsm,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   491
                        indyType,
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   492
                        List.<Object>of(recipe).appendList(constants).toArray());
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   493
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   494
                Items.Item item = gen.getItems().makeDynamicItem(dynSym);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   495
                item.invoke();
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   496
            } finally {
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   497
                make.at(prevPos);
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   498
            }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   499
        }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   500
    }
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   501
96661d1df628 8148483: JEP 280: Indify String Concatenation
shade
parents:
diff changeset
   502
}