001/*
002 * Copyright (c) 2009, 2011, 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 a code position, that is, a chain of inlined methods with bytecode locations, that is
031 * communicated from the compiler to the runtime system. A code position can be used by the runtime
032 * system to reconstruct a source-level stack trace for exceptions and to create
033 * {@linkplain BytecodeFrame frames} for deoptimization.
034 */
035public class BytecodePosition {
036
037    private final BytecodePosition caller;
038    private final ResolvedJavaMethod method;
039    private final int bci;
040
041    /**
042     * Constructs a new object representing a given parent/caller, a given method, and a given BCI.
043     *
044     * @param caller the parent position
045     * @param method the method
046     * @param bci a BCI within the method
047     */
048    public BytecodePosition(BytecodePosition caller, ResolvedJavaMethod method, int bci) {
049        assert method != null;
050        this.caller = caller;
051        this.method = method;
052        this.bci = bci;
053    }
054
055    /**
056     * Converts this code position to a string representation.
057     *
058     * @return a string representation of this code position
059     */
060    @Override
061    public String toString() {
062        return CodeUtil.append(new StringBuilder(100), this).toString();
063    }
064
065    /**
066     * Deep equality test.
067     */
068    @Override
069    public boolean equals(Object obj) {
070        if (obj == this) {
071            return true;
072        }
073        if (obj != null && getClass() == obj.getClass()) {
074            BytecodePosition that = (BytecodePosition) obj;
075            if (this.bci == that.bci && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.caller, that.caller)) {
076                return true;
077            }
078        }
079        return false;
080    }
081
082    @Override
083    public int hashCode() {
084        return getBCI();
085    }
086
087    /**
088     * @return The location within the method, as a bytecode index. The constant {@code -1} may be
089     *         used to indicate the location is unknown, for example within code synthesized by the
090     *         compiler.
091     */
092    public int getBCI() {
093        return bci;
094    }
095
096    /**
097     * @return The runtime interface method for this position.
098     */
099    public ResolvedJavaMethod getMethod() {
100        return method;
101    }
102
103    /**
104     * The position where this position has been called, {@code null} if none.
105     */
106    public BytecodePosition getCaller() {
107        return caller;
108    }
109
110    /**
111     * Adds a caller to the current position returning the new position.
112     */
113    public BytecodePosition addCaller(BytecodePosition link) {
114        if (getCaller() == null) {
115            return new BytecodePosition(link, getMethod(), getBCI());
116        } else {
117            return new BytecodePosition(getCaller().addCaller(link), getMethod(), getBCI());
118        }
119    }
120}