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 */ 013package org.jikesrvm.compilers.opt.inlining; 014 015import org.jikesrvm.classloader.RVMMethod; 016import org.jikesrvm.classloader.NormalMethod; 017import org.jikesrvm.compilers.opt.ir.Instruction; 018import org.jikesrvm.compilers.opt.util.Stack; 019 020/** 021 * Represents an inlining sequence. 022 * Used to uniquely identify program locations. 023 */ 024public 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 * @param m the method to search for 141 * @return whether this inline sequence contains a given method 142 */ 143 public boolean containsMethod(RVMMethod m) { 144 if (method == m) return true; 145 if (caller == null) return false; 146 return (caller.containsMethod(m)); 147 } 148 149 public java.util.Enumeration<InlineSequence> enumerateFromRoot() { 150 return new java.util.Enumeration<InlineSequence>() { 151 Stack<InlineSequence> stack; 152 153 { 154 stack = new Stack<InlineSequence>(); 155 InlineSequence parent = InlineSequence.this; 156 while (parent.caller != null) { 157 stack.push(parent); 158 parent = parent.caller; 159 } 160 } 161 162 @Override 163 public boolean hasMoreElements() { 164 return !stack.isEmpty(); 165 } 166 167 @Override 168 public InlineSequence nextElement() { 169 return stack.pop(); 170 } 171 }; 172 } 173 174 @Override 175 public int hashCode() { 176 final int prime = 31; 177 int result = 1; 178 result = prime * result + bcIndex; 179 result = prime * result + ((caller == null) ? 0 : caller.hashCode()); 180 result = prime * result + ((method == null) ? 0 : method.hashCode()); 181 return result; 182 } 183 184 @Override 185 public boolean equals(Object obj) { 186 if (this == obj) 187 return true; 188 if (obj == null) 189 return false; 190 if (getClass() != obj.getClass()) 191 return false; 192 InlineSequence other = (InlineSequence) obj; 193 if (bcIndex != other.bcIndex) 194 return false; 195 if (caller == null) { 196 if (other.caller != null) 197 return false; 198 } else if (!caller.equals(other.caller)) 199 return false; 200 if (method == null) { 201 if (other.method != null) 202 return false; 203 } else if (!method.equals(other.method)) 204 return false; 205 return true; 206 } 207 208}