src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java
author darcy
Mon, 09 Sep 2019 10:13:42 -0700
changeset 58054 ee230ad8cfef
parent 54677 beca9f8524c1
child 59201 b24f4caa1411
permissions -rw-r--r--
8230723: Remove default constructors from java.lang and java.io Reviewed-by: bpb, rriggs
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     1
/*
58054
ee230ad8cfef 8230723: Remove default constructors from java.lang and java.io
darcy
parents: 54677
diff changeset
     2
 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     4
 *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    10
 *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    15
 * accompanied this code).
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    16
 *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    20
 *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    23
 * questions.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    24
 */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    25
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    26
package java.lang.invoke;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    27
54677
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
    28
import jdk.internal.access.SharedSecrets;
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    29
import jdk.internal.loader.BootLoader;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    30
import jdk.internal.org.objectweb.asm.ClassWriter;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    31
import jdk.internal.org.objectweb.asm.FieldVisitor;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    32
import jdk.internal.org.objectweb.asm.MethodVisitor;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    33
import jdk.internal.vm.annotation.Stable;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    34
import sun.invoke.util.BytecodeName;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    35
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    36
import java.lang.reflect.Constructor;
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    37
import java.lang.reflect.Field;
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    38
import java.lang.reflect.Modifier;
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    39
import java.security.AccessController;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    40
import java.security.PrivilegedAction;
54677
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
    41
import java.security.ProtectionDomain;
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    42
import java.util.ArrayList;
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    43
import java.util.Collections;
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    44
import java.util.List;
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
    45
import java.util.Objects;
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    46
import java.util.concurrent.ConcurrentHashMap;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    47
import java.util.function.Function;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    48
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    49
import static java.lang.invoke.LambdaForm.*;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    50
import static java.lang.invoke.MethodHandleNatives.Constants.REF_getStatic;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    51
import static java.lang.invoke.MethodHandleNatives.Constants.REF_putStatic;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    52
import static java.lang.invoke.MethodHandleStatics.*;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    53
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    54
import static jdk.internal.org.objectweb.asm.Opcodes.*;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    55
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    56
/**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    57
 * Class specialization code.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    58
 * @param <T> top class under which species classes are created.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    59
 * @param <K> key which identifies individual specializations.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    60
 * @param <S> species data type.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    61
 */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    62
/*non-public*/
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    63
abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesData> {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    64
    private final Class<T> topClass;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    65
    private final Class<K> keyType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    66
    private final Class<S> metaType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    67
    private final MemberName sdAccessor;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    68
    private final String sdFieldName;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    69
    private final List<MemberName> transformMethods;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    70
    private final MethodType baseConstructorType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    71
    private final S topSpecies;
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
    72
    private final ConcurrentHashMap<K, Object> cache = new ConcurrentHashMap<>();
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    73
    private final Factory factory;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    74
    private @Stable boolean topClassIsSuper;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    75
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    76
    /** Return the top type mirror, for type {@code T} */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    77
    public final Class<T> topClass() { return topClass; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    78
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    79
    /** Return the key type mirror, for type {@code K} */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    80
    public final Class<K> keyType() { return keyType; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    81
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    82
    /** Return the species metadata type mirror, for type {@code S} */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    83
    public final Class<S> metaType() { return metaType; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    84
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    85
    /** Report the leading arguments (if any) required by every species factory.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    86
     * Every species factory adds its own field types as additional arguments,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    87
     * but these arguments always come first, in every factory method.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    88
     */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    89
    protected MethodType baseConstructorType() { return baseConstructorType; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    90
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    91
    /** Return the trivial species for the null sequence of arguments. */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    92
    protected final S topSpecies() { return topSpecies; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    93
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    94
    /** Return the list of transform methods originally given at creation of this specializer. */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    95
    protected final List<MemberName> transformMethods() { return transformMethods; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    96
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    97
    /** Return the factory object used to build and load concrete species code. */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    98
    protected final Factory factory() { return factory; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
    99
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   100
    /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   101
     * Constructor for this class specializer.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   102
     * @param topClass type mirror for T
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   103
     * @param keyType type mirror for K
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   104
     * @param metaType type mirror for S
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   105
     * @param baseConstructorType principal constructor type
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   106
     * @param sdAccessor the method used to get the speciesData
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   107
     * @param sdFieldName the name of the species data field, inject the speciesData object
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   108
     * @param transformMethods optional list of transformMethods
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   109
     */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   110
    protected ClassSpecializer(Class<T> topClass,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   111
                               Class<K> keyType,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   112
                               Class<S> metaType,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   113
                               MethodType baseConstructorType,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   114
                               MemberName sdAccessor,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   115
                               String sdFieldName,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   116
                               List<MemberName> transformMethods) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   117
        this.topClass = topClass;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   118
        this.keyType = keyType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   119
        this.metaType = metaType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   120
        this.sdAccessor = sdAccessor;
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   121
        this.transformMethods = List.copyOf(transformMethods);
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   122
        this.sdFieldName = sdFieldName;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   123
        this.baseConstructorType = baseConstructorType.changeReturnType(void.class);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   124
        this.factory = makeFactory();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   125
        K tsk = topSpeciesKey();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   126
        S topSpecies = null;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   127
        if (tsk != null && topSpecies == null) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   128
            // if there is a key, build the top species if needed:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   129
            topSpecies = findSpecies(tsk);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   130
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   131
        this.topSpecies = topSpecies;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   132
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   133
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   134
    // Utilities for subclass constructors:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   135
    protected static <T> Constructor<T> reflectConstructor(Class<T> defc, Class<?>... ptypes) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   136
        try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   137
            return defc.getDeclaredConstructor(ptypes);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   138
        } catch (NoSuchMethodException ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   139
            throw newIAE(defc.getName()+"("+MethodType.methodType(void.class, ptypes)+")", ex);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   140
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   141
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   142
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   143
    protected static Field reflectField(Class<?> defc, String name) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   144
        try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   145
            return defc.getDeclaredField(name);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   146
        } catch (NoSuchFieldException ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   147
            throw newIAE(defc.getName()+"."+name, ex);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   148
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   149
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   150
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   151
    private static RuntimeException newIAE(String message, Throwable cause) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   152
        return new IllegalArgumentException(message, cause);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   153
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   154
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   155
    private static final Function<Object, Object> CREATE_RESERVATION = new Function<>() {
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   156
        @Override
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   157
        public Object apply(Object key) {
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   158
            return new Object();
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   159
        }
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   160
    };
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   161
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   162
    public final S findSpecies(K key) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   163
        // Note:  Species instantiation may throw VirtualMachineError because of
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   164
        // code cache overflow.  If this happens the species bytecode may be
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   165
        // loaded but not linked to its species metadata (with MH's etc).
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   166
        // That will cause a throw out of Factory.loadSpecies.
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   167
        //
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   168
        // In a later attempt to get the same species, the already-loaded
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   169
        // class will be present in the system dictionary, causing an
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   170
        // error when the species generator tries to reload it.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   171
        // We try to detect this case and link the pre-existing code.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   172
        //
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   173
        // Although it would be better to start fresh by loading a new
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   174
        // copy, we have to salvage the previously loaded but broken code.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   175
        // (As an alternative, we might spin a new class with a new name,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   176
        // or use the anonymous class mechanism.)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   177
        //
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   178
        // In the end, as long as everybody goes through this findSpecies method,
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   179
        // it will ensure only one SpeciesData will be set successfully on a
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   180
        // concrete class if ever.
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   181
        // The concrete class is published via SpeciesData instance
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   182
        // returned here only after the class and species data are linked together.
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   183
        Object speciesDataOrReservation = cache.computeIfAbsent(key, CREATE_RESERVATION);
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   184
        // Separating the creation of a placeholder SpeciesData instance above
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   185
        // from the loading and linking a real one below ensures we can never
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   186
        // accidentally call computeIfAbsent recursively.
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   187
        S speciesData;
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   188
        if (speciesDataOrReservation.getClass() == Object.class) {
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   189
            synchronized (speciesDataOrReservation) {
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   190
                Object existingSpeciesData = cache.get(key);
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   191
                if (existingSpeciesData == speciesDataOrReservation) { // won the race
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   192
                    // create a new SpeciesData...
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   193
                    speciesData = newSpeciesData(key);
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   194
                    // load and link it...
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   195
                    speciesData = factory.loadSpecies(speciesData);
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   196
                    if (!cache.replace(key, existingSpeciesData, speciesData)) {
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   197
                        throw newInternalError("Concurrent loadSpecies");
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   198
                    }
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   199
                } else { // lost the race; the retrieved existingSpeciesData is the final
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   200
                    speciesData = metaType.cast(existingSpeciesData);
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   201
                }
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   202
            }
50050
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   203
        } else {
0d4920ac269c 8202548: Use reservation Object when creating SpeciesData
redestad
parents: 49885
diff changeset
   204
            speciesData = metaType.cast(speciesDataOrReservation);
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   205
        }
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   206
        assert(speciesData != null && speciesData.isResolved());
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   207
        return speciesData;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   208
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   209
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   210
    /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   211
     * Meta-data wrapper for concrete subtypes of the top class.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   212
     * Each concrete subtype corresponds to a given sequence of basic field types (LIJFD).
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   213
     * The fields are immutable; their values are fully specified at object construction.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   214
     * Each species supplies an array of getter functions which may be used in lambda forms.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   215
     * A concrete value is always constructed from the full tuple of its field values,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   216
     * accompanied by the required constructor parameters.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   217
     * There *may* also be transforms which cloning a species instance and
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   218
     * either replace a constructor parameter or add one or more new field values.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   219
     * The shortest possible species has zero fields.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   220
     * Subtypes are not interrelated among themselves by subtyping, even though
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   221
     * it would appear that a shorter species could serve as a supertype of a
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   222
     * longer one which extends it.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   223
     */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   224
    public abstract class SpeciesData {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   225
        // Bootstrapping requires circular relations Class -> SpeciesData -> Class
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   226
        // Therefore, we need non-final links in the chain.  Use @Stable fields.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   227
        private final K key;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   228
        private final List<Class<?>> fieldTypes;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   229
        @Stable private Class<? extends T> speciesCode;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   230
        @Stable private List<MethodHandle> factories;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   231
        @Stable private List<MethodHandle> getters;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   232
        @Stable private List<LambdaForm.NamedFunction> nominalGetters;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   233
        @Stable private final MethodHandle[] transformHelpers = new MethodHandle[transformMethods.size()];
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   234
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   235
        protected SpeciesData(K key) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   236
            this.key = keyType.cast(Objects.requireNonNull(key));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   237
            List<Class<?>> types = deriveFieldTypes(key);
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   238
            this.fieldTypes = List.copyOf(types);
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   239
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   240
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   241
        public final K key() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   242
            return key;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   243
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   244
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   245
        protected final List<Class<?>> fieldTypes() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   246
            return fieldTypes;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   247
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   248
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   249
        protected final int fieldCount() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   250
            return fieldTypes.size();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   251
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   252
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   253
        protected ClassSpecializer<T,K,S> outer() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   254
            return ClassSpecializer.this;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   255
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   256
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   257
        protected final boolean isResolved() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   258
            return speciesCode != null && factories != null && !factories.isEmpty();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   259
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   260
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   261
        @Override public String toString() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   262
            return metaType.getSimpleName() + "[" + key.toString() + " => " + (isResolved() ? speciesCode.getSimpleName() : "UNRESOLVED") + "]";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   263
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   264
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   265
        @Override
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   266
        public int hashCode() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   267
            return key.hashCode();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   268
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   269
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   270
        @Override
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   271
        public boolean equals(Object obj) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   272
            if (!(obj instanceof ClassSpecializer.SpeciesData)) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   273
                return false;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   274
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   275
            @SuppressWarnings("rawtypes")
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   276
            ClassSpecializer.SpeciesData that = (ClassSpecializer.SpeciesData) obj;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   277
            return this.outer() == that.outer() && this.key.equals(that.key);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   278
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   279
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   280
        /** Throws NPE if this species is not yet resolved. */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   281
        protected final Class<? extends T> speciesCode() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   282
            return Objects.requireNonNull(speciesCode);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   283
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   284
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   285
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   286
         * Return a {@link MethodHandle} which can get the indexed field of this species.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   287
         * The return type is the type of the species field it accesses.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   288
         * The argument type is the {@code fieldHolder} class of this species.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   289
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   290
        protected MethodHandle getter(int i) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   291
            return getters.get(i);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   292
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   293
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   294
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   295
         * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   296
         * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   297
         * getter.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   298
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   299
        protected LambdaForm.NamedFunction getterFunction(int i) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   300
            LambdaForm.NamedFunction nf = nominalGetters.get(i);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   301
            assert(nf.memberDeclaringClassOrNull() == speciesCode());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   302
            assert(nf.returnType() == BasicType.basicType(fieldTypes.get(i)));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   303
            return nf;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   304
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   305
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   306
        protected List<LambdaForm.NamedFunction> getterFunctions() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   307
            return nominalGetters;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   308
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   309
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   310
        protected List<MethodHandle> getters() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   311
            return getters;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   312
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   313
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   314
        protected MethodHandle factory() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   315
            return factories.get(0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   316
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   317
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   318
        protected MethodHandle transformHelper(int whichtm) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   319
            MethodHandle mh = transformHelpers[whichtm];
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   320
            if (mh != null)  return mh;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   321
            mh = deriveTransformHelper(transformMethods().get(whichtm), whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   322
            // Do a little type checking before we start using the MH.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   323
            // (It will be called with invokeBasic, so this is our only chance.)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   324
            final MethodType mt = transformHelperType(whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   325
            mh = mh.asType(mt);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   326
            return transformHelpers[whichtm] = mh;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   327
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   328
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   329
        private final MethodType transformHelperType(int whichtm) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   330
            MemberName tm = transformMethods().get(whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   331
            ArrayList<Class<?>> args = new ArrayList<>();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   332
            ArrayList<Class<?>> fields = new ArrayList<>();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   333
            Collections.addAll(args, tm.getParameterTypes());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   334
            fields.addAll(fieldTypes());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   335
            List<Class<?>> helperArgs = deriveTransformHelperArguments(tm, whichtm, args, fields);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   336
            return MethodType.methodType(tm.getReturnType(), helperArgs);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   337
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   338
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   339
        // Hooks for subclasses:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   340
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   341
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   342
         * Given a key, derive the list of field types, which all instances of this
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   343
         * species must store.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   344
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   345
        protected abstract List<Class<?>> deriveFieldTypes(K key);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   346
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   347
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   348
         * Given the index of a method in the transforms list, supply a factory
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   349
         * method that takes the arguments of the transform, plus the local fields,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   350
         * and produce a value of the required type.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   351
         * You can override this to return null or throw if there are no transforms.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   352
         * This method exists so that the transforms can be "grown" lazily.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   353
         * This is necessary if the transform *adds* a field to an instance,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   354
         * which sometimtes requires the creation, on the fly, of an extended species.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   355
         * This method is only called once for any particular parameter.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   356
         * The species caches the result in a private array.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   357
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   358
         * @param transform the transform being implemented
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   359
         * @param whichtm the index of that transform in the original list of transforms
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   360
         * @return the method handle which creates a new result from a mix of transform
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   361
         * arguments and field values
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   362
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   363
        protected abstract MethodHandle deriveTransformHelper(MemberName transform, int whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   364
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   365
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   366
         * During code generation, this method is called once per transform to determine
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   367
         * what is the mix of arguments to hand to the transform-helper.  The bytecode
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   368
         * which marshals these arguments is open-coded in the species-specific transform.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   369
         * The two lists are of opaque objects, which you shouldn't do anything with besides
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   370
         * reordering them into the output list.  (They are both mutable, to make editing
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   371
         * easier.)  The imputed types of the args correspond to the transform's parameter
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   372
         * list, while the imputed types of the fields correspond to the species field types.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   373
         * After code generation, this method may be called occasionally by error-checking code.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   374
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   375
         * @param transform the transform being implemented
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   376
         * @param whichtm the index of that transform in the original list of transforms
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   377
         * @param args a list of opaque objects representing the incoming transform arguments
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   378
         * @param fields a list of opaque objects representing the field values of the receiver
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   379
         * @param <X> the common element type of the various lists
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   380
         * @return a new list
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   381
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   382
        protected abstract <X> List<X> deriveTransformHelperArguments(MemberName transform, int whichtm,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   383
                                                                      List<X> args, List<X> fields);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   384
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   385
        /** Given a key, generate the name of the class which implements the species for that key.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   386
         * This algorithm must be stable.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   387
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   388
         * @return class name, which by default is {@code outer().topClass().getName() + "$Species_" + deriveTypeString(key)}
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   389
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   390
        protected String deriveClassName() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   391
            return outer().topClass().getName() + "$Species_" + deriveTypeString();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   392
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   393
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   394
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   395
         * Default implementation collects basic type characters,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   396
         * plus possibly type names, if some types don't correspond
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   397
         * to basic types.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   398
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   399
         * @return a string suitable for use in a class name
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   400
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   401
        protected String deriveTypeString() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   402
            List<Class<?>> types = fieldTypes();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   403
            StringBuilder buf = new StringBuilder();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   404
            StringBuilder end = new StringBuilder();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   405
            for (Class<?> type : types) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   406
                BasicType basicType = BasicType.basicType(type);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   407
                if (basicType.basicTypeClass() == type) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   408
                    buf.append(basicType.basicTypeChar());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   409
                } else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   410
                    buf.append('V');
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   411
                    end.append(classSig(type));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   412
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   413
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   414
            String typeString;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   415
            if (end.length() > 0) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   416
                typeString = BytecodeName.toBytecodeName(buf.append("_").append(end).toString());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   417
            } else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   418
                typeString = buf.toString();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   419
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   420
            return LambdaForm.shortenSignature(typeString);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   421
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   422
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   423
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   424
         * Report what immediate super-class to use for the concrete class of this species.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   425
         * Normally this is {@code topClass}, but if that is an interface, the factory must override.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   426
         * The super-class must provide a constructor which takes the {@code baseConstructorType} arguments, if any.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   427
         * This hook also allows the code generator to use more than one canned supertype for species.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   428
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   429
         * @return the super-class of the class to be generated
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   430
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   431
        protected Class<? extends T> deriveSuperClass() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   432
            final Class<T> topc = topClass();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   433
            if (!topClassIsSuper) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   434
                try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   435
                    final Constructor<T> con = reflectConstructor(topc, baseConstructorType().parameterArray());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   436
                    if (!topc.isInterface() && !Modifier.isPrivate(con.getModifiers())) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   437
                        topClassIsSuper = true;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   438
                    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   439
                } catch (Exception|InternalError ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   440
                    // fall through...
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   441
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   442
                if (!topClassIsSuper) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   443
                    throw newInternalError("must override if the top class cannot serve as a super class");
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   444
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   445
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   446
            return topc;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   447
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   448
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   449
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   450
    protected abstract S newSpeciesData(K key);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   451
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   452
    protected K topSpeciesKey() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   453
        return null;  // null means don't report a top species
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   454
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   455
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   456
    /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   457
     * Code generation support for instances.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   458
     * Subclasses can modify the behavior.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   459
     */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   460
    public class Factory {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   461
        /**
58054
ee230ad8cfef 8230723: Remove default constructors from java.lang and java.io
darcy
parents: 54677
diff changeset
   462
         * Constructs a factory.
ee230ad8cfef 8230723: Remove default constructors from java.lang and java.io
darcy
parents: 54677
diff changeset
   463
         */
ee230ad8cfef 8230723: Remove default constructors from java.lang and java.io
darcy
parents: 54677
diff changeset
   464
        Factory() {}
ee230ad8cfef 8230723: Remove default constructors from java.lang and java.io
darcy
parents: 54677
diff changeset
   465
ee230ad8cfef 8230723: Remove default constructors from java.lang and java.io
darcy
parents: 54677
diff changeset
   466
        /**
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   467
         * Get a concrete subclass of the top class for a given combination of bound types.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   468
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   469
         * @param speciesData the species requiring the class, not yet linked
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   470
         * @return a linked version of the same species
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   471
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   472
        S loadSpecies(S speciesData) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   473
            String className = speciesData.deriveClassName();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   474
            assert(className.indexOf('/') < 0) : className;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   475
            Class<?> salvage = null;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   476
            try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   477
                salvage = BootLoader.loadClassOrNull(className);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   478
                if (TRACE_RESOLVE && salvage != null) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   479
                    // Used by jlink species pregeneration plugin, see
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   480
                    // jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   481
                    System.out.println("[SPECIES_RESOLVE] " + className + " (salvaged)");
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   482
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   483
            } catch (Error ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   484
                if (TRACE_RESOLVE) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   485
                    System.out.println("[SPECIES_FRESOLVE] " + className + " (Error) " + ex.getMessage());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   486
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   487
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   488
            final Class<? extends T> speciesCode;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   489
            if (salvage != null) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   490
                speciesCode = salvage.asSubclass(topClass());
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   491
                linkSpeciesDataToCode(speciesData, speciesCode);
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   492
                linkCodeToSpeciesData(speciesCode, speciesData, true);
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   493
            } else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   494
                // Not pregenerated, generate the class
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   495
                try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   496
                    speciesCode = generateConcreteSpeciesCode(className, speciesData);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   497
                    if (TRACE_RESOLVE) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   498
                        // Used by jlink species pregeneration plugin, see
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   499
                        // jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   500
                        System.out.println("[SPECIES_RESOLVE] " + className + " (generated)");
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   501
                    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   502
                    // This operation causes a lot of churn:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   503
                    linkSpeciesDataToCode(speciesData, speciesCode);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   504
                    // This operation commits the relation, but causes little churn:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   505
                    linkCodeToSpeciesData(speciesCode, speciesData, false);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   506
                } catch (Error ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   507
                    if (TRACE_RESOLVE) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   508
                        System.out.println("[SPECIES_RESOLVE] " + className + " (Error #2)" );
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   509
                    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   510
                    // We can get here if there is a race condition loading a class.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   511
                    // Or maybe we are out of resources.  Back out of the CHM.get and retry.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   512
                    throw ex;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   513
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   514
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   515
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   516
            if (!speciesData.isResolved()) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   517
                throw newInternalError("bad species class linkage for " + className + ": " + speciesData);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   518
            }
49885
b2e74972c7d4 8202184: Reduce time blocking the ClassSpecializer cache creating SpeciesData
redestad
parents: 47753
diff changeset
   519
            assert(speciesData == loadSpeciesDataFromCode(speciesCode));
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   520
            return speciesData;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   521
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   522
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   523
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   524
         * Generate a concrete subclass of the top class for a given combination of bound types.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   525
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   526
         * A concrete species subclass roughly matches the following schema:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   527
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   528
         * <pre>
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   529
         * class Species_[[types]] extends [[T]] {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   530
         *     final [[S]] speciesData() { return ... }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   531
         *     static [[T]] make([[fields]]) { return ... }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   532
         *     [[fields]]
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   533
         *     final [[T]] transform([[args]]) { return ... }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   534
         * }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   535
         * </pre>
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   536
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   537
         * The {@code [[types]]} signature is precisely the key for the species.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   538
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   539
         * The {@code [[fields]]} section consists of one field definition per character in
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   540
         * the type signature, adhering to the naming schema described in the definition of
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   541
         * {@link #chooseFieldName}.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   542
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   543
         * For example, a concrete species for two references and one integral bound value
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   544
         * has a shape like the following:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   545
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   546
         * <pre>
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   547
         * class TopClass { ... private static
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   548
         * final class Species_LLI extends TopClass {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   549
         *     final Object argL0;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   550
         *     final Object argL1;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   551
         *     final int argI2;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   552
         *     private Species_LLI(CT ctarg, ..., Object argL0, Object argL1, int argI2) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   553
         *         super(ctarg, ...);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   554
         *         this.argL0 = argL0;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   555
         *         this.argL1 = argL1;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   556
         *         this.argI2 = argI2;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   557
         *     }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   558
         *     final SpeciesData speciesData() { return BMH_SPECIES; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   559
         *     &#64;Stable static SpeciesData BMH_SPECIES; // injected afterwards
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   560
         *     static TopClass make(CT ctarg, ..., Object argL0, Object argL1, int argI2) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   561
         *         return new Species_LLI(ctarg, ..., argL0, argL1, argI2);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   562
         *     }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   563
         *     final TopClass copyWith(CT ctarg, ...) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   564
         *         return new Species_LLI(ctarg, ..., argL0, argL1, argI2);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   565
         *     }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   566
         *     // two transforms, for the sake of illustration:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   567
         *     final TopClass copyWithExtendL(CT ctarg, ..., Object narg) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   568
         *         return BMH_SPECIES.transform(L_TYPE).invokeBasic(ctarg, ..., argL0, argL1, argI2, narg);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   569
         *     }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   570
         *     final TopClass copyWithExtendI(CT ctarg, ..., int narg) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   571
         *         return BMH_SPECIES.transform(I_TYPE).invokeBasic(ctarg, ..., argL0, argL1, argI2, narg);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   572
         *     }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   573
         * }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   574
         * </pre>
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   575
         *
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   576
         * @param className of the species
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   577
         * @param speciesData what species we are generating
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   578
         * @return the generated concrete TopClass class
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   579
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   580
        Class<? extends T> generateConcreteSpeciesCode(String className, ClassSpecializer<T,K,S>.SpeciesData speciesData) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   581
            byte[] classFile = generateConcreteSpeciesCodeFile(className, speciesData);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   582
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   583
            // load class
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   584
            InvokerBytecodeGenerator.maybeDump(classBCName(className), classFile);
54677
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   585
            ClassLoader cl = topClass.getClassLoader();
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   586
            ProtectionDomain pd = null;
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   587
            if (cl != null) {
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   588
                pd = AccessController.doPrivileged(
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   589
                        new PrivilegedAction<>() {
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   590
                            @Override
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   591
                            public ProtectionDomain run() {
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   592
                                return topClass().getProtectionDomain();
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   593
                            }
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   594
                        });
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   595
            }
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   596
            Class<?> speciesCode = SharedSecrets.getJavaLangAccess()
beca9f8524c1 8222895: StackOverflowError in custom security manager that relies on ClassSpecializer
redestad
parents: 52220
diff changeset
   597
                    .defineClass(cl, className, classFile, pd, "_ClassSpecializer_generateConcreteSpeciesCode");
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   598
            return speciesCode.asSubclass(topClass());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   599
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   600
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   601
        // These are named like constants because there is only one per specialization scheme:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   602
        private final String SPECIES_DATA = classBCName(metaType);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   603
        private final String SPECIES_DATA_SIG = classSig(SPECIES_DATA);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   604
        private final String SPECIES_DATA_NAME = sdAccessor.getName();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   605
        private final int SPECIES_DATA_MODS = sdAccessor.getModifiers();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   606
        private final List<String> TRANSFORM_NAMES;  // derived from transformMethods
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   607
        private final List<MethodType> TRANSFORM_TYPES;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   608
        private final List<Integer> TRANSFORM_MODS;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   609
        {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   610
            // Tear apart transformMethods to get the names, types, and modifiers.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   611
            List<String> tns = new ArrayList<>();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   612
            List<MethodType> tts = new ArrayList<>();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   613
            List<Integer> tms = new ArrayList<>();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   614
            for (int i = 0; i < transformMethods.size(); i++) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   615
                MemberName tm = transformMethods.get(i);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   616
                tns.add(tm.getName());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   617
                final MethodType tt = tm.getMethodType();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   618
                tts.add(tt);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   619
                tms.add(tm.getModifiers());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   620
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   621
            TRANSFORM_NAMES = List.of(tns.toArray(new String[0]));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   622
            TRANSFORM_TYPES = List.of(tts.toArray(new MethodType[0]));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   623
            TRANSFORM_MODS = List.of(tms.toArray(new Integer[0]));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   624
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   625
        private static final int ACC_PPP = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   626
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   627
        /*non-public*/ byte[] generateConcreteSpeciesCodeFile(String className0, ClassSpecializer<T,K,S>.SpeciesData speciesData) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   628
            final String className = classBCName(className0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   629
            final String superClassName = classBCName(speciesData.deriveSuperClass());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   630
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   631
            final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   632
            final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   633
            cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, superClassName, null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   634
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   635
            final String sourceFile = className.substring(className.lastIndexOf('.')+1);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   636
            cw.visitSource(sourceFile, null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   637
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   638
            // emit static types and BMH_SPECIES fields
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   639
            FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, sdFieldName, SPECIES_DATA_SIG, null, null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   640
            fw.visitAnnotation(STABLE_SIG, true);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   641
            fw.visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   642
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   643
            // handy holder for dealing with groups of typed values (ctor arguments and fields)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   644
            class Var {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   645
                final int index;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   646
                final String name;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   647
                final Class<?> type;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   648
                final String desc;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   649
                final BasicType basicType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   650
                final int slotIndex;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   651
                Var(int index, int slotIndex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   652
                    this.index = index;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   653
                    this.slotIndex = slotIndex;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   654
                    name = null; type = null; desc = null;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   655
                    basicType = BasicType.V_TYPE;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   656
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   657
                Var(String name, Class<?> type, Var prev) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   658
                    int slotIndex = prev.nextSlotIndex();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   659
                    int index = prev.nextIndex();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   660
                    if (name == null)  name = "x";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   661
                    if (name.endsWith("#"))
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   662
                        name = name.substring(0, name.length()-1) + index;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   663
                    assert(!type.equals(void.class));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   664
                    String desc = classSig(type);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   665
                    BasicType basicType = BasicType.basicType(type);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   666
                    this.index = index;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   667
                    this.name = name;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   668
                    this.type = type;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   669
                    this.desc = desc;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   670
                    this.basicType = basicType;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   671
                    this.slotIndex = slotIndex;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   672
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   673
                Var lastOf(List<Var> vars) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   674
                    int n = vars.size();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   675
                    return (n == 0 ? this : vars.get(n-1));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   676
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   677
                <X> List<Var> fromTypes(List<X> types) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   678
                    Var prev = this;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   679
                    ArrayList<Var> result = new ArrayList<>(types.size());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   680
                    int i = 0;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   681
                    for (X x : types) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   682
                        String vn = name;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   683
                        Class<?> vt;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   684
                        if (x instanceof Class) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   685
                            vt = (Class<?>) x;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   686
                            // make the names friendlier if debugging
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   687
                            assert((vn = vn + "_" + (i++)) != null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   688
                        } else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   689
                            @SuppressWarnings("unchecked")
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   690
                            Var v = (Var) x;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   691
                            vn = v.name;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   692
                            vt = v.type;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   693
                        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   694
                        prev = new Var(vn, vt, prev);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   695
                        result.add(prev);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   696
                    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   697
                    return result;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   698
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   699
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   700
                int slotSize() { return basicType.basicTypeSlots(); }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   701
                int nextIndex() { return index + (slotSize() == 0 ? 0 : 1); }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   702
                int nextSlotIndex() { return slotIndex >= 0 ? slotIndex + slotSize() : slotIndex; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   703
                boolean isInHeap() { return slotIndex < 0; }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   704
                void emitVarInstruction(int asmop, MethodVisitor mv) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   705
                    if (asmop == ALOAD)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   706
                        asmop = typeLoadOp(basicType.basicTypeChar());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   707
                    else
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   708
                        throw new AssertionError("bad op="+asmop+" for desc="+desc);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   709
                    mv.visitVarInsn(asmop, slotIndex);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   710
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   711
                public void emitFieldInsn(int asmop, MethodVisitor mv) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   712
                    mv.visitFieldInsn(asmop, className, name, desc);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   713
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   714
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   715
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   716
            final Var NO_THIS = new Var(0, 0),
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   717
                    AFTER_THIS = new Var(0, 1),
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   718
                    IN_HEAP = new Var(0, -1);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   719
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   720
            // figure out the field types
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   721
            final List<Class<?>> fieldTypes = speciesData.fieldTypes();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   722
            final List<Var> fields = new ArrayList<>(fieldTypes.size());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   723
            {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   724
                Var nextF = IN_HEAP;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   725
                for (Class<?> ft : fieldTypes) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   726
                    String fn = chooseFieldName(ft, nextF.nextIndex());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   727
                    nextF = new Var(fn, ft, nextF);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   728
                    fields.add(nextF);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   729
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   730
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   731
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   732
            // emit bound argument fields
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   733
            for (Var field : fields) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   734
                cw.visitField(ACC_FINAL, field.name, field.desc, null, null).visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   735
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   736
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   737
            MethodVisitor mv;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   738
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   739
            // emit implementation of speciesData()
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   740
            mv = cw.visitMethod((SPECIES_DATA_MODS & ACC_PPP) + ACC_FINAL,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   741
                    SPECIES_DATA_NAME, "()" + SPECIES_DATA_SIG, null, null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   742
            mv.visitCode();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   743
            mv.visitFieldInsn(GETSTATIC, className, sdFieldName, SPECIES_DATA_SIG);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   744
            mv.visitInsn(ARETURN);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   745
            mv.visitMaxs(0, 0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   746
            mv.visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   747
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   748
            // figure out the constructor arguments
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   749
            MethodType superCtorType = ClassSpecializer.this.baseConstructorType();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   750
            MethodType thisCtorType = superCtorType.appendParameterTypes(fieldTypes);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   751
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   752
            // emit constructor
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   753
            {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   754
                mv = cw.visitMethod(ACC_PRIVATE,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   755
                        "<init>", methodSig(thisCtorType), null, null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   756
                mv.visitCode();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   757
                mv.visitVarInsn(ALOAD, 0); // this
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   758
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   759
                final List<Var> ctorArgs = AFTER_THIS.fromTypes(superCtorType.parameterList());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   760
                for (Var ca : ctorArgs) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   761
                    ca.emitVarInstruction(ALOAD, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   762
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   763
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   764
                // super(ca...)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   765
                mv.visitMethodInsn(INVOKESPECIAL, superClassName,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   766
                        "<init>", methodSig(superCtorType), false);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   767
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   768
                // store down fields
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   769
                Var lastFV = AFTER_THIS.lastOf(ctorArgs);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   770
                for (Var f : fields) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   771
                    // this.argL1 = argL1
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   772
                    mv.visitVarInsn(ALOAD, 0);  // this
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   773
                    lastFV = new Var(f.name, f.type, lastFV);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   774
                    lastFV.emitVarInstruction(ALOAD, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   775
                    f.emitFieldInsn(PUTFIELD, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   776
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   777
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   778
                mv.visitInsn(RETURN);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   779
                mv.visitMaxs(0, 0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   780
                mv.visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   781
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   782
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   783
            // emit make()  ...factory method wrapping constructor
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   784
            {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   785
                MethodType ftryType = thisCtorType.changeReturnType(topClass());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   786
                mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   787
                        "make", methodSig(ftryType), null, null);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   788
                mv.visitCode();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   789
                // make instance
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   790
                mv.visitTypeInsn(NEW, className);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   791
                mv.visitInsn(DUP);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   792
                // load factory method arguments:  ctarg... and arg...
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   793
                for (Var v : NO_THIS.fromTypes(ftryType.parameterList())) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   794
                    v.emitVarInstruction(ALOAD, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   795
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   796
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   797
                // finally, invoke the constructor and return
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   798
                mv.visitMethodInsn(INVOKESPECIAL, className,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   799
                        "<init>", methodSig(thisCtorType), false);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   800
                mv.visitInsn(ARETURN);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   801
                mv.visitMaxs(0, 0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   802
                mv.visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   803
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   804
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   805
            // For each transform, emit the customized override of the transform method.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   806
            // This method mixes together some incoming arguments (from the transform's
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   807
            // static type signature) with the field types themselves, and passes
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   808
            // the resulting mish-mosh of values to a method handle produced by
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   809
            // the species itself.  (Typically this method handle is the factory
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   810
            // method of this species or a related one.)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   811
            for (int whichtm = 0; whichtm < TRANSFORM_NAMES.size(); whichtm++) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   812
                final String     TNAME = TRANSFORM_NAMES.get(whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   813
                final MethodType TTYPE = TRANSFORM_TYPES.get(whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   814
                final int        TMODS = TRANSFORM_MODS.get(whichtm);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   815
                mv = cw.visitMethod((TMODS & ACC_PPP) | ACC_FINAL,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   816
                        TNAME, TTYPE.toMethodDescriptorString(), null, E_THROWABLE);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   817
                mv.visitCode();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   818
                // return a call to the corresponding "transform helper", something like this:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   819
                //   MY_SPECIES.transformHelper(whichtm).invokeBasic(ctarg, ..., argL0, ..., xarg)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   820
                mv.visitFieldInsn(GETSTATIC, className,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   821
                        sdFieldName, SPECIES_DATA_SIG);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   822
                emitIntConstant(whichtm, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   823
                mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   824
                        "transformHelper", "(I)" + MH_SIG, false);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   825
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   826
                List<Var> targs = AFTER_THIS.fromTypes(TTYPE.parameterList());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   827
                List<Var> tfields = new ArrayList<>(fields);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   828
                // mix them up and load them for the transform helper:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   829
                List<Var> helperArgs = speciesData.deriveTransformHelperArguments(transformMethods.get(whichtm), whichtm, targs, tfields);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   830
                List<Class<?>> helperTypes = new ArrayList<>(helperArgs.size());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   831
                for (Var ha : helperArgs) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   832
                    helperTypes.add(ha.basicType.basicTypeClass());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   833
                    if (ha.isInHeap()) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   834
                        assert(tfields.contains(ha));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   835
                        mv.visitVarInsn(ALOAD, 0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   836
                        ha.emitFieldInsn(GETFIELD, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   837
                    } else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   838
                        assert(targs.contains(ha));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   839
                        ha.emitVarInstruction(ALOAD, mv);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   840
                    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   841
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   842
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   843
                // jump into the helper (which is probably a factory method)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   844
                final Class<?> rtype = TTYPE.returnType();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   845
                final BasicType rbt = BasicType.basicType(rtype);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   846
                MethodType invokeBasicType = MethodType.methodType(rbt.basicTypeClass(), helperTypes);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   847
                mv.visitMethodInsn(INVOKEVIRTUAL, MH,
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   848
                        "invokeBasic", methodSig(invokeBasicType), false);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   849
                if (rbt == BasicType.L_TYPE) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   850
                    mv.visitTypeInsn(CHECKCAST, classBCName(rtype));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   851
                    mv.visitInsn(ARETURN);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   852
                } else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   853
                    throw newInternalError("NYI: transform of type "+rtype);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   854
                }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   855
                mv.visitMaxs(0, 0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   856
                mv.visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   857
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   858
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   859
            cw.visitEnd();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   860
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   861
            return cw.toByteArray();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   862
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   863
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   864
        private int typeLoadOp(char t) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   865
            switch (t) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   866
            case 'L': return ALOAD;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   867
            case 'I': return ILOAD;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   868
            case 'J': return LLOAD;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   869
            case 'F': return FLOAD;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   870
            case 'D': return DLOAD;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   871
            default : throw newInternalError("unrecognized type " + t);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   872
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   873
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   874
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   875
        private void emitIntConstant(int con, MethodVisitor mv) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   876
            if (ICONST_M1 - ICONST_0 <= con && con <= ICONST_5 - ICONST_0)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   877
                mv.visitInsn(ICONST_0 + con);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   878
            else if (con == (byte) con)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   879
                mv.visitIntInsn(BIPUSH, con);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   880
            else if (con == (short) con)
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   881
                mv.visitIntInsn(SIPUSH, con);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   882
            else {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   883
                mv.visitLdcInsn(con);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   884
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   885
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   886
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   887
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   888
        //
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   889
        // Getter MH generation.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   890
        //
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   891
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   892
        private MethodHandle findGetter(Class<?> speciesCode, List<Class<?>> types, int index) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   893
            Class<?> fieldType = types.get(index);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   894
            String fieldName = chooseFieldName(fieldType, index);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   895
            try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   896
                return IMPL_LOOKUP.findGetter(speciesCode, fieldName, fieldType);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   897
            } catch (NoSuchFieldException | IllegalAccessException e) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   898
                throw newInternalError(e);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   899
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   900
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   901
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   902
        private List<MethodHandle> findGetters(Class<?> speciesCode, List<Class<?>> types) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   903
            MethodHandle[] mhs = new MethodHandle[types.size()];
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   904
            for (int i = 0; i < mhs.length; ++i) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   905
                mhs[i] = findGetter(speciesCode, types, i);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   906
                assert(mhs[i].internalMemberName().getDeclaringClass() == speciesCode);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   907
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   908
            return List.of(mhs);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   909
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   910
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   911
        private List<MethodHandle> findFactories(Class<? extends T> speciesCode, List<Class<?>> types) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   912
            MethodHandle[] mhs = new MethodHandle[1];
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   913
            mhs[0] = findFactory(speciesCode, types);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   914
            return List.of(mhs);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   915
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   916
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   917
        List<LambdaForm.NamedFunction> makeNominalGetters(List<Class<?>> types, List<MethodHandle> getters) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   918
            LambdaForm.NamedFunction[] nfs = new LambdaForm.NamedFunction[types.size()];
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   919
            for (int i = 0; i < nfs.length; ++i) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   920
                nfs[i] = new LambdaForm.NamedFunction(getters.get(i));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   921
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   922
            return List.of(nfs);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   923
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   924
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   925
        //
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   926
        // Auxiliary methods.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   927
        //
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   928
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   929
        protected void linkSpeciesDataToCode(ClassSpecializer<T,K,S>.SpeciesData speciesData, Class<? extends T> speciesCode) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   930
            speciesData.speciesCode = speciesCode.asSubclass(topClass);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   931
            final List<Class<?>> types = speciesData.fieldTypes;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   932
            speciesData.factories = this.findFactories(speciesCode, types);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   933
            speciesData.getters = this.findGetters(speciesCode, types);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   934
            speciesData.nominalGetters = this.makeNominalGetters(types, speciesData.getters);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   935
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   936
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   937
        private Field reflectSDField(Class<? extends T> speciesCode) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   938
            final Field field = reflectField(speciesCode, sdFieldName);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   939
            assert(field.getType() == metaType);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   940
            assert(Modifier.isStatic(field.getModifiers()));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   941
            return field;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   942
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   943
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   944
        private S readSpeciesDataFromCode(Class<? extends T> speciesCode) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   945
            try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   946
                MemberName sdField = IMPL_LOOKUP.resolveOrFail(REF_getStatic, speciesCode, sdFieldName, metaType);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   947
                Object base = MethodHandleNatives.staticFieldBase(sdField);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   948
                long offset = MethodHandleNatives.staticFieldOffset(sdField);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   949
                UNSAFE.loadFence();
52220
9c260a6b6471 8207146: Rename jdk.internal.misc.Unsafe::xxxObject to xxxReference
mchung
parents: 52015
diff changeset
   950
                return metaType.cast(UNSAFE.getReference(base, offset));
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   951
            } catch (Error err) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   952
                throw err;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   953
            } catch (Exception ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   954
                throw newInternalError("Failed to load speciesData from speciesCode: " + speciesCode.getName(), ex);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   955
            } catch (Throwable t) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   956
                throw uncaughtException(t);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   957
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   958
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   959
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   960
        protected S loadSpeciesDataFromCode(Class<? extends T> speciesCode) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   961
            if (speciesCode == topClass()) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   962
                return topSpecies;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   963
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   964
            S result = readSpeciesDataFromCode(speciesCode);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   965
            if (result.outer() != ClassSpecializer.this) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   966
                throw newInternalError("wrong class");
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   967
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   968
            return result;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   969
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   970
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   971
        protected void linkCodeToSpeciesData(Class<? extends T> speciesCode, ClassSpecializer<T,K,S>.SpeciesData speciesData, boolean salvage) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   972
            try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   973
                assert(readSpeciesDataFromCode(speciesCode) == null ||
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   974
                    (salvage && readSpeciesDataFromCode(speciesCode).equals(speciesData)));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   975
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   976
                MemberName sdField = IMPL_LOOKUP.resolveOrFail(REF_putStatic, speciesCode, sdFieldName, metaType);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   977
                Object base = MethodHandleNatives.staticFieldBase(sdField);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   978
                long offset = MethodHandleNatives.staticFieldOffset(sdField);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   979
                UNSAFE.storeFence();
52220
9c260a6b6471 8207146: Rename jdk.internal.misc.Unsafe::xxxObject to xxxReference
mchung
parents: 52015
diff changeset
   980
                UNSAFE.putReference(base, offset, speciesData);
47753
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   981
                UNSAFE.storeFence();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   982
            } catch (Error err) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   983
                throw err;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   984
            } catch (Exception ex) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   985
                throw newInternalError("Failed to link speciesData to speciesCode: " + speciesCode.getName(), ex);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   986
            } catch (Throwable t) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   987
                throw uncaughtException(t);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   988
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   989
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   990
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   991
        /**
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   992
         * Field names in concrete species classes adhere to this pattern:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   993
         * type + index, where type is a single character (L, I, J, F, D).
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   994
         * The factory subclass can customize this.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   995
         * The name is purely cosmetic, since it applies to a private field.
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   996
         */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   997
        protected String chooseFieldName(Class<?> type, int index) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   998
            BasicType bt = BasicType.basicType(type);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
   999
            return "" + bt.basicTypeChar() + index;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1000
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1001
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1002
        MethodHandle findFactory(Class<? extends T> speciesCode, List<Class<?>> types) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1003
            final MethodType type = baseConstructorType().changeReturnType(topClass()).appendParameterTypes(types);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1004
            try {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1005
                return IMPL_LOOKUP.findStatic(speciesCode, "make", type);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1006
            } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1007
                throw newInternalError(e);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1008
            }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1009
        }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1010
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1011
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1012
    /** Hook that virtualizes the Factory class, allowing subclasses to extend it. */
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1013
    protected Factory makeFactory() {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1014
        return new Factory();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1015
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1016
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1017
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1018
    // Other misc helpers:
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1019
    private static final String MH = "java/lang/invoke/MethodHandle";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1020
    private static final String MH_SIG = "L" + MH + ";";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1021
    private static final String STABLE = "jdk/internal/vm/annotation/Stable";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1022
    private static final String STABLE_SIG = "L" + STABLE + ";";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1023
    private static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1024
    static {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1025
        assert(MH_SIG.equals(classSig(MethodHandle.class)));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1026
        assert(MH.equals(classBCName(MethodHandle.class)));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1027
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1028
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1029
    static String methodSig(MethodType mt) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1030
        return mt.toMethodDescriptorString();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1031
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1032
    static String classSig(Class<?> cls) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1033
        if (cls.isPrimitive() || cls.isArray())
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1034
            return MethodType.methodType(cls).toMethodDescriptorString().substring(2);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1035
        return classSig(classBCName(cls));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1036
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1037
    static String classSig(String bcName) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1038
        assert(bcName.indexOf('.') < 0);
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1039
        assert(!bcName.endsWith(";"));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1040
        assert(!bcName.startsWith("["));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1041
        return "L" + bcName + ";";
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1042
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1043
    static String classBCName(Class<?> cls) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1044
        return classBCName(className(cls));
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1045
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1046
    static String classBCName(String str) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1047
        assert(str.indexOf('/') < 0) : str;
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1048
        return str.replace('.', '/');
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1049
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1050
    static String className(Class<?> cls) {
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1051
        assert(!cls.isArray() && !cls.isPrimitive());
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1052
        return cls.getName();
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1053
    }
a2008587c13f 8184777: Factor out species generation logic from BoundMethodHandle
redestad
parents:
diff changeset
  1054
}