001/*
002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.graphbuilderconf;
024
025import java.util.*;
026
027import jdk.internal.jvmci.meta.*;
028
029import com.oracle.graal.compiler.common.*;
030import com.oracle.graal.nodes.*;
031
032public class GraphBuilderConfiguration {
033
034    public static class Plugins {
035        private final InvocationPlugins invocationPlugins;
036        private NodePlugin[] nodePlugins;
037        private ParameterPlugin[] parameterPlugins;
038        private InlineInvokePlugin[] inlineInvokePlugins;
039        private LoopExplosionPlugin loopExplosionPlugin;
040
041        /**
042         * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in
043         * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default}
044         * {@linkplain #getInvocationPlugins() invocation plugins} in this object.
045         */
046        public Plugins(Plugins copyFrom) {
047            this.invocationPlugins = new InvocationPlugins(copyFrom.invocationPlugins);
048            this.nodePlugins = copyFrom.nodePlugins;
049            this.parameterPlugins = copyFrom.parameterPlugins;
050            this.inlineInvokePlugins = copyFrom.inlineInvokePlugins;
051            this.loopExplosionPlugin = copyFrom.loopExplosionPlugin;
052        }
053
054        /**
055         * Creates a new set of plugins.
056         *
057         * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in
058         *            this object
059         */
060        public Plugins(InvocationPlugins invocationPlugins) {
061            this.invocationPlugins = invocationPlugins;
062            this.nodePlugins = new NodePlugin[0];
063            this.parameterPlugins = new ParameterPlugin[0];
064            this.inlineInvokePlugins = new InlineInvokePlugin[0];
065        }
066
067        public InvocationPlugins getInvocationPlugins() {
068            return invocationPlugins;
069        }
070
071        public NodePlugin[] getNodePlugins() {
072            return nodePlugins;
073        }
074
075        public void appendNodePlugin(NodePlugin plugin) {
076            nodePlugins = Arrays.copyOf(nodePlugins, nodePlugins.length + 1);
077            nodePlugins[nodePlugins.length - 1] = plugin;
078        }
079
080        public void prependNodePlugin(NodePlugin plugin) {
081            NodePlugin[] newPlugins = new NodePlugin[nodePlugins.length + 1];
082            System.arraycopy(nodePlugins, 0, newPlugins, 1, nodePlugins.length);
083            newPlugins[0] = plugin;
084            nodePlugins = newPlugins;
085        }
086
087        public void clearNodePlugin() {
088            nodePlugins = new NodePlugin[0];
089        }
090
091        public ParameterPlugin[] getParameterPlugins() {
092            return parameterPlugins;
093        }
094
095        public void appendParameterPlugin(ParameterPlugin plugin) {
096            parameterPlugins = Arrays.copyOf(parameterPlugins, parameterPlugins.length + 1);
097            parameterPlugins[parameterPlugins.length - 1] = plugin;
098        }
099
100        public void prependParameterPlugin(ParameterPlugin plugin) {
101            ParameterPlugin[] newPlugins = new ParameterPlugin[parameterPlugins.length + 1];
102            System.arraycopy(parameterPlugins, 0, newPlugins, 1, parameterPlugins.length);
103            newPlugins[0] = plugin;
104            parameterPlugins = newPlugins;
105        }
106
107        public void clearParameterPlugin() {
108            parameterPlugins = new ParameterPlugin[0];
109        }
110
111        public InlineInvokePlugin[] getInlineInvokePlugins() {
112            return inlineInvokePlugins;
113        }
114
115        public void appendInlineInvokePlugin(InlineInvokePlugin plugin) {
116            inlineInvokePlugins = Arrays.copyOf(inlineInvokePlugins, inlineInvokePlugins.length + 1);
117            inlineInvokePlugins[inlineInvokePlugins.length - 1] = plugin;
118        }
119
120        public void prependInlineInvokePlugin(InlineInvokePlugin plugin) {
121            InlineInvokePlugin[] newPlugins = new InlineInvokePlugin[inlineInvokePlugins.length + 1];
122            System.arraycopy(inlineInvokePlugins, 0, newPlugins, 1, inlineInvokePlugins.length);
123            newPlugins[0] = plugin;
124            inlineInvokePlugins = newPlugins;
125        }
126
127        public void clearInlineInvokePlugins() {
128            inlineInvokePlugins = new InlineInvokePlugin[0];
129        }
130
131        public LoopExplosionPlugin getLoopExplosionPlugin() {
132            return loopExplosionPlugin;
133        }
134
135        public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) {
136            this.loopExplosionPlugin = plugin;
137        }
138    }
139
140    private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{};
141
142    private final boolean eagerResolving;
143    private final boolean omitAllExceptionEdges;
144    private final boolean omitAssertions;
145    private final ResolvedJavaType[] skippedExceptionTypes;
146    private final DebugInfoMode debugInfoMode;
147    private final boolean clearNonLiveLocals;
148    private boolean useProfiling;
149    private final Plugins plugins;
150
151    public static enum DebugInfoMode {
152        SafePointsOnly,
153        /**
154         * This mode inserts {@link SimpleInfopointNode}s in places where no safepoints would be
155         * inserted: inlining boundaries, and line number switches.
156         * <p>
157         * In this mode the infopoint only have a location (method and bytecode index) and no
158         * values.
159         * <p>
160         * This is useful to have better program counter to bci mapping and has no influence on the
161         * generated code. However it can increase the amount of metadata and does not allow access
162         * to accessing values at runtime.
163         */
164        Simple,
165        /**
166         * In this mode, {@link FullInfopointNode}s are generated in the same locations as in
167         * {@link #Simple} mode but the infopoints have access to the runtime values.
168         * <p>
169         * This is relevant when code is to be generated for native, machine-code level debugging
170         * but can have a limit the amount of optimization applied to the code.
171         */
172        Full,
173    }
174
175    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, boolean omitAssertions, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes,
176                    boolean clearNonLiveLocals, Plugins plugins) {
177        this.eagerResolving = eagerResolving;
178        this.omitAllExceptionEdges = omitAllExceptionEdges;
179        this.omitAssertions = omitAssertions;
180        this.debugInfoMode = debugInfoMode;
181        this.skippedExceptionTypes = skippedExceptionTypes;
182        this.clearNonLiveLocals = clearNonLiveLocals;
183        this.useProfiling = true;
184        this.plugins = plugins;
185    }
186
187    /**
188     * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in
189     * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the
190     * {@link InvocationPlugins} in the copy.
191     */
192    public GraphBuilderConfiguration copy() {
193        Plugins newPlugins = new Plugins(plugins);
194        GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, newPlugins);
195        result.useProfiling = useProfiling;
196        return result;
197    }
198
199    public boolean getUseProfiling() {
200        return useProfiling;
201    }
202
203    public void setUseProfiling(boolean b) {
204        this.useProfiling = b;
205    }
206
207    public GraphBuilderConfiguration withEagerResolving(boolean newEagerResolving) {
208        return new GraphBuilderConfiguration(newEagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins);
209    }
210
211    public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) {
212        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins);
213    }
214
215    public GraphBuilderConfiguration withOmitAllExceptionEdges(boolean newOmitAllExceptionEdges) {
216        return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins);
217    }
218
219    public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) {
220        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newOmitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins);
221    }
222
223    public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) {
224        ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length);
225        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, newDebugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins);
226    }
227
228    public GraphBuilderConfiguration withClearNonLiveLocals(boolean newClearNonLiveLocals) {
229        return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, newClearNonLiveLocals, plugins);
230    }
231
232    public ResolvedJavaType[] getSkippedExceptionTypes() {
233        return skippedExceptionTypes;
234    }
235
236    public boolean eagerResolving() {
237        return eagerResolving;
238    }
239
240    public boolean omitAllExceptionEdges() {
241        return omitAllExceptionEdges;
242    }
243
244    public boolean omitAssertions() {
245        return omitAssertions;
246    }
247
248    public boolean insertNonSafepointDebugInfo() {
249        return debugInfoMode.ordinal() >= DebugInfoMode.Simple.ordinal();
250    }
251
252    public boolean insertFullDebugInfo() {
253        return debugInfoMode.ordinal() >= DebugInfoMode.Full.ordinal();
254    }
255
256    public boolean insertSimpleDebugInfo() {
257        return debugInfoMode == DebugInfoMode.Simple;
258    }
259
260    public boolean clearNonLiveLocals() {
261        return clearNonLiveLocals;
262    }
263
264    public static GraphBuilderConfiguration getDefault(Plugins plugins) {
265        return new GraphBuilderConfiguration(false, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
266    }
267
268    public static GraphBuilderConfiguration getInfopointDefault(Plugins plugins) {
269        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
270    }
271
272    public static GraphBuilderConfiguration getEagerDefault(Plugins plugins) {
273        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
274    }
275
276    public static GraphBuilderConfiguration getInfopointEagerDefault(Plugins plugins) {
277        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
278    }
279
280    public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) {
281        return new GraphBuilderConfiguration(true, true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
282    }
283
284    public static GraphBuilderConfiguration getFullDebugDefault(Plugins plugins) {
285        return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins);
286    }
287
288    /**
289     * Returns {@code true} if it is an error for a class/field/method resolution to fail. The
290     * default is the same result as returned by {@link #eagerResolving()}. However, it may be
291     * overridden to allow failure even when {@link #eagerResolving} is {@code true}.
292     */
293    public boolean unresolvedIsError() {
294        return eagerResolving;
295    }
296
297    public Plugins getPlugins() {
298        return plugins;
299    }
300}