/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* 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
int varNumber;
int scopeNumber;
int frameNumber;
/**
* Create the initial context for a method
* The incoming context is inherited from
*/
this.frameNumber = 1;
this.scopeNumber = 2;
this.varNumber = 0;
} else {
// Variables and initializers are inlined into a constructor.
// Model this by inheriting the frame number of the parent,
// which will contain a "this" parameter.
} else {
}
}
}
/**
* Create a new context, for initializing a class.
*/
}
/**
* Create a new nested context, for a block statement
*/
this.frameNumber = 1;
this.scopeNumber = 2;
this.varNumber = 0;
} else {
// Inherit local classes from surrounding block,
// just as for local variables. Fixes 4074421.
}
}
}
/**
* Declare local
*/
//System.out.println( "DECLARE= " + local.getName() + "=" + varNumber + ", read=" + local.readcount + ", write=" + local.writecount + ", hash=" + local.hashCode());
}
if (local.isInnerClass()) {
return 0;
}
// Originally the statement:
//
// local.subModifiers(M_INLINEABLE);
//
// was here with the comment:
//
// // prevent inlining across call sites
//
// This statement prevented constant local variables from
// inlining. It didn't seem to do anything useful.
//
// The statement has been removed and an assertion has been
// added which mandates that the only members which are marked
// with M_INLINEABLE are the ones for which isConstant() is true.
// (Fix for 4106244.)
//
// Addition to the above comment: they might also be
// final variables initialized with 'this', 'super', or other
// final identifiers. See VarDeclarationStatement.inline().
// So I've removed the assertion. The original subModifiers
// call appears to have been there to fix nested class translation
// breakage, which has been fixed in VarDeclarationStatement
// now instead. (Fix for 4073244.)
}
/**
* Get a local variable by name
*/
public
return f;
}
}
return null;
}
/**
* Get the scope number for a reference to a member of this class
* (Larger scope numbers are more deeply nested.)
* @see LocalMember#scopeNumber
*/
public
return ctx.frameNumber;
}
}
return -1;
}
private
// Note: This is structured as a pair of parallel lookups.
// If we were to redesign Context, we might prefer to walk
// along a single chain of scopes.
// Also look for a class member in a shallower scope.
for (ClassDefinition c = thisClass;
c != null;
c = c.getOuterClass()) {
if (apparentOnly && f.getClassDefinition() != c) {
continue;
}
return f;
}
}
return lf;
}
/**
* Assign a number to a class field.
* (This is used to track definite assignment of some blank finals.)
*/
}
/**
* Retrieve a number previously assigned by declareMember().
* Return -1 if there was no such assignment in this context.
*/
return f.number;
}
}
return -1;
}
/**
* Return the local field or member field corresponding to a number.
* Return null if there is no such field.
*/
}
}
return null;
}
/**
* Get a local class by name
*/
public
return f;
}
}
return null;
}
private
boolean apparentOnly) throws ClassNotFound {
// Also look for a class member in a shallower scope.
c != null;
c = c.getOuterClass()) {
// QUERY: We may need to get the inner class from a
// superclass of 'c'. This call is prepared to
// resolve the superclass if necessary. Can we arrange
// to assure that it is always previously resolved?
// This is one of a small number of problematic calls that
// requires 'getSuperClass' to resolve superclasses on demand.
// See 'ClassDefinition.getInnerClass(env, nm)'.
if (apparentOnly && f.getClassDefinition() != c) {
continue;
}
return f;
}
}
return lf;
}
/**
* Get either a local variable, or a field in a current class
*/
public final
}
/**
* Like getField, except that it skips over inherited fields.
* Used for error checking.
*/
public final
MemberDefinition getApparentField(Environment env, Identifier name) throws AmbiguousMember, ClassNotFound {
}
/**
* Check if the given field is active in this context.
*/
if (field == f) {
return true;
}
}
return false;
}
/**
* Notice a reference (usually an uplevel one).
* Update the references list of every enclosing class
* which is enclosed by the scope of the target.
* Update decisions about which uplevels to make into fields.
* Return the uplevel reference descriptor, or null if it's local.
* <p>
* The target must be in scope in this context.
* So, call this method only from the check phase.
* (In other phases, the context may be less complete.)
* <p>
* This can and should be called both before and after classes are frozen.
* It should be a no-op, and will raise a compiler error if not.
*/
// Walk outward visiting each scope.
// Note each distinct frame (i.e., enclosing method).
// For each frame in which the variable is uplevel,
// record the event in the references list of the enclosing class.
int currentFrameNumber = -1;
continue; // we're processing frames, not contexts
}
if (targetScopeNumber >= currentFrameNumber) {
break; // the target is native to this frame
}
// process a frame which is using this variable as an uplevel
// remember the reference pertaining to the innermost frame
res = r;
}
}
return res;
}
/**
* Implement a reference (usually an uplevel one).
* Call noteReference() first, to make sure the reference
* lists are up to date.
* <p>
* The resulting expression tree does not need checking;
* it can be code-generated right away.
* If the reference is not uplevel, the result is an IDENT or THIS.
*/
// Now create a referencing expression.
if (r != null) {
return r.makeLocalReference(env, this);
} else {
}
}
/**
* Return a local expression which can serve as the base reference
* for the given field. If the field is a constructor, return an
* expression for the implicit enclosing instance argument.
* <p>
* Return null if there is no need for such an argument,
* or if there was an error.
*/
MemberDefinition f) {
// reqc is the base pointer type required to use f
: !f.isConstructor() ? fc
: fc.getOuterClass();
return null;
}
}
try {
} catch (ClassNotFound ee) {
return false;
}
}
boolean needExactMatch) {
if (f == null) {
// say something like: undefined variable A.this
} else if (f.isConstructor()) {
} else if (f.isMethod()) {
f, f.getClassDeclaration());
} else {
f.getClassDeclaration());
}
// This is an attempt at error recovery.
// Unfortunately, the constructor may throw
// a null pointer exception after failing to resolve
// 'idThis'. Since an error message has already been
// issued previously, this exception is caught and
// silently ignored. Ideally, we should avoid throwing
// the exception.
return e;
}
// use lp to scan for current instances (locals named "this")
// thise is a link expression being built up
// root is the local variable (idThis) at the far left of thise
// thisc is the class of the link expression thise
// conCls is the class of the "this", in a constructor
if (field.isConstructor()) {
}
}
while (true) {
// start fresh from lp
}
break;
}
}
// Require exact class identity when called with
// 'needExactMatch' true. This is done when checking
// the '<class>.this' syntax. Fixes 4102393 and 4133457.
break;
}
// move out one step, if the current instance has an outer link
if (outerMember == null) {
continue; // try to find more help in lp
}
// Must pick up "this$C" from the constructor argument,
// not from "this.this$C", since the latter may not be
// initialized properly. (This way is cheaper too.)
} else {
}
}
// mark crossed scopes
// ?????
//ensureAvailable(root);
return thise;
}
if (f == null) {
// say something like: undefined variable A.this
} else if (f.isConstructor()) {
} else {
}
// avoid floodgating:
return e;
}
/**
* Is there a "this" of type reqc in scope?
*/
if (thisc.isTopLevel()) {
return false;
}
}
return true;
}
/**
* From which enclosing class do members of this type come?
*/
}
return thisc;
}
/**
* Resolve a type name from within a local scope.
* @see Environment#resolveName
*/
// This logic is pretty much exactly parallel to that of
// Environment.resolveName().
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. Environment.resolveName.)
if (rhead.hasAmbigPrefix()) {
// The first identifier component refers to an
// ambiguous class. Limp on. We throw away the
// rest of the classname as it is irrelevant.
// (part of solution for 4059855).
return rhead;
}
}
try {
} catch (ClassNotFound ee) {
// return partially-resolved name someone else can fail on
}
}
// Look for an unqualified name in enclosing scopes.
try {
if (f != null) {
return f.getInnerClass().getName();
}
} catch (ClassNotFound ee) {
// a missing superclass, or something catastrophic
}
// look in imports, etc.
}
/**
* Return the name of a lexically apparent type,
* skipping inherited members, and ignoring
* the current pacakge and imports.
* This is used for error checking.
*/
public
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. Environment.resolveName.)
}
// Look for an unqualified name in enclosing scopes.
try {
if (f != null) {
return f.getInnerClass().getName();
}
} catch (ClassNotFound ee) {
// a missing superclass, or something catastrophic
}
// the enclosing class name is the only apparent package member:
return topnm;
}
return idNull;
}
/**
* Raise an error if a blank final was definitely unassigned
* on entry to a loop, but has possibly been assigned on the
* back-branch. If this is the case, the loop may be assigning
* it multiple times.
*/
if (f.isBlankFinal()
f.getName());
}
}
}
/**
* Check if a field can reach another field (only considers
* forward references, not the access modifiers).
*/
}
/**
* Get the context that corresponds to a label, return null if
* not found.
*/
public
return ctx;
}
}
return null;
}
/**
* Get the destination context of a break
*/
public
return getLabelContext(lbl);
}
case SWITCH:
case FOR:
case DO:
case WHILE:
return ctx;
}
}
}
return null;
}
/**
* Get the destination context of a continue
*/
public
return getLabelContext(lbl);
}
case FOR:
case DO:
case WHILE:
return ctx;
}
}
}
return null;
}
/**
* Get the destination context of a return (the method body)
*/
public
// The METHOD node is set up by Statement.checkMethod().
return (CheckContext)ctx;
}
}
return null;
}
/**
* Get the context of the innermost surrounding try-block.
* Consider only try-blocks contained within the same method.
* (There could be others when searching from within a method
* of a local class, but they are irrelevant to our purpose.)
* all abnormal transfers of control: break, continue, return,
* and throw.
*/
public
return (CheckContext)ctx;
}
}
return null;
}
/**
* Get the nearest inlined context
*/
case INLINEMETHOD:
case INLINENEWINSTANCE:
return ctx;
}
}
}
return null;
}
/**
* Get the context of a field that is being inlined
*/
case INLINEMETHOD:
return ctx;
}
break;
case INLINENEWINSTANCE:
return ctx;
}
}
}
}
return null;
}
/**
* Remove variables from the vset set that are no longer part of
* this context.
*/
}
public final int getVarNumber() {
return varNumber;
}
/**
* Return the number of the innermost current instance reference.
*/
public int getThisNumber() {
}
// this is a variable; there is no "this" (should not happen)
return varNumber;
}
/**
* Return the field containing the present context.
*/
return field;
}
/**
* Extend an environment with the given context.
* The resulting environment behaves the same as
* the given one, except that resolveName() takes
* into account local class names in this context.
*/
}
}
final
}
}
}