/* |
|
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. |
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
* |
|
* This code is free software; you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License version 2 only, as |
|
* published by the Free Software Foundation. Oracle designates this |
|
* particular file as subject to the "Classpath" exception as provided |
|
* by Oracle in the LICENSE file that accompanied this code. |
|
* |
|
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
* version 2 for more details (a copy is included in the LICENSE file that |
|
* accompanied this code). |
|
* |
|
* You should have received a copy of the GNU General Public License version |
|
* 2 along with this work; if not, write to the Free Software Foundation, |
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
* |
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
* or visit www.oracle.com if you need additional information or have any |
|
* questions. |
|
*/ |
|
package sun.tools.tree; |
|
import sun.tools.java.*; |
|
import sun.tools.tree.*; |
|
import java.util.Vector; |
|
/** |
|
* A local Field |
|
* |
|
* WARNING: The contents of this source file are not part of any |
|
* supported API. Code that depends on them does so at its own risk: |
|
* they are subject to change or removal without notice. |
|
*/ |
|
public |
|
class LocalMember extends MemberDefinition { |
|
/** |
|
* The number of the variable |
|
*/ |
|
int number = -1; |
|
/** |
|
* Some statistics |
|
*/ |
|
int readcount; |
|
int writecount; |
|
/** |
|
* An indication of which block the variable comes from. |
|
* Helps identify uplevel references. |
|
*/ |
|
int scopeNumber; |
|
/** |
|
* Return current nesting level, i.e., the value of 'scopeNumber'. |
|
* Made public for the benefit of 'ClassDefinition.resolveName'. |
|
*/ |
|
public int getScopeNumber() { |
|
return scopeNumber; |
|
} |
|
/** |
|
* Used by copyInline to record the original of this copy. |
|
*/ |
|
LocalMember originalOfCopy; |
|
/** |
|
* The previous local variable, this list is used to build a nested |
|
* context of local variables. |
|
*/ |
|
LocalMember prev; |
|
/** |
|
* Constructor |
|
*/ |
|
public LocalMember(long where, ClassDefinition clazz, int modifiers, Type type, |
|
Identifier name) { |
|
super(where, clazz, modifiers, type, name, null, null); |
|
} |
|
/** |
|
* Constructor for a block-inner class. |
|
*/ |
|
public LocalMember(ClassDefinition innerClass) { |
|
super(innerClass); |
|
// The class's "real" name is something like "foo$1$bar", but locally: |
|
name = innerClass.getLocalName(); |
|
} |
|
/** |
|
* Constructor for a proxy to an instance or class variable. |
|
*/ |
|
LocalMember(MemberDefinition field) { |
|
this(0, null, 0, field.getType(), idClass); |
|
// use this random slot to store the info: |
|
accessPeer = field; |
|
} |
|
/** |
|
* Is this a proxy for the given field? |
|
*/ |
|
final MemberDefinition getMember() { |
|
return (name == idClass) ? accessPeer : null; |
|
} |
|
/** |
|
* Special checks |
|
*/ |
|
public boolean isLocal() { |
|
return true; |
|
} |
|
/** |
|
* Make a copy of this field, which is an argument to a method |
|
* or constructor. Arrange so that when occurrences of the field |
|
* are encountered in an immediately following copyInline() operation, |
|
* the expression nodes will replace the original argument by the |
|
* fresh copy. |
|
*/ |
|
public LocalMember copyInline(Context ctx) { |
|
LocalMember copy = new LocalMember(where, clazz, modifiers, type, name); |
|
copy.readcount = this.readcount; |
|
copy.writecount = this.writecount; |
|
copy.originalOfCopy = this; |
|
// Make a temporary link from the original. |
|
// It only stays valid through the next call to copyInline(). |
|
// (This means that recursive inlining won't work.) |
|
// To stay honest, we mark these inline copies: |
|
copy.addModifiers(M_LOCAL); |
|
if (this.accessPeer != null |
|
&& (this.accessPeer.getModifiers() & M_LOCAL) == 0) { |
|
throw new CompilerError("local copyInline"); |
|
} |
|
this.accessPeer = copy; |
|
return copy; |
|
} |
|
/** |
|
* Returns the previous result of copyInline(ctx). |
|
* Must be called in the course of an Expression.copyInline() |
|
* operation that immediately follows the LocalMember.copyInline(). |
|
* Return "this" if there is no such copy. |
|
*/ |
|
public LocalMember getCurrentInlineCopy(Context ctx) { |
|
MemberDefinition accessPeer = this.accessPeer; |
|
if (accessPeer != null && (accessPeer.getModifiers() & M_LOCAL) != 0) { |
|
LocalMember copy = (LocalMember)accessPeer; |
|
return copy; |
|
} |
|
return this; |
|
} |
|
/** |
|
* May inline copies of all the arguments of the given method. |
|
*/ |
|
static public LocalMember[] copyArguments(Context ctx, MemberDefinition field) { |
|
Vector v = field.getArguments(); |
|
LocalMember res[] = new LocalMember[v.size()]; |
|
v.copyInto(res); |
|
for (int i = 0; i < res.length; i++) { |
|
res[i] = res[i].copyInline(ctx); |
|
} |
|
return res; |
|
} |
|
/** |
|
* Call this when finished with the result of a copyArguments() call. |
|
*/ |
|
static public void doneWithArguments(Context ctx, LocalMember res[]) { |
|
for (int i = 0; i < res.length; i++) { |
|
if (res[i].originalOfCopy.accessPeer == res[i]) { |
|
res[i].originalOfCopy.accessPeer = null; |
|
} |
|
} |
|
} |
|
/** |
|
* Is this local variable's value stable and simple enough to be directly |
|
* substituted for occurrences of the variable itself? |
|
* (This decision is made by VarDeclarationStatement.inline().) |
|
*/ |
|
public boolean isInlineable(Environment env, boolean fromFinal) { |
|
return (getModifiers() & M_INLINEABLE) != 0; |
|
} |
|
/** |
|
* Check if used |
|
*/ |
|
public boolean isUsed() { |
|
return (readcount != 0) || (writecount != 0); |
|
} |
|
// Used by class Context, only on members of MemberDefinition.available: |
|
LocalMember getAccessVar() { |
|
return (LocalMember)accessPeer; |
|
} |
|
void setAccessVar(LocalMember f) { |
|
accessPeer = f; |
|
} |
|
// Used by class Context, only on "AccessVar" constructor args |
|
MemberDefinition getAccessVarMember() { |
|
return accessPeer; |
|
} |
|
void setAccessVarMember(MemberDefinition f) { |
|
accessPeer = f; |
|
} |
|
/** |
|
* Return value |
|
*/ |
|
public Node getValue(Environment env) { |
|
return (Expression)getValue(); |
|
} |
|
/** |
|
* Value number for vsets, or -1 if none. |
|
*/ |
|
public int getNumber(Context ctx) { |
|
return number; |
|
} |
|
} |