001: // Copyright (c) 1997 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: public class Variable extends Location// implements java.util.Enumeration
009: {
010: /* Variables in a Scope are linked together in a linked list. */
011: Variable next;
012:
013: public final Variable nextVar() {
014: return next;
015: }
016:
017: public final boolean hasMoreElements() {
018: return next != null;
019: }
020:
021: public Object nextElement() {
022: if (next == null)
023: throw new java.util.NoSuchElementException(
024: "Variable enumeration");
025: return next;
026: }
027:
028: public Variable() {
029: }
030:
031: public Variable(String name) {
032: setName(name);
033: }
034:
035: public Variable(String name, Type type) {
036: setName(name);
037: setType(type);
038: }
039:
040: private int flags = SIMPLE_FLAG;
041: /* The SIMPLE_FLAG records the isSimple (q.v.) state. */
042: private static final int SIMPLE_FLAG = 0x1;
043: /* The PARAMETER_FLAG bit is true for parameters. */
044: private static final int PARAMETER_FLAG = 0x2;
045: /* The ARTIFICIAL_FLAG bits marks internals variables.
046: PARAMETER_FLAG|ARTIFICIAL_FLAG means an incoming parameter. */
047: private static final int ARTIFICIAL_FLAG = 0x4;
048:
049: static final int UNASSIGNED = -1;
050: /** The local variable slot number used by this variable.
051: * Not used (by the codegen layer) if !isSimple(). */
052: int offset = UNASSIGNED;
053:
054: /** Returns true iff assigned to a local variable slot.
055: * Only relevant if isSimple (). */
056: public final boolean isAssigned() {
057: return offset != UNASSIGNED;
058: }
059:
060: int start_pc;
061: int end_pc;
062:
063: final boolean dead() {
064: return end_pc > 0;
065: }
066:
067: private void setFlag(boolean setting, int flag) {
068: if (setting)
069: flags |= flag;
070: else
071: flags &= ~flag;
072: }
073:
074: /** Returns true for a "simple" variable.
075: * A "simple" Variable can be stack-allocated using standard local
076: * variable slots. It is allocated by the codegen package.
077: * A non-simple variable may need heap allocation, or more more
078: * complex access; it is basically ignored by the codegen package,
079: * and must be managed by higher layers. */
080: public final boolean isSimple() {
081: return (flags & SIMPLE_FLAG) != 0;
082: }
083:
084: public final void setSimple(boolean simple) {
085: setFlag(simple, SIMPLE_FLAG);
086: }
087:
088: public final boolean isParameter() {
089: return (flags & PARAMETER_FLAG) != 0;
090: }
091:
092: public final void setParameter(boolean parameter) {
093: setFlag(parameter, PARAMETER_FLAG);
094: }
095:
096: public final boolean isArtificial() {
097: return (flags & ARTIFICIAL_FLAG) != 0;
098: }
099:
100: public final void setArtificial(boolean artificial) {
101: setFlag(artificial, ARTIFICIAL_FLAG);
102: }
103:
104: /** Assign a local variable to a given local variable slot.
105: * @param local the index of the local variables.
106: * @return true iff we succeeded (i.e. the slot was unused) */
107: public boolean reserveLocal(int varIndex, CodeAttr code) {
108: int size = getType().size > 4 ? 2 : 1;
109: if (code.locals.used == null)
110: code.locals.used = new Variable[20 + size];
111: else if (code.getMaxLocals() + size >= code.locals.used.length) {
112: Variable[] new_locals = new Variable[2
113: * code.locals.used.length + size];
114: System.arraycopy(code.locals.used, 0, new_locals, 0, code
115: .getMaxLocals());
116: code.locals.used = new_locals;
117: }
118: for (int j = 0; j < size; j++) {
119: if (code.locals.used[varIndex + j] != null)
120: return false;
121: }
122: for (int j = 0; j < size; j++)
123: code.locals.used[varIndex + j] = this ;
124: if (varIndex + size > code.getMaxLocals())
125: code.setMaxLocals(varIndex + size);
126: offset = varIndex;
127: return true;
128: }
129:
130: /**
131: * Allocate slots for a local variable (or parameter).
132: * @return the index of the (first) slot.
133: */
134: public void allocateLocal(CodeAttr code) {
135: if (offset != UNASSIGNED)
136: return;
137: for (int i = 0;; i++) {
138: if (reserveLocal(i, code)) {
139: return;
140: }
141: }
142: }
143:
144: public void freeLocal(CodeAttr code) {
145: end_pc = code.previousPC;
146: int size = getType().size > 4 ? 2 : 1;
147: while (--size >= 0)
148: code.locals.used[offset + size] = null;
149: }
150:
151: public String toString() {
152: return "Variable[" + getName() + " offset:" + offset + ']';
153: }
154: }
|