FileDocCategorySizeDatePackage
StackMapFrame.javaAPI DocJ2ME CLDC 1.15523Wed Feb 05 15:56:02 GMT 2003components

StackMapFrame.java

/*
 *    StackMapFrame.java    1.4    01/03/30
 *
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. 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;
    }
}