001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.opt.inlining;
014
015 import org.jikesrvm.classloader.RVMMethod;
016 import org.jikesrvm.classloader.NormalMethod;
017 import org.jikesrvm.compilers.opt.ir.Instruction;
018 import org.jikesrvm.compilers.opt.util.Stack;
019
020 /**
021 * Represents an inlining sequence.
022 * Used to uniquely identify program locations.
023 */
024 public final class InlineSequence {
025 /**
026 * Current method.
027 */
028 public final NormalMethod method;
029
030 /**
031 * Caller info. null if none.
032 */
033 public final InlineSequence caller;
034
035 /**
036 * bytecode index (in caller) of call site
037 */
038 public int bcIndex;
039
040 /**
041 * We need more detailed information of call site than bcIndex.
042 */
043 final Instruction callSite;
044
045 /**
046 * @return contents of {@link #method}
047 */
048 public NormalMethod getMethod() {
049 return method;
050 }
051
052 /**
053 * @return contents of {@link #caller}
054 */
055 public InlineSequence getCaller() {
056 return caller;
057 }
058
059 public boolean equals(Object o) {
060 if (!(o instanceof InlineSequence)) return false;
061 InlineSequence is = (InlineSequence) o;
062 if (method == null) return (is.method == null);
063 if (!method.equals(is.method)) return false;
064 if (bcIndex != is.bcIndex) return false;
065 if (caller == null) return (is.caller == null);
066 return (caller.equals(is.caller));
067 }
068
069 /**
070 * Constructs a new top-level inline sequence operand.
071 *
072 * @param method current method
073 */
074 public InlineSequence(NormalMethod method) {
075 this(method, null, -1);
076 }
077
078 /**
079 * Constructs a new inline sequence operand.
080 *
081 * @param method current method
082 * @param caller caller info
083 * @param bcIndex bytecode index of call site
084 */
085 InlineSequence(NormalMethod method, InlineSequence caller, int bcIndex) {
086 this.method = method;
087 this.caller = caller;
088 this.callSite = null;
089 this.bcIndex = bcIndex;
090 }
091
092 /**
093 * Constructs a new inline sequence operand.
094 *
095 * @param method current method
096 * @param caller caller info
097 * @param callsite the call site instruction of this callee
098 */
099 public InlineSequence(NormalMethod method, InlineSequence caller, Instruction callsite) {
100 this.method = method;
101 this.caller = caller;
102 this.callSite = callsite;
103 this.bcIndex = callsite.bcIndex;
104 }
105
106 public Instruction getCallSite() {
107 return this.callSite;
108 }
109
110 /**
111 * Returns the string representation of this inline sequence.
112 */
113 public String toString() {
114 StringBuilder sb = new StringBuilder(" ");
115 for (InlineSequence is = this; is != null; is = is.caller) {
116 sb.append(is.method.getDeclaringClass().getDescriptor()).append(" ").
117 append(is.method.getName()).append(" ").
118 append(is.method.getDescriptor()).append(" ").
119 append(is.bcIndex).append(" ");
120 }
121 return sb.toString();
122 }
123
124 /**
125 * return the depth of inlining: (0 corresponds to no inlining)
126 */
127 public int getInlineDepth() {
128 int depth = 0;
129 InlineSequence parent = this.caller;
130 while (parent != null) {
131 depth++;
132 parent = parent.caller;
133 }
134 return depth;
135 }
136
137 /**
138 * Return the root method of this inline sequence
139 */
140 public NormalMethod getRootMethod() {
141 InlineSequence parent = this;
142 while (parent.caller != null) {
143 parent = parent.caller;
144 }
145 return parent.method;
146 }
147
148 /**
149 * Does this inline sequence contain a given method?
150 */
151 public boolean containsMethod(RVMMethod m) {
152 if (method == m) return true;
153 if (caller == null) return false;
154 return (caller.containsMethod(m));
155 }
156
157 /**
158 * Return a hashcode for this object.
159 *
160 * TODO: Figure out a better hashcode. Efficiency doesn't matter
161 * for now.
162 *
163 * @return the hashcode for this object.
164 */
165 public int hashCode() {
166 return bcIndex;
167 }
168
169 public java.util.Enumeration<InlineSequence> enumerateFromRoot() {
170 return new java.util.Enumeration<InlineSequence>() {
171 Stack<InlineSequence> stack;
172
173 {
174 stack = new Stack<InlineSequence>();
175 InlineSequence parent = InlineSequence.this;
176 while (parent.caller != null) {
177 stack.push(parent);
178 parent = parent.caller;
179 }
180 }
181
182 public boolean hasMoreElements() {
183 return !stack.isEmpty();
184 }
185
186 public InlineSequence nextElement() {
187 return stack.pop();
188 }
189 };
190 }
191 }