/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm.bytecode; import org.jnode.vm.objects.BootableArrayList; import org.jnode.vm.objects.VmSystemObject; import java.util.Set; import java.util.HashSet; /** * A Basic block of instructions. * <p/> * A basic block has 0-n predecessors and 0-m successors. The only exit * of a basic block is the last instruction. * * @author epr * @author Madhu Siddalingaiah * @author Levente S\u00e1ntha */ public class BasicBlock extends VmSystemObject { private final int startPC; private int endPC; private boolean startOfExceptionHandler; private boolean retTarget; private TypeStack startStack; private BootableArrayList<BasicBlock> entryBlocks = new BootableArrayList<BasicBlock>(); /** * Create a new instance * * @param startPC The first bytecode address of this block * @param endPC The first bytecode address after this block * @param startOfExceptionHandler */ public BasicBlock(int startPC, int endPC, boolean startOfExceptionHandler) { this.startPC = startPC; this.endPC = endPC; this.startOfExceptionHandler = startOfExceptionHandler; } /** * Create a new instance * * @param startPC The first bytecode address of this block */ public BasicBlock(int startPC) { this(startPC, -1, false); } /** * Gets the first bytecode address after this basic block * * @return The end pc */ public final int getEndPC() { return endPC; } /** * @param endPC The endPC to set. */ public final void setEndPC(int endPC) { this.endPC = endPC; } /** * @param startOfExceptionHandler The startOfExceptionHandler to set. */ public final void setStartOfExceptionHandler(boolean startOfExceptionHandler) { this.startOfExceptionHandler = startOfExceptionHandler; } public void setRetTarget(boolean retTarget) { this.retTarget = retTarget; } /** * Gets the first bytecode address of this basic block * * @return The start pc */ public final int getStartPC() { return startPC; } /** * Does this block contain a given bytecode address? * * @param address * @return boolean */ public final boolean contains(int address) { return ((address >= startPC) && (address < endPC)); } /** * @return String * @see java.lang.Object#toString() */ public String toString() { final StringBuilder buf = new StringBuilder(); buf.append(startPC); buf.append('-'); buf.append(endPC); buf.append(" [entry:"); buf.append(startStack); buf.append(';'); addEntryBlockInfo(buf); buf.append(']'); if (startOfExceptionHandler) { buf.append(" (EH)"); } return buf.toString(); } private void addEntryBlockInfo(StringBuilder buf) { boolean first = true; for (BasicBlock bb : entryBlocks) { if (first) { first = false; } else { buf.append(','); } buf.append(bb.getStartPC()); buf.append('-'); buf.append(bb.getEndPC()); } } /** * Is this block the start of an exception handler? * * @return boolean */ public final boolean isStartOfExceptionHandler() { return startOfExceptionHandler; } /** * Gets the stack types at the start of this basic block. * * @return Returns the startStack. * @see org.jnode.vm.JvmType */ public final TypeStack getStartStack() { return this.startStack; } /** * Set the stack types at the start of this basic block. * * @param startStack The startStack to set. * @see org.jnode.vm.JvmType */ public final void setStartStack(TypeStack startStack) { this.startStack = startStack; } /** * Add a list of block that can can transfer execution to this block. * * @param entryBlock */ public final void addEntryBlock(BasicBlock entryBlock) { if (entryBlock != null) { this.entryBlocks.add(entryBlock); } } public boolean isLive() { Set<BasicBlock> checked = new HashSet<BasicBlock>(); checked.add(this); return isLive(checked); } private boolean isLive(Set<BasicBlock> checked) { if (startPC == 0) return true; if (startOfExceptionHandler) return true; if (retTarget) return true; if (entryBlocks != null) { for (BasicBlock bb : entryBlocks) { if (!checked.contains(bb)) { checked.add(bb); if (bb.isLive(checked)) { return true; } } } } return false; } }