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