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.compilers.opt.OptOptions;
017
018 /**
019 * Instances of this class represent decisions to inline.
020 */
021 public final class InlineDecision {
022 private enum Code {
023 /**
024 * Symbolic constant coding internal state.
025 */
026 DECIDE_NO,
027 /**
028 * Symbolic constant coding internal state.
029 */
030 DECIDE_YES,
031 /**
032 * Symbolic constant coding internal state.
033 */
034 GUARDED_YES
035 }
036
037 /**
038 * Rationale for this decision
039 */
040 private final String rationale;
041 /**
042 * Holds characterization of this decision.
043 */
044 private final Code code;
045 /**
046 * The set of methods to inline.
047 */
048 private final RVMMethod[] targets;
049 /**
050 * The set of guards to use (only valid when code == GUARDED_YES)
051 */
052 private final byte[] guards;
053
054 /**
055 * Should the test-failed block be replaced with an OSR point?
056 */
057 private boolean testFailedOSR = false;
058
059 /**
060 * @param targets The methods to inline
061 * @param code the decision code
062 * @param reason a string rationale
063 */
064 private InlineDecision(RVMMethod[] targets, byte[] guards, Code code, String reason) {
065 this.code = code;
066 this.rationale = reason;
067 this.targets = targets;
068 this.guards = guards;
069 }
070
071 /**
072 * Return a decision NOT to inline.
073 *
074 * @param target the method that is not being inlined.
075 * @param reason a rationale for not inlining
076 * @return a decision NOT to inline
077 */
078 public static InlineDecision NO(RVMMethod target, String reason) {
079 RVMMethod[] targets = new RVMMethod[1];
080 targets[0] = target;
081 return new InlineDecision(targets, null, Code.DECIDE_NO, reason);
082 }
083
084 /**
085 * Return a decision NOT to inline.
086 *
087 * @param reason a rationale for not inlining
088 * @return a decision NOT to inline
089 */
090 public static InlineDecision NO(String reason) {
091 return new InlineDecision(null, null, Code.DECIDE_NO, reason);
092 }
093
094 /**
095 * Return a decision to inline without a guard.
096 * @param target the method to inline
097 * @param reason a rationale for inlining
098 * @return a decision YES to inline
099 */
100 public static InlineDecision YES(RVMMethod target, String reason) {
101 RVMMethod[] targets = new RVMMethod[1];
102 targets[0] = target;
103 return new InlineDecision(targets, null, Code.DECIDE_YES, reason);
104 }
105
106 /**
107 * Return a decision YES to do a guarded inline.
108 *
109 * @param target the method to inline
110 * @param guard the type of guard to use
111 * @param reason a rationale for inlining
112 * @return a decision YES to inline, but it is not always safe.
113 */
114 public static InlineDecision guardedYES(RVMMethod target, byte guard, String reason) {
115 RVMMethod[] targets = new RVMMethod[1];
116 byte[] guards = new byte[1];
117 targets[0] = target;
118 guards[0] = guard;
119 return new InlineDecision(targets, guards, Code.GUARDED_YES, reason);
120 }
121
122 /**
123 * Return a decision YES to do a guarded inline.
124 *
125 * @param targets The methods to inline
126 * @param guards the types of guard to use
127 * @param reason A rationale for inlining
128 * @return a decision YES to inline, but it is not always safe.
129 */
130 public static InlineDecision guardedYES(RVMMethod[] targets, byte[] guards, String reason) {
131 return new InlineDecision(targets, guards, Code.GUARDED_YES, reason);
132 }
133
134 /**
135 * Is this inline decision a YES?
136 */
137 public boolean isYES() {
138 return !isNO();
139 }
140
141 /**
142 * Is this inline decision a NO?
143 */
144 public boolean isNO() {
145 return (code == Code.DECIDE_NO);
146 }
147
148 /**
149 * Does this inline site need a guard?
150 */
151 public boolean needsGuard() {
152 return (code == Code.GUARDED_YES);
153 }
154
155 /**
156 * Return the methods to inline according to this decision.
157 */
158 public RVMMethod[] getTargets() {
159 return targets;
160 }
161
162 /**
163 * Return the guards to use according to this decision.
164 */
165 public byte[] getGuards() {
166 return guards;
167 }
168
169 /**
170 * Return the number methods to inline.
171 */
172 public int getNumberOfTargets() {
173 if (targets == null) {
174 return 0;
175 }
176 return targets.length;
177 }
178
179 public void setOSRTestFailed() { testFailedOSR = true; }
180
181 public boolean OSRTestFailed() { return testFailedOSR; }
182
183 public String toString() {
184 String s = code.toString();
185 if (testFailedOSR) {
186 s += "(OSR off-branch)";
187 }
188 s += ":" + rationale;
189 if (targets != null) {
190 for (int i = 0; i < targets.length; i++) {
191 s += " " + targets[i];
192 if (guards != null) {
193 switch (guards[i]) {
194 case OptOptions.INLINE_GUARD_METHOD_TEST:
195 s += " (method test)";
196 break;
197 case OptOptions.INLINE_GUARD_CLASS_TEST:
198 s += " (class test)";
199 break;
200 case OptOptions.INLINE_GUARD_CODE_PATCH:
201 s += " (code patch)";
202 break;
203 }
204 }
205 }
206 }
207 return s;
208 }
209 }