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. {@code 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 /** 060 * Constructs a new top-level inline sequence operand. 061 * 062 * @param method current method 063 */ 064 public InlineSequence(NormalMethod method) { 065 this(method, null, -1); 066 } 067 068 /** 069 * Constructs a new inline sequence operand. 070 * 071 * @param method current method 072 * @param caller caller info 073 * @param bcIndex bytecode index of call site 074 */ 075 InlineSequence(NormalMethod method, InlineSequence caller, int bcIndex) { 076 this.method = method; 077 this.caller = caller; 078 this.callSite = null; 079 this.bcIndex = bcIndex; 080 } 081 082 /** 083 * Constructs a new inline sequence operand. 084 * 085 * @param method current method 086 * @param caller caller info 087 * @param callsite the call site instruction of this callee 088 */ 089 public InlineSequence(NormalMethod method, InlineSequence caller, Instruction callsite) { 090 this.method = method; 091 this.caller = caller; 092 this.callSite = callsite; 093 this.bcIndex = callsite.bcIndex; 094 } 095 096 public Instruction getCallSite() { 097 return this.callSite; 098 } 099 100 /** 101 * Returns the string representation of this inline sequence. 102 */ 103 @Override 104 public String toString() { 105 StringBuilder sb = new StringBuilder(" "); 106 for (InlineSequence is = this; is != null; is = is.caller) { 107 sb.append(is.method.getDeclaringClass().getDescriptor()).append(" "). 108 append(is.method.getName()).append(" "). 109 append(is.method.getDescriptor()).append(" "). 110 append(is.bcIndex).append(" "); 111 } 112 return sb.toString(); 113 } 114 115 /** 116 * return the depth of inlining: (0 corresponds to no inlining) 117 */ 118 public int getInlineDepth() { 119 int depth = 0; 120 InlineSequence parent = this.caller; 121 while (parent != null) { 122 depth++; 123 parent = parent.caller; 124 } 125 return depth; 126 } 127 128 /** 129 * Return the root method of this inline sequence 130 */ 131 public NormalMethod getRootMethod() { 132 InlineSequence parent = this; 133 while (parent.caller != null) { 134 parent = parent.caller; 135 } 136 return parent.method; 137 } 138 139 /** 140 * Does this inline sequence contain a given method? 141 */ 142 public boolean containsMethod(RVMMethod m) { 143 if (method == m) return true; 144 if (caller == null) return false; 145 return (caller.containsMethod(m)); 146 } 147 148 public java.util.Enumeration<InlineSequence> enumerateFromRoot() { 149 return new java.util.Enumeration<InlineSequence>() { 150 Stack<InlineSequence> stack; 151 152 { 153 stack = new Stack<InlineSequence>(); 154 InlineSequence parent = InlineSequence.this; 155 while (parent.caller != null) { 156 stack.push(parent); 157 parent = parent.caller; 158 } 159 } 160 161 @Override 162 public boolean hasMoreElements() { 163 return !stack.isEmpty(); 164 } 165 166 @Override 167 public InlineSequence nextElement() { 168 return stack.pop(); 169 } 170 }; 171 } 172 173 @Override 174 public int hashCode() { 175 final int prime = 31; 176 int result = 1; 177 result = prime * result + bcIndex; 178 result = prime * result + ((caller == null) ? 0 : caller.hashCode()); 179 result = prime * result + ((method == null) ? 0 : method.hashCode()); 180 return result; 181 } 182 183 @Override 184 public boolean equals(Object obj) { 185 if (this == obj) 186 return true; 187 if (obj == null) 188 return false; 189 if (getClass() != obj.getClass()) 190 return false; 191 InlineSequence other = (InlineSequence) obj; 192 if (bcIndex != other.bcIndex) 193 return false; 194 if (caller == null) { 195 if (other.caller != null) 196 return false; 197 } else if (!caller.equals(other.caller)) 198 return false; 199 if (method == null) { 200 if (other.method != null) 201 return false; 202 } else if (!method.equals(other.method)) 203 return false; 204 return true; 205 } 206 207 }