/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.inlining; import org.jikesrvm.classloader.RVMMethod; import org.jikesrvm.classloader.NormalMethod; import org.jikesrvm.compilers.opt.ir.Instruction; import org.jikesrvm.compilers.opt.util.Stack; /** * Represents an inlining sequence. * Used to uniquely identify program locations. */ public final class InlineSequence { /** * Current method. */ public final NormalMethod method; /** * Caller info. {@code null} if none. */ public final InlineSequence caller; /** * bytecode index (in caller) of call site */ private int bcIndex; /** * We need more detailed information of call site than bcIndex. */ final Instruction callSite; /** * @return contents of {@link #method} */ public NormalMethod getMethod() { return method; } /** * @return contents of {@link #caller} */ public InlineSequence getCaller() { return caller; } /** * Constructs a new top-level inline sequence operand. * * @param method current method */ public InlineSequence(NormalMethod method) { this(method, null, -1); } /** * Constructs a new inline sequence operand. * * @param method current method * @param caller caller info * @param bcIndex bytecode index of call site */ InlineSequence(NormalMethod method, InlineSequence caller, int bcIndex) { this.method = method; this.caller = caller; this.callSite = null; this.bcIndex = bcIndex; } /** * Constructs a new inline sequence operand. * * @param method current method * @param caller caller info * @param callsite the call site instruction of this callee */ public InlineSequence(NormalMethod method, InlineSequence caller, Instruction callsite) { this.method = method; this.caller = caller; this.callSite = callsite; this.bcIndex = callsite.getBytecodeIndex(); } public Instruction getCallSite() { return this.callSite; } /** * Returns the string representation of this inline sequence. */ @Override public String toString() { StringBuilder sb = new StringBuilder(" "); for (InlineSequence is = this; is != null; is = is.caller) { sb.append(is.method.getDeclaringClass().getDescriptor()).append(" "). append(is.method.getName()).append(" "). append(is.method.getDescriptor()).append(" "). append(is.bcIndex).append(" "); } return sb.toString(); } /** * @return the depth of inlining: (0 corresponds to no inlining) */ public int getInlineDepth() { int depth = 0; InlineSequence parent = this.caller; while (parent != null) { depth++; parent = parent.caller; } return depth; } /** * @return the root method of this inline sequence */ public NormalMethod getRootMethod() { InlineSequence parent = this; while (parent.caller != null) { parent = parent.caller; } return parent.method; } /** * @param m the method to search for * @return whether this inline sequence contains a given method */ public boolean containsMethod(RVMMethod m) { if (method == m) return true; if (caller == null) return false; return (caller.containsMethod(m)); } public java.util.Enumeration<InlineSequence> enumerateFromRoot() { return new java.util.Enumeration<InlineSequence>() { Stack<InlineSequence> stack; { stack = new Stack<InlineSequence>(); InlineSequence parent = InlineSequence.this; while (parent.caller != null) { stack.push(parent); parent = parent.caller; } } @Override public boolean hasMoreElements() { return !stack.isEmpty(); } @Override public InlineSequence nextElement() { return stack.pop(); } }; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + bcIndex; result = prime * result + ((caller == null) ? 0 : caller.hashCode()); result = prime * result + ((method == null) ? 0 : method.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; InlineSequence other = (InlineSequence) obj; if (bcIndex != other.bcIndex) return false; if (caller == null) { if (other.caller != null) return false; } else if (!caller.equals(other.caller)) return false; if (method == null) { if (other.method != null) return false; } else if (!method.equals(other.method)) return false; return true; } public int getBcIndex() { return bcIndex; } public void adjustBcIndex(int delta) { this.bcIndex += delta; } }