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.runtime;
014    
015    import org.jikesrvm.ArchitectureSpecific.Registers;
016    import org.jikesrvm.compilers.common.CompiledMethod;
017    import org.vmmagic.pragma.Unpreemptible;
018    import org.vmmagic.unboxed.Address;
019    
020    /**
021     * Interface for exception delivery called by RuntimeEntrypoints.deliverException() to
022     * pass control to a stackframe whose method has an appropriate "catch" block
023     * or to step over a stackframe that does not have an appropriate catch block.
024     * <p>
025     * The exception delivery implementation is specific to the compiler
026     * that generated the method's machine instructions.
027     * <p>
028     * Note that the "deliverException" and "unwindStackFrame" methods of this
029     * class will be called in an environment that does not permit garbage
030     * collection: see VM.disableGC().
031     * We must do this because some of the parameters to these methods are raw
032     * machine addresses. They are not recognized by the garbage collector as
033     * Object references and so would not be correctly fixed up in the event of
034     * object motion during GC. As a
035     * consequence, implementors of these methods must not cause object allocations
036     * to take place (i.e. by calling "new" either directly or indirectly).
037     */
038    public abstract class ExceptionDeliverer {
039      /**
040       * Stackframe's method has a "catch" block for exception being
041       * thrown and control is to be passed to that catch block.
042       *
043       * <p> Note:
044       *   Implementers must issue the following two lines just before
045       *   transferring control to the catch block:
046       *
047       * <pre>
048       *           VM.enableGC();
049       *           registers.inuse = false;
050       * </pre>
051       *
052       * <p> Note: this method does not return
053       * (execution resumes at catchBlockInstructionAddress)
054       *
055       * @param compiledMethod method whose catch block is to receive control
056       * @param catchBlockInstructionAddress instruction address at which
057       * to begin execution of catch block
058       * @param exceptionObject exception object to be passed as argument to
059       * catch block
060       * @param registers registers to be loaded before passing control to
061       * catch block
062       */
063      @Unpreemptible("Deliver exception possibly from unpreemptible code")
064      public abstract void deliverException(CompiledMethod compiledMethod, Address catchBlockInstructionAddress,
065                                            Throwable exceptionObject, Registers registers);
066    
067      /**
068       * Stackframe's method has no "catch" block for exception being thrown
069       * and stackframe is to be "unwound" as follows:
070       *
071       * <ul>
072       * <li> 1. for a synchronized method, call ObjectModel.genericUnlock(),
073       *     passing it the appropriate "lock" object
074       *     <ul>
075       *       <li>for non-static methods, the lock is the method's
076       *         first argument ("this")
077       *       <li>for static methods, the lock is the method's java.lang.Class
078       *     </ul>
079       *
080       * <li> 2. restore the non-volatile registers (including fp) that were saved
081       *     in the method's prologue, by copying them from the method's stackframe
082       *     save area into the provided "registers" object
083       * </ul>
084       *
085       * @param compiledMethod method whose stackframe is to be unwound
086       * @param registers thread state to be updated by restoring non-volatiles
087       *                  and unwinding the stackframe
088       */
089      @Unpreemptible("Unwind stack possibly from unpreemptible code")
090      public abstract void unwindStackFrame(CompiledMethod compiledMethod, Registers registers);
091    }