001/*
002 * Copyright (c) 2009, 2015, 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 jdk.internal.jvmci.code;
024
025import java.util.*;
026
027import jdk.internal.jvmci.meta.*;
028
029/**
030 * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
031 * where to find the local variables, operand stack values and locked objects of the bytecode
032 * frame(s).
033 */
034public class BytecodeFrame extends BytecodePosition {
035
036    /**
037     * An array of values representing how to reconstruct the state of the Java frame. This is array
038     * is partitioned as follows:
039     * <p>
040     * <table summary="" border="1" cellpadding="5" frame="void" rules="all">
041     * <tr>
042     * <th>Start index (inclusive)</th>
043     * <th>End index (exclusive)</th>
044     * <th>Description</th>
045     * </tr>
046     * <tr>
047     * <td>0</td>
048     * <td>numLocals</td>
049     * <td>Local variables</td>
050     * </tr>
051     * <tr>
052     * <td>numLocals</td>
053     * <td>numLocals + numStack</td>
054     * <td>Operand stack</td>
055     * </tr>
056     * <tr>
057     * <td>numLocals + numStack</td>
058     * <td>values.length</td>
059     * <td>Locked objects</td>
060     * </tr>
061     * </table>
062     * <p>
063     * Note that the number of locals and the number of stack slots may be smaller than the maximum
064     * number of locals and stack slots as specified in the compiled method.
065     */
066    public final Value[] values;
067
068    /**
069     * The number of locals in the values array.
070     */
071    public final int numLocals;
072
073    /**
074     * The number of stack slots in the values array.
075     */
076    public final int numStack;
077
078    /**
079     * The number of locks in the values array.
080     */
081    public final int numLocks;
082
083    /**
084     * True if this is a position inside an exception handler before the exception object has been
085     * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
086     * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
087     * position, the interpreter will rethrow the exception instead of executing the bytecode
088     * instruction at this position.
089     */
090    public final boolean rethrowException;
091
092    public final boolean duringCall;
093
094    /**
095     * This BCI should be used for frame states that are built for code with no meaningful BCI.
096     */
097    public static final int UNKNOWN_BCI = -5;
098
099    /**
100     * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
101     * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
102     * the monitor is still held.
103     */
104    public static final int UNWIND_BCI = -1;
105
106    /**
107     * The BCI for the state before starting to execute a method. Note that if the method is
108     * synchronized, the monitor is not yet held.
109     */
110    public static final int BEFORE_BCI = -2;
111
112    /**
113     * The BCI for the state after finishing the execution of a method and returning normally. Note
114     * that if the method was synchronized the monitor is already released.
115     */
116    public static final int AFTER_BCI = -3;
117
118    /**
119     * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
120     * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the
121     * monitor is already released.
122     */
123    public static final int AFTER_EXCEPTION_BCI = -4;
124
125    /**
126     * This BCI should be used for states that cannot be the target of a deoptimization, like
127     * snippet frame states.
128     */
129    public static final int INVALID_FRAMESTATE_BCI = -6;
130
131    /**
132     * Determines if a given BCI matches one of the placeholder BCI constants defined in this class.
133     */
134    public static boolean isPlaceholderBci(int bci) {
135        return bci < 0;
136    }
137
138    /**
139     * Gets the name of a given placeholder BCI.
140     */
141    public static String getPlaceholderBciName(int bci) {
142        assert isPlaceholderBci(bci);
143        if (bci == BytecodeFrame.AFTER_BCI) {
144            return "AFTER_BCI";
145        } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
146            return "AFTER_EXCEPTION_BCI";
147        } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
148            return "INVALID_FRAMESTATE_BCI";
149        } else if (bci == BytecodeFrame.BEFORE_BCI) {
150            return "BEFORE_BCI";
151        } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
152            return "UNKNOWN_BCI";
153        } else {
154            assert bci == BytecodeFrame.UNWIND_BCI;
155            return "UNWIND_BCI";
156        }
157    }
158
159    /**
160     * Creates a new frame object.
161     *
162     * @param caller the caller frame (which may be {@code null})
163     * @param method the method
164     * @param bci a BCI within the method
165     * @param rethrowException specifies if the VM should re-throw the pending exception when
166     *            deopt'ing using this frame
167     * @param values the frame state {@link #values}
168     * @param numLocals the number of local variables
169     * @param numStack the depth of the stack
170     * @param numLocks the number of locked objects
171     */
172    public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, Value[] values, int numLocals, int numStack, int numLocks) {
173        super(caller, method, bci);
174        assert values != null;
175        this.rethrowException = rethrowException;
176        this.duringCall = duringCall;
177        this.values = values;
178        this.numLocals = numLocals;
179        this.numStack = numStack;
180        this.numLocks = numLocks;
181        assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
182    }
183
184    /**
185     * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
186     * slot following a double word item. This should really be checked in FrameState itself but
187     * because of Word type rewriting and alternative backends that can't be done.
188     */
189    public boolean validateFormat(boolean derivedOk) {
190        if (caller() != null) {
191            caller().validateFormat(derivedOk);
192        }
193        for (int i = 0; i < numLocals + numStack; i++) {
194            if (values[i] != null) {
195                Kind kind = values[i].getKind();
196                if (kind.needsTwoSlots()) {
197                    assert values.length > i + 1 : String.format("missing second word %s", this);
198                    assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal : this;
199                }
200                assert derivedOk || ValueUtil.isIllegal(values[i]) || !values[i].getLIRKind().isUnknownReference() : "Unexpected derived value: " + values[i];
201            }
202        }
203        return true;
204    }
205
206    /**
207     * Gets the value representing the specified local variable.
208     *
209     * @param i the local variable index
210     * @return the value that can be used to reconstruct the local's current value
211     */
212    public Value getLocalValue(int i) {
213        return values[i];
214    }
215
216    /**
217     * Gets the value representing the specified stack slot.
218     *
219     * @param i the stack index
220     * @return the value that can be used to reconstruct the stack slot's current value
221     */
222    public Value getStackValue(int i) {
223        return values[i + numLocals];
224    }
225
226    /**
227     * Gets the value representing the specified lock.
228     *
229     * @param i the lock index
230     * @return the value that can be used to reconstruct the lock's current value
231     */
232    public Value getLockValue(int i) {
233        return values[i + numLocals + numStack];
234    }
235
236    /**
237     * Gets the caller of this frame.
238     *
239     * @return {@code null} if this frame has no caller
240     */
241    public BytecodeFrame caller() {
242        return (BytecodeFrame) getCaller();
243    }
244
245    @Override
246    public boolean equals(Object obj) {
247        if (this == obj) {
248            return true;
249        }
250        if (obj instanceof BytecodeFrame && super.equals(obj)) {
251            BytecodeFrame that = (BytecodeFrame) obj;
252            // @formatter:off
253            if (this.duringCall == that.duringCall &&
254                this.rethrowException == that.rethrowException &&
255                this.numLocals == that.numLocals &&
256                this.numLocks == that.numLocks &&
257                this.numStack == that.numStack &&
258                Arrays.equals(this.values, that.values)) {
259                return true;
260            }
261            // @formatter:off
262            return true;
263        }
264        return false;
265    }
266
267    @Override
268    public String toString() {
269        return CodeUtil.append(new StringBuilder(100), this).toString();
270    }
271}