001: /*
002: * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.tree;
027:
028: import sun.tools.java.*;
029: import sun.tools.tree.*;
030: import java.util.Vector;
031:
032: /**
033: * A local Field
034: *
035: * WARNING: The contents of this source file are not part of any
036: * supported API. Code that depends on them does so at its own risk:
037: * they are subject to change or removal without notice.
038: */
039:
040: public class LocalMember extends MemberDefinition {
041: /**
042: * The number of the variable
043: */
044: int number = -1;
045:
046: /**
047: * Some statistics
048: */
049: int readcount;
050: int writecount;
051:
052: /**
053: * An indication of which block the variable comes from.
054: * Helps identify uplevel references.
055: */
056: int scopeNumber;
057:
058: /**
059: * Return current nesting level, i.e., the value of 'scopeNumber'.
060: * Made public for the benefit of 'ClassDefinition.resolveName'.
061: */
062: public int getScopeNumber() {
063: return scopeNumber;
064: }
065:
066: /**
067: * Used by copyInline to record the original of this copy.
068: */
069: LocalMember originalOfCopy;
070:
071: /**
072: * The previous local variable, this list is used to build a nested
073: * context of local variables.
074: */
075: LocalMember prev;
076:
077: /**
078: * Constructor
079: */
080: public LocalMember(long where, ClassDefinition clazz,
081: int modifiers, Type type, Identifier name) {
082: super (where, clazz, modifiers, type, name, null, null);
083: }
084:
085: /**
086: * Constructor for a block-inner class.
087: */
088: public LocalMember(ClassDefinition innerClass) {
089: super (innerClass);
090:
091: // The class's "real" name is something like "foo$1$bar", but locally:
092: name = innerClass.getLocalName();
093: }
094:
095: /**
096: * Constructor for a proxy to an instance or class variable.
097: */
098: LocalMember(MemberDefinition field) {
099: this (0, null, 0, field.getType(), idClass);
100: // use this random slot to store the info:
101: accessPeer = field;
102: }
103:
104: /**
105: * Is this a proxy for the given field?
106: */
107: final MemberDefinition getMember() {
108: return (name == idClass) ? accessPeer : null;
109: }
110:
111: /**
112: * Special checks
113: */
114: public boolean isLocal() {
115: return true;
116: }
117:
118: /**
119: * Make a copy of this field, which is an argument to a method
120: * or constructor. Arrange so that when occurrences of the field
121: * are encountered in an immediately following copyInline() operation,
122: * the expression nodes will replace the original argument by the
123: * fresh copy.
124: */
125: public LocalMember copyInline(Context ctx) {
126: LocalMember copy = new LocalMember(where, clazz, modifiers,
127: type, name);
128: copy.readcount = this .readcount;
129: copy.writecount = this .writecount;
130:
131: copy.originalOfCopy = this ;
132:
133: // Make a temporary link from the original.
134: // It only stays valid through the next call to copyInline().
135: // (This means that recursive inlining won't work.)
136: // To stay honest, we mark these inline copies:
137: copy.addModifiers(M_LOCAL);
138: if (this .accessPeer != null
139: && (this .accessPeer.getModifiers() & M_LOCAL) == 0) {
140: throw new CompilerError("local copyInline");
141: }
142: this .accessPeer = copy;
143:
144: return copy;
145: }
146:
147: /**
148: * Returns the previous result of copyInline(ctx).
149: * Must be called in the course of an Expression.copyInline()
150: * operation that immediately follows the LocalMember.copyInline().
151: * Return "this" if there is no such copy.
152: */
153: public LocalMember getCurrentInlineCopy(Context ctx) {
154: MemberDefinition accessPeer = this .accessPeer;
155: if (accessPeer != null
156: && (accessPeer.getModifiers() & M_LOCAL) != 0) {
157: LocalMember copy = (LocalMember) accessPeer;
158: return copy;
159: }
160: return this ;
161: }
162:
163: /**
164: * May inline copies of all the arguments of the given method.
165: */
166: static public LocalMember[] copyArguments(Context ctx,
167: MemberDefinition field) {
168: Vector v = field.getArguments();
169: LocalMember res[] = new LocalMember[v.size()];
170: v.copyInto(res);
171: for (int i = 0; i < res.length; i++) {
172: res[i] = res[i].copyInline(ctx);
173: }
174: return res;
175: }
176:
177: /**
178: * Call this when finished with the result of a copyArguments() call.
179: */
180: static public void doneWithArguments(Context ctx, LocalMember res[]) {
181: for (int i = 0; i < res.length; i++) {
182: if (res[i].originalOfCopy.accessPeer == res[i]) {
183: res[i].originalOfCopy.accessPeer = null;
184: }
185: }
186: }
187:
188: /**
189: * Is this local variable's value stable and simple enough to be directly
190: * substituted for occurrences of the variable itself?
191: * (This decision is made by VarDeclarationStatement.inline().)
192: */
193: public boolean isInlineable(Environment env, boolean fromFinal) {
194: return (getModifiers() & M_INLINEABLE) != 0;
195: }
196:
197: /**
198: * Check if used
199: */
200: public boolean isUsed() {
201: return (readcount != 0) || (writecount != 0);
202: }
203:
204: // Used by class Context, only on members of MemberDefinition.available:
205: LocalMember getAccessVar() {
206: return (LocalMember) accessPeer;
207: }
208:
209: void setAccessVar(LocalMember f) {
210: accessPeer = f;
211: }
212:
213: // Used by class Context, only on "AccessVar" constructor args
214: MemberDefinition getAccessVarMember() {
215: return accessPeer;
216: }
217:
218: void setAccessVarMember(MemberDefinition f) {
219: accessPeer = f;
220: }
221:
222: /**
223: * Return value
224: */
225: public Node getValue(Environment env) {
226: return (Expression) getValue();
227: }
228:
229: /**
230: * Value number for vsets, or -1 if none.
231: */
232: public int getNumber(Context ctx) {
233: return number;
234: }
235: }
|