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.compilers.opt.OptOptions; 017 018/** 019 * Instances of this class represent decisions to inline. 020 */ 021public 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 guards the chosen guards. will be {@code null} if no guards are necessary 062 * @param code the decision code 063 * @param reason a string rationale 064 */ 065 private InlineDecision(RVMMethod[] targets, byte[] guards, Code code, String reason) { 066 this.code = code; 067 this.rationale = reason; 068 this.targets = targets; 069 this.guards = guards; 070 } 071 072 /** 073 * Return a decision NOT to inline. 074 * 075 * @param target the method that is not being inlined. 076 * @param reason a rationale for not inlining 077 * @return a decision NOT to inline 078 */ 079 public static InlineDecision NO(RVMMethod target, String reason) { 080 RVMMethod[] targets = new RVMMethod[1]; 081 targets[0] = target; 082 return new InlineDecision(targets, null, Code.DECIDE_NO, reason); 083 } 084 085 /** 086 * Return a decision NOT to inline. 087 * 088 * @param reason a rationale for not inlining 089 * @return a decision NOT to inline 090 */ 091 public static InlineDecision NO(String reason) { 092 return new InlineDecision(null, null, Code.DECIDE_NO, reason); 093 } 094 095 /** 096 * Return a decision to inline without a guard. 097 * @param target the method to inline 098 * @param reason a rationale for inlining 099 * @return a decision YES to inline 100 */ 101 public static InlineDecision YES(RVMMethod target, String reason) { 102 RVMMethod[] targets = new RVMMethod[1]; 103 targets[0] = target; 104 return new InlineDecision(targets, null, Code.DECIDE_YES, reason); 105 } 106 107 /** 108 * Return a decision YES to do a guarded inline. 109 * 110 * @param target the method to inline 111 * @param guard the type of guard to use 112 * @param reason a rationale for inlining 113 * @return a decision YES to inline, but it is not always safe. 114 */ 115 public static InlineDecision guardedYES(RVMMethod target, byte guard, String reason) { 116 RVMMethod[] targets = new RVMMethod[1]; 117 byte[] guards = new byte[1]; 118 targets[0] = target; 119 guards[0] = guard; 120 return new InlineDecision(targets, guards, Code.GUARDED_YES, reason); 121 } 122 123 /** 124 * Return a decision YES to do a guarded inline. 125 * 126 * @param targets The methods to inline 127 * @param guards the types of guard to use 128 * @param reason A rationale for inlining 129 * @return a decision YES to inline, but it is not always safe. 130 */ 131 public static InlineDecision guardedYES(RVMMethod[] targets, byte[] guards, String reason) { 132 return new InlineDecision(targets, guards, Code.GUARDED_YES, reason); 133 } 134 135 /** 136 * @return whether this inline decision is a YES 137 */ 138 public boolean isYES() { 139 return !isNO(); 140 } 141 142 /** 143 * @return whether this inline decision is a NO 144 */ 145 public boolean isNO() { 146 return (code == Code.DECIDE_NO); 147 } 148 149 /** 150 * @return whether this inline site needs a guard 151 */ 152 public boolean needsGuard() { 153 return (code == Code.GUARDED_YES); 154 } 155 156 /** 157 * @return the methods to inline according to this decision. 158 */ 159 public RVMMethod[] getTargets() { 160 return targets; 161 } 162 163 /** 164 * @return the guards to use according to this decision. 165 */ 166 public byte[] getGuards() { 167 return guards; 168 } 169 170 /** 171 * @return the number methods to inline 172 */ 173 public int getNumberOfTargets() { 174 if (targets == null) { 175 return 0; 176 } 177 return targets.length; 178 } 179 180 public void setOSRTestFailed() { 181 testFailedOSR = true; 182 } 183 184 public boolean OSRTestFailed() { 185 return testFailedOSR; 186 } 187 188 @Override 189 public String toString() { 190 StringBuilder s = new StringBuilder(code.toString()); 191 if (testFailedOSR) { 192 s.append("(OSR off-branch)"); 193 } 194 s.append(':'); 195 s.append(rationale); 196 if (targets != null) { 197 for (int i = 0; i < targets.length; i++) { 198 s.append(' '); 199 s.append(targets[i]); 200 if (guards != null) { 201 switch (guards[i]) { 202 case OptOptions.INLINE_GUARD_METHOD_TEST: 203 s.append(" (method test)"); 204 break; 205 case OptOptions.INLINE_GUARD_CLASS_TEST: 206 s.append(" (class test)"); 207 break; 208 case OptOptions.INLINE_GUARD_CODE_PATCH: 209 s.append(" (code patch)"); 210 break; 211 } 212 } 213 } 214 } 215 return s.toString(); 216 } 217}