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 @Override 184 public String toString() { 185 String s = code.toString(); 186 if (testFailedOSR) { 187 s += "(OSR off-branch)"; 188 } 189 s += ":" + rationale; 190 if (targets != null) { 191 for (int i = 0; i < targets.length; i++) { 192 s += " " + targets[i]; 193 if (guards != null) { 194 switch (guards[i]) { 195 case OptOptions.INLINE_GUARD_METHOD_TEST: 196 s += " (method test)"; 197 break; 198 case OptOptions.INLINE_GUARD_CLASS_TEST: 199 s += " (class test)"; 200 break; 201 case OptOptions.INLINE_GUARD_CODE_PATCH: 202 s += " (code patch)"; 203 break; 204 } 205 } 206 } 207 } 208 return s; 209 } 210 }