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.bc2ir;
014
015import static org.jikesrvm.compilers.opt.driver.OptConstants.SYNTH_CATCH_BCI;
016import static org.jikesrvm.compilers.opt.ir.Operators.GET_CAUGHT_EXCEPTION;
017
018import org.jikesrvm.classloader.TypeReference;
019import org.jikesrvm.compilers.opt.inlining.InlineSequence;
020import org.jikesrvm.compilers.opt.ir.BasicBlock;
021import org.jikesrvm.compilers.opt.ir.ControlFlowGraph;
022import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock;
023import org.jikesrvm.compilers.opt.ir.GenericRegisterPool;
024import org.jikesrvm.compilers.opt.ir.Instruction;
025import org.jikesrvm.compilers.opt.ir.Nullary;
026import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
027import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
028import org.jikesrvm.compilers.opt.ir.operand.TypeOperand;
029
030/**
031 * Extend BasicBlockLE for handler blocks
032 */
033final class HandlerBlockLE extends BasicBlockLE {
034  /**
035   * The RegisterOperand that code should use to access
036   * the caught exception object
037   */
038  final RegisterOperand exceptionObject;
039
040  /**
041   * The synthetic entry basic block for this handler.
042   * It contains the instruction sequence to get the caught exception object
043   * into a "normal" register operand (exceptionObject);
044   */
045  final ExceptionHandlerBasicBlock entryBlock;
046
047  /**
048   * Create a new exception handler BBLE (and exception handler basic block)
049   * for the specified bytecode index and exception type.
050   *
051   * @param loc bytecode index
052   * @param position inline sequence
053   * @param eType   exception type
054   * @param temps the register pool to allocate exceptionObject from
055   * @param exprStackSize max size of expression stack
056   * @param cfg ControlFlowGraph into which the block
057   *            will eventually be inserted
058   */
059  HandlerBlockLE(int loc, InlineSequence position, TypeOperand eType, GenericRegisterPool temps,
060                 int exprStackSize, ControlFlowGraph cfg) {
061    super(loc);
062    entryBlock = new ExceptionHandlerBasicBlock(SYNTH_CATCH_BCI, position, eType, cfg);
063    block = new BasicBlock(loc, position, cfg);
064    // NOTE: We intentionally use throwable rather than eType to avoid
065    // having the complexity of having to regenerate the handler when a
066    // new type of caught exception is added. Since we shouldn't care about
067    // the performance of code in exception handling blocks, this
068    // should be the right tradeoff.
069    exceptionObject = temps.makeTemp(TypeReference.JavaLangThrowable);
070    BC2IR.setGuardForRegOp(exceptionObject, new TrueGuardOperand());    // know not null
071    high = loc;
072    // Set up expression stack on entry to have the caught exception operand.
073    stackState = new OperandStack(exprStackSize);
074    stackState.push(exceptionObject);
075    setStackKnown();
076    // entry block contains instructions to transfer the caught
077    // exception object to exceptionObject.
078    Instruction s = Nullary.create(GET_CAUGHT_EXCEPTION, exceptionObject.copyD2D());
079    entryBlock.appendInstruction(s);
080    s.bcIndex = SYNTH_CATCH_BCI;
081    entryBlock.insertOut(block);
082  }
083
084  void addCaughtException(TypeOperand et) {
085    entryBlock.addCaughtException(et);
086  }
087
088  byte mayCatchException(TypeReference et) {
089    return entryBlock.mayCatchException(et);
090  }
091
092  byte mustCatchException(TypeReference et) {
093    return entryBlock.mustCatchException(et);
094  }
095}