/* * StackMapFrame.java 1.4 01/03/30 * * Copyright (c) 2000 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * Use is subject to license terms. */ package components; import java.io.DataOutput; import java.io.DataInput; import java.io.IOException; import util.DataFormatException; import vm.Const; public class StackMapFrame { // A single frame in the stack map table public static final int ITEM_Bogus = 0; public static final int ITEM_Integer = 1; public static final int ITEM_Float = 2; public static final int ITEM_Double = 3; public static final int ITEM_Long = 4; public static final int ITEM_Null = 5; public static final int ITEM_InitObject = 6; public static final int ITEM_Object = 7; public static final int ITEM_NewObject = 8; int offset; ConstantObject locals[]; ConstantObject stack[]; // Read in a frame from the specified data input stream. StackMapFrame(DataInput in, ConstantObject globals[]) throws IOException { this.offset = in.readShort(); this.locals = readOneTable(in, globals); this.stack = readOneTable(in, globals); } private ConstantObject[] readOneTable(DataInput in, ConstantObject globals[]) throws IOException { int length = in.readShort(); ConstantObject result[] = new ConstantObject[length]; for (int i = 0; i < length; i++) { int tag = in.readByte(); switch(tag) { case ITEM_Bogus: case ITEM_Integer: case ITEM_Float: case ITEM_Double: case ITEM_Long: case ITEM_Null: case ITEM_InitObject: // Small non-negative values represent the corresponding // type. result[i] = new SingleValueConstant(tag); break; case ITEM_Object: result[i] = globals[in.readShort()]; break; case ITEM_NewObject: // This is a hack, but it's not really worth creating a new // type to represent this. Negative numbers represent new // objects. result[i] = new SingleValueConstant(~in.readShort()); break; default: System.out.println("Unknown tag"); } } return result; } public int writeData(DataOutput out) throws IOException { out.writeShort(offset); // Return the number of bytes that we've written return 2 + writeData(out, locals) + writeData(out, stack); } public int writeData(DataOutput out, ConstantObject[] table) throws IOException { int count = 0; out.writeShort(table.length); count += 2; for (int i = 0; i < table.length; i++) { if (table[i] instanceof SingleValueConstant) { int value = ((SingleValueConstant)table[i]).value; if (value < 0) { out.writeByte(ITEM_NewObject); out.writeShort(~value); count += 3; } else { out.writeShort(value); count += 2; } } else if (table[i] instanceof ClassConstant) { out.writeByte(ITEM_Object); out.writeShort(((ClassConstant)table[i]).name.index); count += 3; } } return count; } public void externalize( ConstantPool p ){ // do nothing } public void countConstantReferences(boolean isRelocatable) { if (isRelocatable) { // Is this the right thing?? for (int i = 0; i < locals.length; i++) { locals[i].incReference(); } for (int i = 0; i < stack.length; i++) { stack[i].incReference(); } } } // Return a bitmap indicating which values on the stack are pointers public boolean[] getStackBitmap() { return getBitmap(stack); } public int getStackSize() { ConstantObject table[] = stack; int extra = 0; for (int i = 0; i < table.length; i++) { if (table[i] instanceof SingleValueConstant) { int value = ((SingleValueConstant)table[i]).value; if (value == ITEM_Long || value == ITEM_Double) { extra++; } } } return table.length + extra; } // Return a bitmap indicating which values on the locals are pointers public boolean[] getLocalsBitmap() { return getBitmap(locals); } private boolean[] getBitmap(ConstantObject table[]) { int extra = 0; // Count the actual number of values, since doubles and longs take up // two slots for (int i = 0; i < table.length; i++) { if (table[i] instanceof SingleValueConstant) { int value = ((SingleValueConstant)table[i]).value; if (value == ITEM_Long || value == ITEM_Double) { extra++; } } } boolean result[] = new boolean[table.length + extra]; extra = 0; // Fill in the table for (int i = 0; i < table.length; i++) { if (table[i] instanceof SingleValueConstant) { int value = ((SingleValueConstant)table[i]).value; if (value == ITEM_Long || value == ITEM_Double) { extra++; } else if (value < 0 || value == ITEM_InitObject) { result[i + extra] = true; } } else if (table[i] instanceof ClassConstant) { result[i + extra] = true; } else { throw new RuntimeException("Unknown table type"); } } return result; } public int getOffset() { return offset; } }