/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.vm.classfile; import java.io.*; import com.sun.max.vm.bytecode.graft.*; /** * Exception table entries in code attributes as described in #4.7.3. */ public final class ExceptionHandlerEntry { public static final ExceptionHandlerEntry[] NONE = {}; private final int startBCI; private final int endBCI; private final int handlerBCI; private final int catchTypeIndex; public int startBCI() { return startBCI; } public int endBCI() { return endBCI; } public int handlerBCI() { return handlerBCI; } public int catchTypeIndex() { return catchTypeIndex; } public ExceptionHandlerEntry(int startAddress, int endAddress, int handlerAddress, int catchTypeIndex) { this.startBCI = startAddress; this.endBCI = endAddress; this.handlerBCI = handlerAddress; this.catchTypeIndex = catchTypeIndex; } public ExceptionHandlerEntry changeEndBCI(int address) { return new ExceptionHandlerEntry(startBCI, address, handlerBCI, catchTypeIndex); } /** * Determines if a given BCI is within the range {@code [startProgramCounter() .. endProgramCounter())}. */ public boolean rangeIncludes(int bci) { return startBCI <= bci && bci < endBCI; } public ExceptionHandlerEntry relocate(OpcodeBCIRelocator relocator) { return new ExceptionHandlerEntry(relocator.relocate(startBCI), relocator.relocate(endBCI), relocator.relocate(handlerBCI), catchTypeIndex); } @Override public String toString() { return "[" + startBCI + " .. " + endBCI + ") -> " + handlerBCI + " {type=" + catchTypeIndex + "}"; } public static void encode(ExceptionHandlerEntry[] entries, DataOutputStream dataOutputStream) throws IOException { final int length = entries.length; assert length > 0 && length <= Short.MAX_VALUE; dataOutputStream.writeShort(length); boolean byteEncoding = true; for (ExceptionHandlerEntry entry : entries) { if (!(entry.startBCI <= 0xff && entry.endBCI <= 0xff && entry.handlerBCI <= 0xff && entry.catchTypeIndex <= 0xff)) { byteEncoding = false; break; } } dataOutputStream.writeBoolean(byteEncoding); if (byteEncoding) { for (ExceptionHandlerEntry entry : entries) { dataOutputStream.writeByte(entry.startBCI); dataOutputStream.writeByte(entry.endBCI); dataOutputStream.writeByte(entry.handlerBCI); dataOutputStream.writeByte(entry.catchTypeIndex); } } else { for (ExceptionHandlerEntry entry : entries) { dataOutputStream.writeShort(entry.startBCI); dataOutputStream.writeShort(entry.endBCI); dataOutputStream.writeShort(entry.handlerBCI); dataOutputStream.writeShort(entry.catchTypeIndex); } } } public static ExceptionHandlerEntry[] decode(DataInputStream dataInputStream) throws IOException { final int length = dataInputStream.readUnsignedShort(); assert length != 0; final ExceptionHandlerEntry[] entries = new ExceptionHandlerEntry[length]; final boolean byteEncoding = dataInputStream.readBoolean(); if (byteEncoding) { for (int i = 0; i < length; ++i) { final ExceptionHandlerEntry entry = new ExceptionHandlerEntry( dataInputStream.readUnsignedByte(), dataInputStream.readUnsignedByte(), dataInputStream.readUnsignedByte(), dataInputStream.readUnsignedByte()); entries[i] = entry; } } else { for (int i = 0; i < length; ++i) { final ExceptionHandlerEntry entry = new ExceptionHandlerEntry( dataInputStream.readUnsignedShort(), dataInputStream.readUnsignedShort(), dataInputStream.readUnsignedShort(), dataInputStream.readUnsignedShort()); entries[i] = entry; } } return entries; } /** * Decodes the exception handler table as an array of triplets (start bci, end bci, handler bci). */ public static int[] decodeHandlerBCIs(DataInputStream dataInputStream) throws IOException { final int length = dataInputStream.readUnsignedShort(); assert length != 0; final int[] entries = new int[length * 3]; final boolean byteEncoding = dataInputStream.readBoolean(); if (byteEncoding) { for (int i = 0; i < entries.length; i += 3) { entries[i ] = dataInputStream.readUnsignedByte(); entries[i + 1] = dataInputStream.readUnsignedByte(); entries[i + 2] = dataInputStream.readUnsignedByte(); dataInputStream.skip(1); } } else { for (int i = 0; i < entries.length; i += 3) { entries[i ] = dataInputStream.readUnsignedShort(); entries[i + 1] = dataInputStream.readUnsignedShort(); entries[i + 2] = dataInputStream.readUnsignedShort(); dataInputStream.skip(2); } } return entries; } }