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