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; 014 015import java.io.PrintWriter; 016import java.io.StringWriter; 017 018import org.jikesrvm.VM; 019import org.jikesrvm.classloader.TypeReference; 020 021/** 022 * Use this exception if we encounter a runtime error in the dynamic 023 * optimizing compiler. The caller can recover by calling the 024 * non-optimizing compiler instead (or by reverting to the previous 025 * version of compiled code). 026 */ 027public class OptimizingCompilerException extends RuntimeException { 028 /** Support for exception serialization */ 029 static final long serialVersionUID = -868535710873341956L; 030 031 /** 032 * Capture illegal upcasts from magic types to java.lang.Object 033 */ 034 public static final class IllegalUpcast extends RuntimeException { 035 /** Support for exception serialization */ 036 static final long serialVersionUID = -847866659938089530L; 037 /** Unboxed type that was attempted to convert to an Object */ 038 final transient TypeReference magicType; 039 040 public IllegalUpcast(TypeReference type) { 041 super("Illegal upcast from " + type + " to java.lang.Object"); 042 magicType = type; 043 } 044 } 045 046 /** 047 * When running in the RVM, typically optimizing compiler 048 * exceptions are caught, optionally a message is printed, and we 049 * fallback to using the baseline compiler. However, this 050 * may not be desirable when running regression testing because 051 * an optimizing compiler exception may be a symptom of a serious failure. 052 * Thus, the code throwing the exception can use an optional boolean value 053 * to indicate if the exception is "normal" or if it should be treated 054 * as a fatal failure for the purpose of regression testing. 055 */ 056 public boolean isFatal = true; 057 058 public OptimizingCompilerException() { } 059 060 /** 061 * @param b is the exception fatal? 062 */ 063 public OptimizingCompilerException(boolean b) { 064 isFatal = b; 065 } 066 067 /** 068 * @param err message describing reason for exception 069 */ 070 public OptimizingCompilerException(String err) { 071 super(err); 072 } 073 074 /** 075 * @param err message describing reason for exception 076 * @param b is the exception fatal? 077 */ 078 public OptimizingCompilerException(String err, boolean b) { 079 super(err); 080 isFatal = b; 081 } 082 083 /** 084 * @param module opt compiler module in which exception was raised 085 * @param err message describing reason for exception 086 */ 087 public OptimizingCompilerException(String module, String err) { 088 super("ERROR produced in module:" + module + "\n " + err + "\n"); 089 } 090 091 /** 092 * @param module opt compiler module in which exception was raised 093 * @param err1 message describing reason for exception 094 * @param err2 message describing reason for exception 095 */ 096 public OptimizingCompilerException(String module, String err1, String err2) { 097 super("ERROR produced in module:" + module + "\n " + err1 + " " + err2 + "\n"); 098 } 099 100 /** 101 * @param module opt compiler module in which exception was raised 102 * @param err1 message describing reason for exception 103 * @param obj object to print describing reason for exception 104 */ 105 public OptimizingCompilerException(String module, String err1, Object obj) { 106 this(module, err1, obj.toString()); 107 } 108 109 /** 110 * @param module opt compiler module in which exception was raised 111 * @param err1 message describing reason for exception 112 * @param val integer to print describing reason for exception 113 */ 114 public OptimizingCompilerException(String module, String err1, int val) { 115 this(module, err1, Integer.toString(val)); 116 } 117 118 /** 119 * @param module opt compiler module in which exception was raised 120 * @param err1 message describing reason for exception 121 * @param err2 message describing reason for exception 122 * @param err3 message describing reason for exception 123 */ 124 public OptimizingCompilerException(String module, String err1, String err2, String err3) { 125 super("ERROR produced in module:" + module + "\n " + err1 + " " + err2 + "\n" + err3 + "\n"); 126 } 127 128 /** 129 * @param module opt compiler module in which exception was raised 130 * @param err1 message describing reason for exception 131 * @param err2 message describing reason for exception 132 * @param obj object to print describing reason for exception 133 */ 134 public OptimizingCompilerException(String module, String err1, String err2, Object obj) { 135 this(module, err1, err2, obj.toString()); 136 } 137 138 /** 139 * @param module opt compiler module in which exception was raised 140 * @param err1 message describing reason for exception 141 * @param err2 message describing reason for exception 142 * @param val integer to print describing reason for exception 143 */ 144 OptimizingCompilerException(String module, String err1, String err2, int val) { 145 this(module, err1, err2, Integer.toString(val)); 146 } 147 148 /** 149 * Use the UNREACHABLE methods to mark code that should never execute 150 * e.g., unexpected cases of switch statements and nested if/then/else 151 * @throws OptimizingCompilerException because the code is supposed 152 * to be unreachable 153 */ 154 public static void UNREACHABLE() throws OptimizingCompilerException { 155 throw new OptimizingCompilerException("Executed UNREACHABLE code"); 156 } 157 158 /** 159 * Use the UNREACHABLE methods to mark code that should never execute 160 * e.g., unexpected cases of switch statements and nested if/then/else 161 * @param module module in which exception occurred 162 * @throws OptimizingCompilerException because the code is supposed 163 * to be unreachable 164 */ 165 public static void UNREACHABLE(String module) throws OptimizingCompilerException { 166 throw new OptimizingCompilerException(module, "Executed UNREACHABLE code"); 167 } 168 169 /** 170 * Use the UNREACHABLE methods to mark code that should never execute 171 * e.g., unexpected cases of switch statements and nested if/then/else 172 * @param module opt compiler module in which exception was raised 173 * @param err1 message describing reason for exception 174 * @throws OptimizingCompilerException because the code is supposed 175 * to be unreachable 176 */ 177 public static void UNREACHABLE(String module, String err1) throws OptimizingCompilerException { 178 throw new OptimizingCompilerException(module, "Executed UNREACHABLE code", err1); 179 } 180 181 /** 182 * Use the UNREACHABLE methods to mark code that should never execute 183 * e.g., unexpected cases of switch statements and nested if/then/else 184 * @param module opt compiler module in which exception was raised 185 * @param err1 message describing reason for exception 186 * @param err2 message describing reason for exception 187 * @throws OptimizingCompilerException because the code is supposed 188 * to be unreachable 189 */ 190 public static void UNREACHABLE(String module, String err1, String err2) throws OptimizingCompilerException { 191 throw new OptimizingCompilerException(module, "Executed UNREACHABLE code", err1, err2); 192 } 193 194 /** 195 * Incomplete function in IA32 port. 196 * @throws OptimizingCompilerException because the required functionality 197 * is NYI 198 */ 199 public static void TODO() throws OptimizingCompilerException { 200 throw new OptimizingCompilerException("Unsupported function in IA32 port"); 201 } 202 203 /** 204 * Incomplete function in IA32 port. 205 * @param module opt compiler module in which exception was raised 206 * @throws OptimizingCompilerException because the required functionality 207 * is NYI 208 */ 209 public static void TODO(String module) throws OptimizingCompilerException { 210 throw new OptimizingCompilerException(module, "Unsupported function in IA32 port"); 211 } 212 213 /** 214 * Checks that the condition holds. Fails by throwing an {@link OptimizingCompilerException} 215 * if the condition doesn't hold and assertions are enabled. 216 * <p> 217 * Use this in preference to normal assertions if it's possible to recover from the 218 * error by switching to the baseline compiler 219 * 220 * @param b condition to check 221 */ 222 public static void opt_assert(boolean b) { 223 if (!VM.VerifyAssertions) { 224 throw new Error("Assertion should have been guarded by VM.VerifyAssertions"); 225 } 226 if (!b) { 227 throw new OptimizingCompilerException("Assertion failure"); 228 } 229 } 230 231 /** 232 * Checks that the condition holds. Fails by throwing an {@link OptimizingCompilerException} 233 * if the condition doesn't hold and assertions are enabled. 234 * <p> 235 * Use this in preference to normal assertions if it's possible to recover from the 236 * error by switching to the baseline compiler 237 * 238 * @param b condition to check 239 * @param message the message to print 240 */ 241 public static void opt_assert(boolean b, String message) { 242 if (!VM.VerifyAssertions) { 243 throw new Error("Assertion should have been guarded by VM.VerifyAssertions"); 244 } 245 if (!b) { 246 throw new OptimizingCompilerException("Assertion failure - " + message); 247 } 248 } 249 250 /** 251 * Return a string that is the printout of level stackframes in the stacktrace. 252 * @param level the number of levels to print 253 * @return n-level dump of stacktrace 254 */ 255 public String trace(int level) { 256 StringWriter sw = new StringWriter(); 257 PrintWriter pw = new PrintWriter(sw); 258 printStackTrace(pw); 259 int count = 0, i = 0; 260 StringBuffer sb = sw.getBuffer(); 261 for (; i < sb.length() && count < level + 1; i++) { 262 if (sb.charAt(i) == '\n') { 263 count++; 264 } 265 } 266 sb.setLength(i); 267 return sb.toString(); 268 } 269}