001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package components;
028:
029: import java.io.DataOutput;
030: import java.io.DataInput;
031: import java.io.IOException;
032: import util.DataFormatException;
033: import jcc.Const;
034:
035: public class StackMapFrame {
036: // A single frame in the stack map table
037:
038: public static final int ITEM_Bogus = 0;
039: public static final int ITEM_Integer = 1;
040: public static final int ITEM_Float = 2;
041: public static final int ITEM_Double = 3;
042: public static final int ITEM_Long = 4;
043: public static final int ITEM_Null = 5;
044: public static final int ITEM_InitObject = 6;
045: public static final int ITEM_Object = 7;
046: public static final int ITEM_NewObject = 8;
047:
048: int offset;
049: ConstantObject locals[];
050: ConstantObject stack[];
051:
052: // Read in a frame from the specified data input stream.
053: StackMapFrame(DataInput in, ConstantObject globals[])
054: throws IOException {
055: this .offset = in.readShort();
056: this .locals = readOneTable(in, globals);
057: this .stack = readOneTable(in, globals);
058: }
059:
060: private ConstantObject[] readOneTable(DataInput in,
061: ConstantObject globals[]) throws IOException {
062: int length = in.readShort();
063: ConstantObject result[] = new ConstantObject[length];
064: for (int i = 0; i < length; i++) {
065: int tag = in.readByte();
066: switch (tag) {
067: case ITEM_Bogus:
068: case ITEM_Integer:
069: case ITEM_Float:
070: case ITEM_Double:
071: case ITEM_Long:
072: case ITEM_Null:
073: case ITEM_InitObject:
074: // Small non-negative values represent the corresponding
075: // type.
076: result[i] = new SingleValueConstant(tag);
077: break;
078:
079: case ITEM_Object:
080: result[i] = globals[in.readShort()];
081: break;
082:
083: case ITEM_NewObject:
084: // It's not really worth creating a new
085: // type to represent this. Negative numbers represent new
086: // objects.
087: result[i] = new SingleValueConstant(~in.readShort());
088: break;
089:
090: default:
091: System.out.println("Unknown tag");
092: }
093: }
094: return result;
095: }
096:
097: public int writeData(DataOutput out) throws IOException {
098: out.writeShort(offset);
099: // Return the number of bytes that we've written
100: return 2 + writeData(out, locals) + writeData(out, stack);
101: }
102:
103: public int writeData(DataOutput out, ConstantObject[] table)
104: throws IOException {
105: int count = 0;
106: out.writeShort(table.length);
107: count += 2;
108: for (int i = 0; i < table.length; i++) {
109: if (table[i] instanceof SingleValueConstant) {
110: int value = ((SingleValueConstant) table[i]).value;
111: if (value < 0) {
112: out.writeByte(ITEM_NewObject);
113: out.writeShort(~value);
114: count += 3;
115: } else {
116: out.writeShort(value);
117: count += 2;
118: }
119: } else if (table[i] instanceof ClassConstant) {
120: out.writeByte(ITEM_Object);
121: out.writeShort(((ClassConstant) table[i]).name.index);
122: count += 3;
123: }
124: }
125: return count;
126: }
127:
128: public void externalize(ConstantPool p) {
129: // do nothing
130: }
131:
132: public void countConstantReferences(boolean isRelocatable) {
133: if (isRelocatable) {
134: // Is this the right thing??
135: for (int i = 0; i < locals.length; i++) {
136: locals[i].incReference();
137: }
138: for (int i = 0; i < stack.length; i++) {
139: stack[i].incReference();
140: }
141: }
142: }
143:
144: // Return a bitmap indicating which values on the stack are pointers
145: public boolean[] getStackBitmap() {
146: return getBitmap(stack);
147: }
148:
149: public int getStackSize() {
150: ConstantObject table[] = stack;
151: int extra = 0;
152: for (int i = 0; i < table.length; i++) {
153: if (table[i] instanceof SingleValueConstant) {
154: int value = ((SingleValueConstant) table[i]).value;
155: if (value == ITEM_Long || value == ITEM_Double) {
156: extra++;
157: }
158: }
159: }
160: return table.length + extra;
161: }
162:
163: // Return a bitmap indicating which values on the locals are pointers
164: public boolean[] getLocalsBitmap() {
165: return getBitmap(locals);
166: }
167:
168: private boolean[] getBitmap(ConstantObject table[]) {
169: int extra = 0;
170: // Count the actual number of values, since doubles and longs take up
171: // two slots
172: for (int i = 0; i < table.length; i++) {
173: if (table[i] instanceof SingleValueConstant) {
174: int value = ((SingleValueConstant) table[i]).value;
175: if (value == ITEM_Long || value == ITEM_Double) {
176: extra++;
177: }
178: }
179: }
180: boolean result[] = new boolean[table.length + extra];
181: extra = 0;
182: // Fill in the table
183: for (int i = 0; i < table.length; i++) {
184: if (table[i] instanceof SingleValueConstant) {
185: int value = ((SingleValueConstant) table[i]).value;
186: if (value == ITEM_Long || value == ITEM_Double) {
187: extra++;
188: } else if (value < 0 || value == ITEM_InitObject) {
189: result[i + extra] = true;
190: }
191: } else if (table[i] instanceof ClassConstant) {
192: result[i + extra] = true;
193: } else {
194: throw new RuntimeException("Unknown table type");
195: }
196: }
197: return result;
198: }
199:
200: public int getOffset() {
201: return offset;
202: }
203: }
|