1 package Analysis.OoOJava;
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
7 import java.util.Stack;
9 import Analysis.ArrayReferencees;
10 import Analysis.Liveness;
11 import Analysis.CallGraph.CallGraph;
12 import Analysis.Disjoint.DisjointAnalysis;
13 import Analysis.OwnershipAnalysis.AllocationSite;
14 import Analysis.OwnershipAnalysis.MethodContext;
20 import IR.Flat.FlatEdge;
21 import IR.Flat.FlatMethod;
22 import IR.Flat.FlatNode;
23 import IR.Flat.FlatOpNode;
24 import IR.Flat.FlatReturnNode;
25 import IR.Flat.FlatSESEEnterNode;
26 import IR.Flat.FlatSESEExitNode;
27 import IR.Flat.FlatWriteDynamicVarNode;
28 import IR.Flat.TempDescriptor;
30 public class OoOJavaAnalysis {
32 // data from the compiler
34 private TypeUtil typeUtil;
35 private CallGraph callGraph;
36 private DisjointAnalysis disjointAnalysis;
38 // an implicit SESE is automatically spliced into
39 // the IR graph around the C main before this analysis--it
40 // is nothing special except that we can make assumptions
41 // about it, such as the whole program ends when it ends
42 private FlatSESEEnterNode mainSESE;
44 // SESEs that are the root of an SESE tree belong to this
45 // set--the main SESE is always a root, statically SESEs
46 // inside methods are a root because we don't know how they
47 // will fit into the runtime tree of SESEs
48 private Set<FlatSESEEnterNode> rootSESEs;
50 // simply a set of every reachable SESE in the program, not
51 // including caller placeholder SESEs
52 private Set<FlatSESEEnterNode> allSESEs;
54 // A mapping of flat nodes to the stack of SESEs for that node, where
55 // an SESE is the child of the SESE directly below it on the stack.
56 // These stacks do not reflect the heirarchy over methods calls--whenever
57 // there is an empty stack it means all variables are available.
58 private Hashtable<FlatNode, Stack<FlatSESEEnterNode>> seseStacks;
60 private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
61 private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
62 private Hashtable<FlatNode, VarSrcTokTable> variableResults;
63 private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
64 private Hashtable<FlatNode, CodePlan> codePlans;
66 private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
68 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
70 private Hashtable<MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet;
72 // private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
73 // private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
74 // private OwnershipAnalysis ownAnalysisForSESEConflicts;
75 // private Hashtable<FlatNode, ConflictGraph> conflictGraphResults;
77 // temporal data structures to track analysis progress.
78 static private int uniqueLockSetId = 0;
80 public static int maxSESEage = -1;
82 // use these methods in BuildCode to have access to analysis results
83 public FlatSESEEnterNode getMainSESE() {
87 public Set<FlatSESEEnterNode> getRootSESEs() {
91 public Set<FlatSESEEnterNode> getAllSESEs() {
95 public int getMaxSESEage() {
100 public CodePlan getCodePlan(FlatNode fn) {
101 CodePlan cp = codePlans.get(fn);
105 public OoOJavaAnalysis(State state, TypeUtil tu, CallGraph callGraph,
106 DisjointAnalysis disjointAnalysis, Liveness liveness, ArrayReferencees arrayReferencees) {
108 double timeStartAnalysis = (double) System.nanoTime();
112 this.callGraph = callGraph;
113 this.disjointAnalysis = disjointAnalysis;
114 this.maxSESEage = state.MLP_MAXSESEAGE;
116 rootSESEs = new HashSet<FlatSESEEnterNode>();
117 allSESEs = new HashSet<FlatSESEEnterNode>();
119 seseStacks = new Hashtable<FlatNode, Stack<FlatSESEEnterNode>>();
120 livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
121 livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
122 variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
123 notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
124 codePlans = new Hashtable<FlatNode, CodePlan>();
125 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
127 notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
129 mapMethodContextToLiveInAllocationSiteSet = new Hashtable<MethodContext, HashSet<AllocationSite>>();
131 // conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
132 // methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
133 // conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
135 // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
136 // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
137 // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
139 FlatMethod fmMain = state.getMethodFlat(typeUtil.getMain());
141 mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);
142 mainSESE.setfmEnclosing(fmMain);
143 mainSESE.setmdEnclosing(fmMain.getMethod());
144 mainSESE.setcdEnclosing(fmMain.getMethod().getClassDesc());
147 // run analysis on each method that is actually called
148 // reachability analysis already computed this so reuse
149 Iterator<Descriptor> methItr = disjointAnalysis.getDescriptorsToAnalyze().iterator();
150 while (methItr.hasNext()) {
151 Descriptor d = methItr.next();
152 FlatMethod fm = state.getMethodFlat(d);
154 // find every SESE from methods that may be called
155 // and organize them into roots and children
156 buildForestForward(fm);
159 // 2nd pass, results are saved in FlatSESEEnterNode, so
160 // intermediate results, for safety, are discarded
161 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
162 while (rootItr.hasNext()) {
163 FlatSESEEnterNode root = rootItr.next();
164 livenessAnalysisBackward(root, true, null);
168 methItr = disjointAnalysis.getDescriptorsToAnalyze().iterator();
169 while (methItr.hasNext()) {
170 Descriptor d = methItr.next();
171 FlatMethod fm = state.getMethodFlat(d);
173 // starting from roots do a forward, fixed-point
174 // variable analysis for refinement and stalls
175 variableAnalysisForward(fm);
178 // 4th pass, compute liveness contribution from
179 // virtual reads discovered in variable pass
180 rootItr = rootSESEs.iterator();
181 while (rootItr.hasNext()) {
182 FlatSESEEnterNode root = rootItr.next();
183 livenessAnalysisBackward(root, true, null);
187 * SOMETHING IS WRONG WITH THIS, DON'T USE IT UNTIL IT CAN BE FIXED
189 * // 5th pass methItr = ownAnalysis.descriptorsToAnalyze.iterator(); while(
190 * methItr.hasNext() ) { Descriptor d = methItr.next(); FlatMethod fm =
191 * state.getMethodFlat( d );
193 * // prune variable results in one traversal // by removing reference
194 * variables that are not live pruneVariableResultsWithLiveness( fm ); }
198 methItr = disjointAnalysis.getDescriptorsToAnalyze().iterator();
199 while (methItr.hasNext()) {
200 Descriptor d = methItr.next();
201 FlatMethod fm = state.getMethodFlat(d);
203 // compute what is not available at every program
204 // point, in a forward fixed-point pass
205 notAvailableForward(fm);
210 private void buildForestForward(FlatMethod fm) {
212 // start from flat method top, visit every node in
213 // method exactly once, find SESEs and remember
214 // roots and child relationships
215 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
216 flatNodesToVisit.add(fm);
218 Set<FlatNode> visited = new HashSet<FlatNode>();
220 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
221 seseStacks.put(fm, seseStackFirst);
223 while (!flatNodesToVisit.isEmpty()) {
224 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
225 FlatNode fn = fnItr.next();
227 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
228 assert seseStack != null;
230 flatNodesToVisit.remove(fn);
233 buildForest_nodeActions(fn, seseStack, fm);
235 for (int i = 0; i < fn.numNext(); i++) {
236 FlatNode nn = fn.getNext(i);
238 if (!visited.contains(nn)) {
239 flatNodesToVisit.add(nn);
241 // clone stack and send along each analysis path
242 seseStacks.put(nn, (Stack<FlatSESEEnterNode>) seseStack.clone());
248 private void buildForest_nodeActions(FlatNode fn, Stack<FlatSESEEnterNode> seseStack,
252 case FKind.FlatSESEEnterNode: {
253 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
255 if (!fsen.getIsCallerSESEplaceholder()) {
259 fsen.setfmEnclosing(fm);
260 fsen.setmdEnclosing(fm.getMethod());
261 fsen.setcdEnclosing(fm.getMethod().getClassDesc());
263 if (seseStack.empty()) {
265 fsen.setParent(null);
267 seseStack.peek().addChild(fsen);
268 fsen.setParent(seseStack.peek());
271 seseStack.push(fsen);
275 case FKind.FlatSESEExitNode: {
276 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
277 assert !seseStack.empty();
278 FlatSESEEnterNode fsen = seseStack.pop();
282 case FKind.FlatReturnNode: {
283 FlatReturnNode frn = (FlatReturnNode) fn;
284 if (!seseStack.empty() && !seseStack.peek().getIsCallerSESEplaceholder()) {
285 throw new Error("Error: return statement enclosed within SESE "
286 + seseStack.peek().getPrettyIdentifier());
294 private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
295 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
297 // start from an SESE exit, visit nodes in reverse up to
298 // SESE enter in a fixed-point scheme, where children SESEs
299 // should already be analyzed and therefore can be skipped
300 // because child SESE enter node has all necessary info
301 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
304 flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
306 flatNodesToVisit.add(fsen.getFlatExit());
309 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
312 liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
315 while (!flatNodesToVisit.isEmpty()) {
316 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
317 flatNodesToVisit.remove(fn);
319 Set<TempDescriptor> prev = livenessResults.get(fn);
321 // merge sets from control flow joins
322 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
323 for (int i = 0; i < fn.numNext(); i++) {
324 FlatNode nn = fn.getNext(i);
325 Set<TempDescriptor> s = livenessResults.get(nn);
331 Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
333 // if a new result, schedule backward nodes for analysis
334 if (!curr.equals(prev)) {
335 livenessResults.put(fn, curr);
337 // don't flow backwards past current SESE enter
338 if (!fn.equals(fsen)) {
339 for (int i = 0; i < fn.numPrev(); i++) {
340 FlatNode nn = fn.getPrev(i);
341 flatNodesToVisit.add(nn);
347 Set<TempDescriptor> s = livenessResults.get(fsen);
352 // remember liveness per node from the root view as the
353 // global liveness of variables for later passes to use
355 livenessRootView.putAll(livenessResults);
358 // post-order traversal, so do children first
359 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
360 while (childItr.hasNext()) {
361 FlatSESEEnterNode fsenChild = childItr.next();
362 livenessAnalysisBackward(fsenChild, false, liveout);
366 private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
367 FlatSESEEnterNode currentSESE, boolean toplevel,
368 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
371 case FKind.FlatSESEExitNode:
373 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
374 if (!liveout.containsKey(fsexn)) {
375 liveout.put(fsexn, new HashSet<TempDescriptor>());
377 liveout.get(fsexn).addAll(liveIn);
379 // no break, sese exits should also execute default actions
382 // handle effects of statement in reverse, writes then reads
383 TempDescriptor[] writeTemps = fn.writesTemps();
384 for (int i = 0; i < writeTemps.length; ++i) {
385 liveIn.remove(writeTemps[i]);
388 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
389 Set<TempDescriptor> livetemps = liveout.get(fsexn);
390 if (livetemps != null && livetemps.contains(writeTemps[i])) {
391 // write to a live out temp...
392 // need to put in SESE liveout set
393 currentSESE.addOutVar(writeTemps[i]);
398 TempDescriptor[] readTemps = fn.readsTemps();
399 for (int i = 0; i < readTemps.length; ++i) {
400 liveIn.add(readTemps[i]);
403 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
404 if (virtualReadTemps != null) {
405 liveIn.addAll(virtualReadTemps);
416 private void variableAnalysisForward(FlatMethod fm) {
418 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
419 flatNodesToVisit.add(fm);
421 while (!flatNodesToVisit.isEmpty()) {
422 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
423 flatNodesToVisit.remove(fn);
425 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
426 assert seseStack != null;
428 VarSrcTokTable prev = variableResults.get(fn);
430 // merge sets from control flow joins
431 VarSrcTokTable curr = new VarSrcTokTable();
432 for (int i = 0; i < fn.numPrev(); i++) {
433 FlatNode nn = fn.getPrev(i);
434 VarSrcTokTable incoming = variableResults.get(nn);
435 curr.merge(incoming);
438 if (!seseStack.empty()) {
439 variable_nodeActions(fn, curr, seseStack.peek());
442 // if a new result, schedule forward nodes for analysis
443 if (!curr.equals(prev)) {
444 variableResults.put(fn, curr);
446 for (int i = 0; i < fn.numNext(); i++) {
447 FlatNode nn = fn.getNext(i);
448 flatNodesToVisit.add(nn);
454 private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
455 FlatSESEEnterNode currentSESE) {
458 case FKind.FlatSESEEnterNode: {
459 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
460 assert fsen.equals(currentSESE);
462 vstTable.age(currentSESE);
463 vstTable.assertConsistency();
467 case FKind.FlatSESEExitNode: {
468 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
469 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
470 assert currentSESE.getChildren().contains(fsen);
472 // remap all of this child's children tokens to be
473 // from this child as the child exits
474 vstTable.remapChildTokens(fsen);
476 // liveness virtual reads are things that might be
477 // written by an SESE and should be added to the in-set
478 // anything virtually read by this SESE should be pruned
479 // of parent or sibling sources
480 Set<TempDescriptor> liveVars = livenessRootView.get(fn);
481 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
483 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
484 if (fsenVirtReadsOld != null) {
485 fsenVirtReads.addAll(fsenVirtReadsOld);
487 livenessVirtualReads.put(fn, fsenVirtReads);
489 // then all child out-set tokens are guaranteed
490 // to be filled in, so clobber those entries with
491 // the latest, clean sources
492 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
493 while (outVarItr.hasNext()) {
494 TempDescriptor outVar = outVarItr.next();
495 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
497 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
498 vstTable.remove(outVar);
501 vstTable.assertConsistency();
506 case FKind.FlatOpNode: {
507 FlatOpNode fon = (FlatOpNode) fn;
509 if (fon.getOp().getOp() == Operation.ASSIGN) {
510 TempDescriptor lhs = fon.getDest();
511 TempDescriptor rhs = fon.getLeft();
513 vstTable.remove(lhs);
515 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
517 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
518 while (itr.hasNext()) {
519 VariableSourceToken vst = itr.next();
521 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
524 if (currentSESE.getChildren().contains(vst.getSESE())) {
525 // if the source comes from a child, copy it over
526 forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
529 // otherwise, stamp it as us as the source
530 forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
534 vstTable.addAll(forAddition);
536 // only break if this is an ASSIGN op node,
537 // otherwise fall through to default case
538 vstTable.assertConsistency();
543 // note that FlatOpNode's that aren't ASSIGN
544 // fall through to this default case
546 TempDescriptor[] writeTemps = fn.writesTemps();
547 if (writeTemps.length > 0) {
549 // for now, when writeTemps > 1, make sure
550 // its a call node, programmer enforce only
551 // doing stuff like calling a print routine
552 // assert writeTemps.length == 1;
553 if (writeTemps.length > 1) {
554 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
558 vstTable.remove(writeTemps[0]);
560 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
561 ts.add(writeTemps[0]);
563 vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
566 vstTable.assertConsistency();
573 private void notAvailableForward(FlatMethod fm) {
575 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
576 flatNodesToVisit.add(fm);
578 while (!flatNodesToVisit.isEmpty()) {
579 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
580 flatNodesToVisit.remove(fn);
582 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
583 assert seseStack != null;
585 Set<TempDescriptor> prev = notAvailableResults.get(fn);
587 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
588 for (int i = 0; i < fn.numPrev(); i++) {
589 FlatNode nn = fn.getPrev(i);
590 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
591 if (notAvailIn != null) {
592 curr.addAll(notAvailIn);
596 if (!seseStack.empty()) {
597 notAvailable_nodeActions(fn, curr, seseStack.peek());
600 // if a new result, schedule forward nodes for analysis
601 if (!curr.equals(prev)) {
602 notAvailableResults.put(fn, curr);
604 for (int i = 0; i < fn.numNext(); i++) {
605 FlatNode nn = fn.getNext(i);
606 flatNodesToVisit.add(nn);
612 private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
613 FlatSESEEnterNode currentSESE) {
615 // any temps that are removed from the not available set
616 // at this node should be marked in this node's code plan
617 // as temps to be grabbed at runtime!
621 case FKind.FlatSESEEnterNode: {
622 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
623 assert fsen.equals(currentSESE);
625 // keep a copy of what's not available into the SESE
626 // and restore it at the matching exit node
627 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
628 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
629 while (tdItr.hasNext()) {
630 notAvailCopy.add(tdItr.next());
632 notAvailableIntoSESE.put(fsen, notAvailCopy);
638 case FKind.FlatSESEExitNode: {
639 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
640 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
641 assert currentSESE.getChildren().contains(fsen);
643 notAvailSet.addAll(fsen.getOutVarSet());
645 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
646 assert notAvailIn != null;
647 notAvailSet.addAll(notAvailIn);
652 case FKind.FlatMethod: {
656 case FKind.FlatOpNode: {
657 FlatOpNode fon = (FlatOpNode) fn;
659 if (fon.getOp().getOp() == Operation.ASSIGN) {
660 TempDescriptor lhs = fon.getDest();
661 TempDescriptor rhs = fon.getLeft();
663 // copy makes lhs same availability as rhs
664 if (notAvailSet.contains(rhs)) {
665 notAvailSet.add(lhs);
667 notAvailSet.remove(lhs);
670 // only break if this is an ASSIGN op node,
671 // otherwise fall through to default case
676 // note that FlatOpNode's that aren't ASSIGN
677 // fall through to this default case
679 TempDescriptor[] writeTemps = fn.writesTemps();
680 for (int i = 0; i < writeTemps.length; i++) {
681 TempDescriptor wTemp = writeTemps[i];
682 notAvailSet.remove(wTemp);
684 TempDescriptor[] readTemps = fn.readsTemps();
685 for (int i = 0; i < readTemps.length; i++) {
686 TempDescriptor rTemp = readTemps[i];
687 notAvailSet.remove(rTemp);
689 // if this variable has exactly one source, potentially
690 // get other things from this source as well
691 VarSrcTokTable vstTable = variableResults.get(fn);
693 VSTWrapper vstIfStatic = new VSTWrapper();
694 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
696 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
698 VariableSourceToken vst = vstIfStatic.vst;
700 Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
703 // look through things that are also available from same source
704 while (availItr.hasNext()) {
705 VariableSourceToken vstAlsoAvail = availItr.next();
707 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
708 while (refVarItr.hasNext()) {
709 TempDescriptor refVarAlso = refVarItr.next();
711 // if a variable is available from the same source, AND it ALSO
712 // only comes from one statically known source, mark it available
713 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
714 Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
716 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
717 notAvailSet.remove(refVarAlso);