001: // Copyright (c) 1997, 2004 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.bytecode;
005:
006: import java.io.*;
007:
008: /* Represents the contents of a standard "LocalVariableTable" attribute.
009: * @author Per Bothner
010: */
011:
012: public class LocalVarsAttr extends Attribute {
013: private Method method;
014:
015: /* Map local slot index to the local variable that is there. */
016: Variable[] used;
017: public Scope current_scope;
018: Scope parameter_scope;
019:
020: /** Add a new LocalVarsAttr to a CodeAttr. */
021: public LocalVarsAttr(CodeAttr code) {
022: super ("LocalVariableTable");
023: addToFrontOf(code);
024: method = (Method) code.getContainer();
025: code.locals = this ;
026: }
027:
028: /** Create, but don't link into method.code's attributes list (yet). */
029: public LocalVarsAttr(Method method) {
030: super ("LocalVariableTable");
031: CodeAttr code = method.code;
032: this .method = method;
033: code.locals = this ;
034: }
035:
036: public final Method getMethod() {
037: return method;
038: }
039:
040: public VarEnumerator allVars() {
041: return new VarEnumerator(parameter_scope);
042: }
043:
044: public void enterScope(Scope scope) {
045: scope.linkChild(current_scope);
046: current_scope = scope;
047: CodeAttr code = method.getCode();
048: for (Variable var = scope.firstVar(); var != null; var = var
049: .nextVar()) {
050: if (var.isSimple()) {
051: if (!var.isAssigned())
052: var.allocateLocal(code);
053: else if (used[var.offset] == null)
054: used[var.offset] = var;
055: else if (used[var.offset] != var)
056: throw new Error(
057: "inconsistent local variable assignments for "
058: + var + " != " + used[var.offset]);
059: }
060: }
061: }
062:
063: /** Mark scopes upto specified scope as 'preserved'.
064: * This means that the local variable slots are not available for reuse
065: * when the scope exits. The effected scopes are all ancestor scopes from
066: * the current scope (inclusive) upto the specified scope (exclusive). */
067: public void preserveVariablesUpto(Scope scope) {
068: for (Scope cur = current_scope; cur != scope; cur = cur.parent)
069: cur.preserved = true;
070: }
071:
072: public final boolean isEmpty() {
073: VarEnumerator vars = allVars();
074: Variable var;
075: while ((var = vars.nextVar()) != null) {
076: if (var.isSimple() && var.name != null)
077: return false;
078: }
079: return true;
080: }
081:
082: public final int getCount() {
083: int local_variable_count = 0;
084: VarEnumerator vars = allVars();
085: Variable var;
086: while ((var = vars.nextVar()) != null) {
087: if (var.shouldEmit())
088: local_variable_count++;
089: }
090: return local_variable_count;
091: }
092:
093: public final int getLength() {
094: return 2 + 10 * getCount();
095: }
096:
097: public void assignConstants(ClassType cl) {
098: super .assignConstants(cl);
099:
100: VarEnumerator vars = allVars();
101: Variable var;
102: while ((var = vars.nextVar()) != null) {
103: if (var.isSimple() && var.name != null) {
104: if (var.name_index == 0)
105: var.name_index = cl.getConstants().addUtf8(
106: var.getName()).index;
107: if (var.signature_index == 0)
108: var.signature_index = cl.getConstants().addUtf8(
109: var.getType().signature).index;
110: }
111: }
112: }
113:
114: public void write(DataOutputStream dstr) throws java.io.IOException {
115: VarEnumerator vars = allVars();
116: Variable var;
117: dstr.writeShort(getCount());
118:
119: for (vars.reset(); (var = vars.nextVar()) != null;) {
120: if (var.shouldEmit()) {
121: Scope scope = var.scope;
122: int start_pc = scope.start.position;
123: int end_pc = scope.end.position;
124: dstr.writeShort(start_pc);
125: dstr.writeShort(end_pc - start_pc);
126: dstr.writeShort(var.name_index);
127: dstr.writeShort(var.signature_index);
128: dstr.writeShort(var.offset);
129: }
130: }
131: }
132:
133: public void print(ClassTypeWriter dst) {
134: VarEnumerator vars = allVars();
135: dst.print("Attribute \"");
136: dst.print(getName());
137: dst.print("\", length:");
138: dst.print(getLength());
139: dst.print(", count: ");
140: dst.println(getCount());
141:
142: Variable var;
143: for (vars.reset(); (var = vars.nextVar()) != null;) {
144: if (var.isSimple() && var.name != null) {
145: dst.print(" slot#");
146: dst.print(var.offset);
147: dst.print(": name: ");
148: dst.printOptionalIndex(var.name_index);
149: dst.print(var.getName());
150: dst.print(", type: ");
151: dst.printOptionalIndex(var.signature_index);
152: dst.printSignature(var.getType());
153: dst.print(" (pc: ");
154: Scope scope = var.scope;
155: int start_pc, end_pc;
156: if (scope == null || scope.start == null
157: || scope.end == null
158: || (start_pc = scope.start.position) < 0
159: || (end_pc = scope.end.position) < 0)
160: dst.print("unknown");
161: else {
162: dst.print(start_pc);
163: dst.print(" length: ");
164: dst.print(end_pc - start_pc);
165: }
166: dst.println(')');
167: }
168: }
169: }
170: }
|