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}