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.runtime;
014
015import org.jikesrvm.architecture.AbstractRegisters;
016import org.jikesrvm.compilers.common.CompiledMethod;
017import org.vmmagic.pragma.Unpreemptible;
018import 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 */
038public 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, AbstractRegisters 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, AbstractRegisters registers);
091}