1/* 2 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.tools.tree; 27 28import sun.tools.java.*; 29import sun.tools.tree.*; 30import java.util.Vector; 31 32/** 33 * A local Field 34 * 35 * WARNING: The contents of this source file are not part of any 36 * supported API. Code that depends on them does so at its own risk: 37 * they are subject to change or removal without notice. 38 */ 39 40public 41class LocalMember extends MemberDefinition { 42 /** 43 * The number of the variable 44 */ 45 int number = -1; 46 47 /** 48 * Some statistics 49 */ 50 int readcount; 51 int writecount; 52 53 /** 54 * An indication of which block the variable comes from. 55 * Helps identify uplevel references. 56 */ 57 int scopeNumber; 58 59 /** 60 * Return current nesting level, i.e., the value of 'scopeNumber'. 61 * Made public for the benefit of 'ClassDefinition.resolveName'. 62 */ 63 public int getScopeNumber() { 64 return scopeNumber; 65 } 66 67 /** 68 * Used by copyInline to record the original of this copy. 69 */ 70 LocalMember originalOfCopy; 71 72 /** 73 * The previous local variable, this list is used to build a nested 74 * context of local variables. 75 */ 76 LocalMember prev; 77 78 /** 79 * Constructor 80 */ 81 public LocalMember(long where, ClassDefinition clazz, int modifiers, Type type, 82 Identifier name) { 83 super(where, clazz, modifiers, type, name, null, null); 84 } 85 86 /** 87 * Constructor for a block-inner class. 88 */ 89 public LocalMember(ClassDefinition innerClass) { 90 super(innerClass); 91 92 // The class's "real" name is something like "foo$1$bar", but locally: 93 name = innerClass.getLocalName(); 94 } 95 96 /** 97 * Constructor for a proxy to an instance or class variable. 98 */ 99 LocalMember(MemberDefinition field) { 100 this(0, null, 0, field.getType(), idClass); 101 // use this random slot to store the info: 102 accessPeer = field; 103 } 104 105 /** 106 * Is this a proxy for the given field? 107 */ 108 final MemberDefinition getMember() { 109 return (name == idClass) ? accessPeer : null; 110 } 111 112 /** 113 * Special checks 114 */ 115 public boolean isLocal() { 116 return true; 117 } 118 119 /** 120 * Make a copy of this field, which is an argument to a method 121 * or constructor. Arrange so that when occurrences of the field 122 * are encountered in an immediately following copyInline() operation, 123 * the expression nodes will replace the original argument by the 124 * fresh copy. 125 */ 126 public LocalMember copyInline(Context ctx) { 127 LocalMember copy = new LocalMember(where, clazz, modifiers, 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 && (accessPeer.getModifiers() & M_LOCAL) != 0) { 156 LocalMember copy = (LocalMember)accessPeer; 157 return copy; 158 } 159 return this; 160 } 161 162 /** 163 * May inline copies of all the arguments of the given method. 164 */ 165 static public LocalMember[] copyArguments(Context ctx, MemberDefinition field) { 166 Vector<MemberDefinition> v = field.getArguments(); 167 LocalMember res[] = new LocalMember[v.size()]; 168 v.copyInto(res); 169 for (int i = 0; i < res.length; i++) { 170 res[i] = res[i].copyInline(ctx); 171 } 172 return res; 173 } 174 175 /** 176 * Call this when finished with the result of a copyArguments() call. 177 */ 178 static public void doneWithArguments(Context ctx, LocalMember res[]) { 179 for (int i = 0; i < res.length; i++) { 180 if (res[i].originalOfCopy.accessPeer == res[i]) { 181 res[i].originalOfCopy.accessPeer = null; 182 } 183 } 184 } 185 186 /** 187 * Is this local variable's value stable and simple enough to be directly 188 * substituted for occurrences of the variable itself? 189 * (This decision is made by VarDeclarationStatement.inline().) 190 */ 191 public boolean isInlineable(Environment env, boolean fromFinal) { 192 return (getModifiers() & M_INLINEABLE) != 0; 193 } 194 195 /** 196 * Check if used 197 */ 198 public boolean isUsed() { 199 return (readcount != 0) || (writecount != 0); 200 } 201 202 // Used by class Context, only on members of MemberDefinition.available: 203 LocalMember getAccessVar() { 204 return (LocalMember)accessPeer; 205 } 206 void setAccessVar(LocalMember f) { 207 accessPeer = f; 208 } 209 // Used by class Context, only on "AccessVar" constructor args 210 MemberDefinition getAccessVarMember() { 211 return accessPeer; 212 } 213 void setAccessVarMember(MemberDefinition f) { 214 accessPeer = f; 215 } 216 217 218 /** 219 * Return value 220 */ 221 public Node getValue(Environment env) { 222 return (Expression)getValue(); 223 } 224 225 /** 226 * Value number for vsets, or -1 if none. 227 */ 228 public int getNumber(Context ctx) { 229 return number; 230 } 231} 232