< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java

Print this page

 757         refs.remove(ExprRef.direct(depth));
 758         boolean indirectRef = refs.remove(ExprRef.indirect(depth));
 759         scan(tree.index);
 760         refs.discardExprs(depth);
 761         if (indirectRef) {
 762             refs.add(ExprRef.direct(depth));
 763             refs.add(ExprRef.indirect(depth));
 764         }
 765     }
 766 
 767     @Override
 768     public void visitSelect(JCFieldAccess tree) {
 769 
 770         // Scan the selected thing
 771         scan(tree.selected);
 772         boolean selectedDirectRef = refs.remove(ExprRef.direct(depth));
 773         boolean selectedIndirectRef = refs.remove(ExprRef.indirect(depth));
 774 
 775         // Explicit 'this' reference?
 776         Type.ClassType currentClassType = (Type.ClassType)methodClass.sym.type;
 777         if (isExplicitThisReference(types, currentClassType, tree)) {
 778             refs.mapInto(refs, ThisRef.class, direct -> new ExprRef(depth, direct));
 779             return;
 780         }
 781 
 782         // Explicit outer 'this' reference?
 783         Type selectedType = types.erasure(tree.selected.type);
 784         if (selectedType.hasTag(CLASS)) {
 785             ClassSymbol currentClassSym = (ClassSymbol)currentClassType.tsym;
 786             ClassSymbol selectedTypeSym = (ClassSymbol)selectedType.tsym;
 787             if (tree.name == names._this &&
 788                     selectedTypeSym != currentClassSym &&
 789                     currentClassSym.isEnclosedBy(selectedTypeSym)) {
 790                 refs.mapInto(refs, OuterRef.class, direct -> new ExprRef(depth, direct));
 791                 return;
 792             }
 793         }
 794 
 795         // Methods - the "value" of a non-static method is a reference to its instance
 796         Symbol sym = tree.sym;
 797         if (sym.kind == MTH) {

1145         pendingWarning = callStack.toArray(new DiagnosticPosition[0]);
1146         callStack.pop();
1147     }
1148 
1149     // Copy pending warning, if any, to the warning list and reset
1150     private boolean copyPendingWarning() {
1151         if (pendingWarning == null)
1152             return false;
1153         warningList.add(pendingWarning);
1154         pendingWarning = null;
1155         return true;
1156     }
1157 
1158     // Does the symbol correspond to a parameter or local variable (not a field)?
1159     private boolean isParamOrVar(Symbol sym) {
1160         return sym != null &&
1161             sym.kind == VAR &&
1162             (sym.owner.kind == MTH || sym.owner.kind == VAR);
1163     }
1164 
1165     /** Check if the given tree is an explicit reference to the 'this' instance of the
1166      *  class currently being compiled. This is true if tree is:
1167      *  - An unqualified 'this' identifier
1168      *  - A 'super' identifier qualified by a class name whose type is 'currentClass' or a supertype
1169      *  - A 'this' identifier qualified by a class name whose type is 'currentClass' or a supertype
1170      *    but also NOT an enclosing outer class of 'currentClass'.
1171      */
1172     private boolean isExplicitThisReference(Types types, Type.ClassType currentClass, JCTree tree) {
1173         switch (tree.getTag()) {
1174             case PARENS:
1175                 return isExplicitThisReference(types, currentClass, TreeInfo.skipParens(tree));
1176             case IDENT:
1177             {
1178                 JCIdent ident = (JCIdent)tree;
1179                 Names names = ident.name.table.names;
1180                 return ident.name == names._this;
1181             }
1182             case SELECT:
1183             {
1184                 JCFieldAccess select = (JCFieldAccess)tree;
1185                 Type selectedType = types.erasure(select.selected.type);
1186                 if (!selectedType.hasTag(CLASS))
1187                     return false;
1188                 ClassSymbol currentClassSym = (ClassSymbol)((Type.ClassType)types.erasure(currentClass)).tsym;
1189                 ClassSymbol selectedClassSym = (ClassSymbol)((Type.ClassType)selectedType).tsym;
1190                 Names names = select.name.table.names;
1191                 return currentClassSym.isSubClass(selectedClassSym, types) &&
1192                         (select.name == names._super ||
1193                         (select.name == names._this &&
1194                             (currentClassSym == selectedClassSym ||
1195                             !currentClassSym.isEnclosedBy(selectedClassSym))));
1196             }
1197             default:
1198                 return false;
1199         }
1200     }
1201 
1202     // When scanning nodes we can be in one of two modes:
1203     //  (a) Looking for constructors - we do not recurse into any code blocks
1204     //  (b) Analyzing a constructor - we are tracing its possible execution paths
1205     private boolean isAnalyzing() {
1206         return targetClass != null;
1207     }
1208 
1209 // Debugging
1210 
1211     // Invariant checks
1212     private boolean checkInvariants(boolean analyzing, boolean allowExpr) {
1213         Assert.check(analyzing == isAnalyzing());
1214         if (isAnalyzing()) {
1215             Assert.check(methodClass != null);
1216             Assert.check(targetClass != null);
1217             Assert.check(refs != null);
1218             Assert.check(depth >= 0);
1219             Assert.check(refs.stream().noneMatch(ref -> ref.getDepth() > depth));
1220             Assert.check(allowExpr || !refs.contains(ExprRef.direct(depth)));
1221             Assert.check(allowExpr || !refs.contains(ExprRef.indirect(depth)));

 757         refs.remove(ExprRef.direct(depth));
 758         boolean indirectRef = refs.remove(ExprRef.indirect(depth));
 759         scan(tree.index);
 760         refs.discardExprs(depth);
 761         if (indirectRef) {
 762             refs.add(ExprRef.direct(depth));
 763             refs.add(ExprRef.indirect(depth));
 764         }
 765     }
 766 
 767     @Override
 768     public void visitSelect(JCFieldAccess tree) {
 769 
 770         // Scan the selected thing
 771         scan(tree.selected);
 772         boolean selectedDirectRef = refs.remove(ExprRef.direct(depth));
 773         boolean selectedIndirectRef = refs.remove(ExprRef.indirect(depth));
 774 
 775         // Explicit 'this' reference?
 776         Type.ClassType currentClassType = (Type.ClassType)methodClass.sym.type;
 777         if (TreeInfo.isExplicitThisReference(types, currentClassType, tree)) {
 778             refs.mapInto(refs, ThisRef.class, direct -> new ExprRef(depth, direct));
 779             return;
 780         }
 781 
 782         // Explicit outer 'this' reference?
 783         Type selectedType = types.erasure(tree.selected.type);
 784         if (selectedType.hasTag(CLASS)) {
 785             ClassSymbol currentClassSym = (ClassSymbol)currentClassType.tsym;
 786             ClassSymbol selectedTypeSym = (ClassSymbol)selectedType.tsym;
 787             if (tree.name == names._this &&
 788                     selectedTypeSym != currentClassSym &&
 789                     currentClassSym.isEnclosedBy(selectedTypeSym)) {
 790                 refs.mapInto(refs, OuterRef.class, direct -> new ExprRef(depth, direct));
 791                 return;
 792             }
 793         }
 794 
 795         // Methods - the "value" of a non-static method is a reference to its instance
 796         Symbol sym = tree.sym;
 797         if (sym.kind == MTH) {

1145         pendingWarning = callStack.toArray(new DiagnosticPosition[0]);
1146         callStack.pop();
1147     }
1148 
1149     // Copy pending warning, if any, to the warning list and reset
1150     private boolean copyPendingWarning() {
1151         if (pendingWarning == null)
1152             return false;
1153         warningList.add(pendingWarning);
1154         pendingWarning = null;
1155         return true;
1156     }
1157 
1158     // Does the symbol correspond to a parameter or local variable (not a field)?
1159     private boolean isParamOrVar(Symbol sym) {
1160         return sym != null &&
1161             sym.kind == VAR &&
1162             (sym.owner.kind == MTH || sym.owner.kind == VAR);
1163     }
1164 





































1165     // When scanning nodes we can be in one of two modes:
1166     //  (a) Looking for constructors - we do not recurse into any code blocks
1167     //  (b) Analyzing a constructor - we are tracing its possible execution paths
1168     private boolean isAnalyzing() {
1169         return targetClass != null;
1170     }
1171 
1172 // Debugging
1173 
1174     // Invariant checks
1175     private boolean checkInvariants(boolean analyzing, boolean allowExpr) {
1176         Assert.check(analyzing == isAnalyzing());
1177         if (isAnalyzing()) {
1178             Assert.check(methodClass != null);
1179             Assert.check(targetClass != null);
1180             Assert.check(refs != null);
1181             Assert.check(depth >= 0);
1182             Assert.check(refs.stream().noneMatch(ref -> ref.getDepth() > depth));
1183             Assert.check(allowExpr || !refs.contains(ExprRef.direct(depth)));
1184             Assert.check(allowExpr || !refs.contains(ExprRef.indirect(depth)));
< prev index next >