/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * 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/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.ir; import org.jikesrvm.classloader.VM_Method; import org.jikesrvm.classloader.VM_NormalMethod; import org.jikesrvm.compilers.opt.OPT_Stack; /** * Represents an inlining sequence. * Used to uniquely identify program locations. */ public final class OPT_InlineSequence { static final boolean DEBUG = false; /** * Current method. */ public final VM_NormalMethod method; /** * Caller info. null if none. */ public final OPT_InlineSequence caller; /** * bytecode index (in caller) of call site */ public int bcIndex; /** * We need more detailed information of call site than bcIndex. */ final OPT_Instruction callSite; /** * @return contents of {@link #method} */ public VM_NormalMethod getMethod() { return method; } /** * @return contents of {@link #caller} */ public OPT_InlineSequence getCaller() { return caller; } public boolean equals(Object o) { if (!(o instanceof OPT_InlineSequence)) return false; OPT_InlineSequence is = (OPT_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 */ OPT_InlineSequence(VM_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 */ OPT_InlineSequence(VM_NormalMethod method, OPT_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 */ OPT_InlineSequence(VM_NormalMethod method, OPT_InlineSequence caller, OPT_Instruction callsite) { this.method = method; this.caller = caller; this.callSite = callsite; this.bcIndex = callsite.bcIndex; } public OPT_Instruction getCallSite() { return this.callSite; } /** * Returns the string representation of this inline sequence. */ public String toString() { StringBuilder sb = new StringBuilder(" "); for (OPT_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; OPT_InlineSequence parent = this.caller; while (parent != null) { depth++; parent = parent.caller; } return depth; } /** * Return the root method of this inline sequence */ public VM_NormalMethod getRootMethod() { OPT_InlineSequence parent = this; while (parent.caller != null) { parent = parent.caller; } return parent.method; } /** * Does this inline sequence contain a given method? */ public boolean containsMethod(VM_Method 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<OPT_InlineSequence> enumerateFromRoot() { return new java.util.Enumeration<OPT_InlineSequence>() { OPT_Stack<OPT_InlineSequence> stack; { stack = new OPT_Stack<OPT_InlineSequence>(); OPT_InlineSequence parent = OPT_InlineSequence.this; while (parent.caller != null) { stack.push(parent); parent = parent.caller; } } public boolean hasMoreElements() { return !stack.isEmpty(); } public OPT_InlineSequence nextElement() { return stack.pop(); } }; } }