GraphBuilderConfiguration.java revision 12657:6ef01bd40ce2
1/*
2 * Copyright (c) 2011, 2016, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.nodes.graphbuilderconf;
24
25import java.util.Arrays;
26
27import org.graalvm.compiler.core.common.GraalOptions;
28import org.graalvm.compiler.core.common.type.StampPair;
29
30import jdk.vm.ci.meta.JavaType;
31import jdk.vm.ci.meta.ResolvedJavaType;
32
33public class GraphBuilderConfiguration {
34
35    public static class Plugins {
36        private final InvocationPlugins invocationPlugins;
37        private NodePlugin[] nodePlugins;
38        private ParameterPlugin[] parameterPlugins;
39        private TypePlugin[] typePlugins;
40        private InlineInvokePlugin[] inlineInvokePlugins;
41        private LoopExplosionPlugin loopExplosionPlugin;
42        private ClassInitializationPlugin classInitializationPlugin;
43        private ProfilingPlugin profilingPlugin;
44
45        /**
46         * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in
47         * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default}
48         * {@linkplain #getInvocationPlugins() invocation plugins} in this object.
49         */
50        public Plugins(Plugins copyFrom) {
51            this.invocationPlugins = new InvocationPlugins(copyFrom.invocationPlugins);
52            this.nodePlugins = copyFrom.nodePlugins;
53            this.parameterPlugins = copyFrom.parameterPlugins;
54            this.typePlugins = copyFrom.typePlugins;
55            this.inlineInvokePlugins = copyFrom.inlineInvokePlugins;
56            this.loopExplosionPlugin = copyFrom.loopExplosionPlugin;
57            this.classInitializationPlugin = copyFrom.classInitializationPlugin;
58            this.profilingPlugin = copyFrom.profilingPlugin;
59        }
60
61        /**
62         * Creates a new set of plugins.
63         *
64         * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in
65         *            this object
66         */
67        public Plugins(InvocationPlugins invocationPlugins) {
68            this.invocationPlugins = invocationPlugins;
69            this.nodePlugins = new NodePlugin[0];
70            this.parameterPlugins = new ParameterPlugin[0];
71            this.typePlugins = new TypePlugin[0];
72            this.inlineInvokePlugins = new InlineInvokePlugin[0];
73        }
74
75        public InvocationPlugins getInvocationPlugins() {
76            return invocationPlugins;
77        }
78
79        public NodePlugin[] getNodePlugins() {
80            return nodePlugins;
81        }
82
83        public void appendNodePlugin(NodePlugin plugin) {
84            nodePlugins = Arrays.copyOf(nodePlugins, nodePlugins.length + 1);
85            nodePlugins[nodePlugins.length - 1] = plugin;
86        }
87
88        public void prependNodePlugin(NodePlugin plugin) {
89            NodePlugin[] newPlugins = new NodePlugin[nodePlugins.length + 1];
90            System.arraycopy(nodePlugins, 0, newPlugins, 1, nodePlugins.length);
91            newPlugins[0] = plugin;
92            nodePlugins = newPlugins;
93        }
94
95        public void clearNodePlugin() {
96            nodePlugins = new NodePlugin[0];
97        }
98
99        public ParameterPlugin[] getParameterPlugins() {
100            return parameterPlugins;
101        }
102
103        public void appendParameterPlugin(ParameterPlugin plugin) {
104            parameterPlugins = Arrays.copyOf(parameterPlugins, parameterPlugins.length + 1);
105            parameterPlugins[parameterPlugins.length - 1] = plugin;
106        }
107
108        public void prependParameterPlugin(ParameterPlugin plugin) {
109            ParameterPlugin[] newPlugins = new ParameterPlugin[parameterPlugins.length + 1];
110            System.arraycopy(parameterPlugins, 0, newPlugins, 1, parameterPlugins.length);
111            newPlugins[0] = plugin;
112            parameterPlugins = newPlugins;
113        }
114
115        public TypePlugin[] getTypePlugins() {
116            return typePlugins;
117        }
118
119        public void appendTypePlugin(TypePlugin plugin) {
120            typePlugins = Arrays.copyOf(typePlugins, typePlugins.length + 1);
121            typePlugins[typePlugins.length - 1] = plugin;
122        }
123
124        public void prependTypePlugin(TypePlugin plugin) {
125            TypePlugin[] newPlugins = new TypePlugin[typePlugins.length + 1];
126            System.arraycopy(typePlugins, 0, newPlugins, 1, typePlugins.length);
127            newPlugins[0] = plugin;
128            typePlugins = newPlugins;
129        }
130
131        public void clearParameterPlugin() {
132            parameterPlugins = new ParameterPlugin[0];
133        }
134
135        public InlineInvokePlugin[] getInlineInvokePlugins() {
136            return inlineInvokePlugins;
137        }
138
139        public void appendInlineInvokePlugin(InlineInvokePlugin plugin) {
140            inlineInvokePlugins = Arrays.copyOf(inlineInvokePlugins, inlineInvokePlugins.length + 1);
141            inlineInvokePlugins[inlineInvokePlugins.length - 1] = plugin;
142        }
143
144        public void prependInlineInvokePlugin(InlineInvokePlugin plugin) {
145            InlineInvokePlugin[] newPlugins = new InlineInvokePlugin[inlineInvokePlugins.length + 1];
146            System.arraycopy(inlineInvokePlugins, 0, newPlugins, 1, inlineInvokePlugins.length);
147            newPlugins[0] = plugin;
148            inlineInvokePlugins = newPlugins;
149        }
150
151        public void clearInlineInvokePlugins() {
152            inlineInvokePlugins = new InlineInvokePlugin[0];
153        }
154
155        public LoopExplosionPlugin getLoopExplosionPlugin() {
156            return loopExplosionPlugin;
157        }
158
159        public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) {
160            this.loopExplosionPlugin = plugin;
161        }
162
163        public ClassInitializationPlugin getClassInitializationPlugin() {
164            return classInitializationPlugin;
165        }
166
167        public void setClassInitializationPlugin(ClassInitializationPlugin plugin) {
168            this.classInitializationPlugin = plugin;
169        }
170
171        public ProfilingPlugin getProfilingPlugin() {
172            return profilingPlugin;
173        }
174
175        public void setProfilingPlugin(ProfilingPlugin plugin) {
176            this.profilingPlugin = plugin;
177        }
178
179        public StampPair getOverridingStamp(GraphBuilderTool b, JavaType type, boolean nonNull) {
180            for (TypePlugin plugin : getTypePlugins()) {
181                StampPair stamp = plugin.interceptType(b, type, nonNull);
182                if (stamp != null) {
183                    return stamp;
184                }
185            }
186            return null;
187        }
188    }
189
190    private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{};
191
192    private final boolean eagerResolving;
193    private final BytecodeExceptionMode bytecodeExceptionMode;
194    private final boolean omitAssertions;
195    private final ResolvedJavaType[] skippedExceptionTypes;
196    private final boolean insertFullInfopoints;
197    private final boolean trackNodeSourcePosition;
198    private final boolean clearNonLiveLocals;
199    private final Plugins plugins;
200
201    public enum BytecodeExceptionMode {
202        /**
203         * This mode always explicitly checks for exceptions.
204         */
205        CheckAll,
206        /**
207         * This mode omits all explicit exception edges.
208         */
209        OmitAll,
210        /**
211         * This mode uses profiling information to decide whether to use explicit exception edges.
212         */
213        Profile
214    }
215
216    protected GraphBuilderConfiguration(boolean eagerResolving, BytecodeExceptionMode bytecodeExceptionMode, boolean omitAssertions, boolean insertFullInfopoints,
217                    boolean trackNodeSourcePosition, ResolvedJavaType[] skippedExceptionTypes,
218                    boolean clearNonLiveLocals, Plugins plugins) {
219        this.eagerResolving = eagerResolving;
220        this.bytecodeExceptionMode = bytecodeExceptionMode;
221        this.omitAssertions = omitAssertions;
222        this.insertFullInfopoints = insertFullInfopoints;
223        this.trackNodeSourcePosition = trackNodeSourcePosition;
224        this.skippedExceptionTypes = skippedExceptionTypes;
225        this.clearNonLiveLocals = clearNonLiveLocals;
226        this.plugins = plugins;
227    }
228
229    /**
230     * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in
231     * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the
232     * {@link InvocationPlugins} in the copy.
233     */
234    public GraphBuilderConfiguration copy() {
235        Plugins newPlugins = new Plugins(plugins);
236        GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes,
237                        clearNonLiveLocals, newPlugins);
238        return result;
239    }
240
241    public GraphBuilderConfiguration withEagerResolving(boolean newEagerResolving) {
242        return new GraphBuilderConfiguration(newEagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, clearNonLiveLocals,
243                        plugins);
244    }
245
246    public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) {
247        return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, newSkippedExceptionTypes, clearNonLiveLocals,
248                        plugins);
249    }
250
251    public GraphBuilderConfiguration withBytecodeExceptionMode(BytecodeExceptionMode newBytecodeExceptionMode) {
252        return new GraphBuilderConfiguration(eagerResolving, newBytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, clearNonLiveLocals,
253                        plugins);
254    }
255
256    public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) {
257        return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, newOmitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, clearNonLiveLocals,
258                        plugins);
259    }
260
261    public GraphBuilderConfiguration withFullInfopoints(boolean newInsertFullInfopoints) {
262        ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length);
263        return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, newInsertFullInfopoints, trackNodeSourcePosition, newSkippedExceptionTypes, clearNonLiveLocals,
264                        plugins);
265    }
266
267    public GraphBuilderConfiguration withNodeSourcePosition(boolean newTrackNodeSourcePosition) {
268        ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length);
269        return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, newTrackNodeSourcePosition, newSkippedExceptionTypes, clearNonLiveLocals,
270                        plugins);
271    }
272
273    public GraphBuilderConfiguration withClearNonLiveLocals(boolean newClearNonLiveLocals) {
274        return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, newClearNonLiveLocals,
275                        plugins);
276    }
277
278    public ResolvedJavaType[] getSkippedExceptionTypes() {
279        return skippedExceptionTypes;
280    }
281
282    public boolean eagerResolving() {
283        return eagerResolving;
284    }
285
286    public BytecodeExceptionMode getBytecodeExceptionMode() {
287        return bytecodeExceptionMode;
288    }
289
290    public boolean omitAssertions() {
291        return omitAssertions;
292    }
293
294    public boolean trackNodeSourcePosition() {
295        return trackNodeSourcePosition;
296    }
297
298    public boolean insertFullInfopoints() {
299        return insertFullInfopoints;
300    }
301
302    public boolean clearNonLiveLocals() {
303        return clearNonLiveLocals;
304    }
305
306    public static GraphBuilderConfiguration getDefault(Plugins plugins) {
307        return new GraphBuilderConfiguration(false, BytecodeExceptionMode.Profile, false, false, false, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
308    }
309
310    public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) {
311        return new GraphBuilderConfiguration(true, BytecodeExceptionMode.OmitAll, false, false, false, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
312    }
313
314    /**
315     * Returns {@code true} if it is an error for a class/field/method resolution to fail. The
316     * default is the same result as returned by {@link #eagerResolving()}. However, it may be
317     * overridden to allow failure even when {@link #eagerResolving} is {@code true}.
318     */
319    public boolean unresolvedIsError() {
320        return eagerResolving;
321    }
322
323    public Plugins getPlugins() {
324        return plugins;
325    }
326}
327