1/*
2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package java.lang.invoke;
26
27import jdk.internal.vm.annotation.ForceInline;
28import jdk.internal.vm.annotation.Stable;
29
30import java.lang.invoke.VarHandle.AccessMode;
31import java.lang.reflect.Method;
32import java.lang.reflect.Modifier;
33import java.util.ArrayList;
34import java.util.List;
35
36/**
37 * A var handle form containing a set of member name, one for each operation.
38 * Each member characterizes a static method.
39 */
40final class VarForm {
41
42    final @Stable MethodType[] methodType_table;
43
44    final @Stable MemberName[] memberName_table;
45
46    VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
47        this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
48
49        // TODO lazily calculate
50        this.memberName_table = linkFromStatic(implClass);
51
52        // (Receiver, <Intermediates>)
53        List<Class<?>> l = new ArrayList<>();
54        if (receiver != null)
55            l.add(receiver);
56        for (Class<?> c : intermediate)
57            l.add(c);
58
59        // (Receiver, <Intermediates>)Value
60        methodType_table[VarHandle.AccessType.GET.ordinal()] =
61                MethodType.methodType(value, l).erase();
62
63        // (Receiver, <Intermediates>, Value)void
64        l.add(value);
65        methodType_table[VarHandle.AccessType.SET.ordinal()] =
66                MethodType.methodType(void.class, l).erase();
67
68        // (Receiver, <Intermediates>, Value)Value
69        methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
70                MethodType.methodType(value, l).erase();
71
72        // (Receiver, <Intermediates>, Value, Value)boolean
73        l.add(value);
74        methodType_table[VarHandle.AccessType.COMPARE_AND_SWAP.ordinal()] =
75                MethodType.methodType(boolean.class, l).erase();
76
77        // (Receiver, <Intermediates>, Value, Value)Value
78        methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
79                MethodType.methodType(value, l).erase();
80    }
81
82    @ForceInline
83    final MethodType getMethodType(int type) {
84        return methodType_table[type];
85    }
86
87    @ForceInline
88    final MemberName getMemberName(int mode) {
89        // TODO calculate lazily
90        MemberName mn = memberName_table[mode];
91        if (mn == null) {
92            throw new UnsupportedOperationException();
93        }
94        return mn;
95    }
96
97
98    @Stable
99    MethodType[] methodType_V_table;
100
101    @ForceInline
102    final MethodType[] getMethodType_V_init() {
103        MethodType[] table = new MethodType[VarHandle.AccessType.values().length];
104        for (int i = 0; i < methodType_table.length; i++) {
105            MethodType mt = methodType_table[i];
106            // TODO only adjust for sig-poly methods returning Object
107            table[i] = mt.changeReturnType(void.class);
108        }
109        methodType_V_table = table;
110        return table;
111    }
112
113    @ForceInline
114    final MethodType getMethodType_V(int type) {
115        MethodType[] table = methodType_V_table;
116        if (table == null) {
117            table = getMethodType_V_init();
118        }
119        return table[type];
120    }
121
122
123    /**
124     * Link all signature polymorphic methods.
125     */
126    private static MemberName[] linkFromStatic(Class<?> implClass) {
127        MemberName[] table = new MemberName[AccessMode.values().length];
128
129        for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
130            for (Method m : c.getDeclaredMethods()) {
131                if (Modifier.isStatic(m.getModifiers())) {
132                    AccessMode am = AccessMode.methodNameToAccessMode.get(m.getName());
133                    if (am != null) {
134                        assert table[am.ordinal()] == null;
135                        table[am.ordinal()] = new MemberName(m);
136                    }
137                }
138            }
139        }
140        return table;
141    }
142}