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