/*
* 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. null if none.
*/
public final InlineSequence caller;
/**
* bytecode index (in caller) of call site
*/
public 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;
}
public boolean equals(Object o) {
if (!(o instanceof InlineSequence)) return false;
InlineSequence is = (InlineSequence) o;
if (method == null) return (is.method == null);
if (!method.equals(is.method)) return false;
if (bcIndex != is.bcIndex) return false;
if (caller == null) return (is.caller == null);
return (caller.equals(is.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.bcIndex;
}
public Instruction getCallSite() {
return this.callSite;
}
/**
* Returns the string representation of this inline sequence.
*/
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;
}
/**
* Does this inline sequence contain a given method?
*/
public boolean containsMethod(RVMMethod m) {
if (method == m) return true;
if (caller == null) return false;
return (caller.containsMethod(m));
}
/**
* Return a hashcode for this object.
*
* TODO: Figure out a better hashcode. Efficiency doesn't matter
* for now.
*
* @return the hashcode for this object.
*/
public int hashCode() {
return bcIndex;
}
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;
}
}
public boolean hasMoreElements() {
return !stack.isEmpty();
}
public InlineSequence nextElement() {
return stack.pop();
}
};
}
}