001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.opt.liveness;
014
015import static org.jikesrvm.classloader.ClassLoaderConstants.LongTypeCode;
016import static org.jikesrvm.classloader.ClassLoaderConstants.VoidTypeCode;
017import static org.jikesrvm.compilers.opt.ir.Operators.PHI;
018import static org.jikesrvm.osr.OSRConstants.LOCAL;
019import static org.jikesrvm.osr.OSRConstants.STACK;
020
021import java.lang.reflect.Constructor;
022import java.util.ArrayList;
023import java.util.Enumeration;
024import java.util.HashSet;
025import java.util.Iterator;
026import java.util.LinkedList;
027import java.util.List;
028import java.util.Stack;
029
030import org.jikesrvm.VM;
031import org.jikesrvm.classloader.TypeReference;
032import org.jikesrvm.compilers.opt.DefUse;
033import org.jikesrvm.compilers.opt.driver.CompilerPhase;
034import org.jikesrvm.compilers.opt.ir.BasicBlock;
035import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock;
036import org.jikesrvm.compilers.opt.ir.GCIRMap;
037import org.jikesrvm.compilers.opt.ir.IR;
038import org.jikesrvm.compilers.opt.ir.Instruction;
039import org.jikesrvm.compilers.opt.ir.OsrPoint;
040import org.jikesrvm.compilers.opt.ir.Phi;
041import org.jikesrvm.compilers.opt.ir.RegSpillListElement;
042import org.jikesrvm.compilers.opt.ir.Register;
043import org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand;
044import org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand;
045import org.jikesrvm.compilers.opt.ir.operand.Operand;
046import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
047import org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement;
048import org.jikesrvm.compilers.opt.util.SortedGraphIterator;
049import org.jikesrvm.osr.LocalRegPair;
050import org.jikesrvm.osr.MethodVariables;
051import org.jikesrvm.osr.VariableMap;
052import org.jikesrvm.util.EmptyIterator;
053
054/**
055 * This class performs a flow-sensitive iterative live variable analysis.
056 * The result of this analysis is live ranges for each basic block.
057 * (@see BasicBlock)<p>
058 *
059 * This class can also optionally construct GC maps. These GC maps
060 * are later used to create the final gc map (see OptReferenceMap.java).<p>
061 *
062 * Previously we used to be concerned that we didn't lose any
063 * precision due to imprecise modeling of exceptions.
064 * However, the troublesome situation cannot occur in Java. The rest of the
065 * comment for this class explains why that situation cannot occur.<p>
066 *
067 * The Java SPEC forces the compiler to declare a variable as uninitialized
068 * in those case that would be problematic. Consider the following
069 * ***ILLEGAL*** example:
070 *
071 * <pre>
072 * static void main(String arg[]) {
073 *   Object x;
074 *
075 *   try {
076 *     foo();
077 *     x = null;
078 *     bar();
079 *   }
080 *   catch (FooException e) {
081 *   }
082 *
083 *   catch (BarException e) {
084 *     Object a = x;
085 *   }
086 * }
087 * </pre>
088 *
089 * <p>
090 * Here x is live in the Bar catch block, but not above the assignment
091 * in the try block.  We only kill off values coming from
092 * catch blocks if they are in the first PEI region (above the call
093 * to foo).  Thus, our analysis will conservatively record that x
094 * is live above the assignment.<p>
095 *
096 * However, the Java SPEC requires compilers to state that x is uninitialized
097 * here, even though it isn't.  Thus, this scenario cannot occur.
098 * Basically, every variable used in a catch block needs to be defined
099 * before the TRY statement.  (The SPEC doesn't explicitly state this, but
100 * on page 398 (Sec 16.2.13) it says that every variable used in a *finally*
101 * block needs to be defined before the TRY statement, which is even more
102 * restrictive.<p>
103 *
104 * Bottomline: losing precision is not a concern!
105 */
106public final class LiveAnalysis extends CompilerPhase {
107  // Real Instance Variables
108  /**
109   *  Should we also create GC maps while we are computing liveness
110   */
111  private final boolean createGCMaps;
112
113  /**
114   *  Should we store liveness information at the top of each handler block?
115   */
116  private final boolean storeLiveAtHandlers;
117
118  /**
119   *  Should we skip guard registers?
120   */
121  private final boolean skipGuards;
122
123  /**
124   *  Should we skip the (final) local propagation phase?
125   */
126  private final boolean skipLocal;
127
128  /**
129   *  The current LiveSet that we will carry around
130   */
131  private LiveSet currentSet;
132
133  /**
134   *  Temporary live information associated with each basic block
135   */
136  private BBLiveElement[] bbLiveInfo;
137
138  /**
139   * The GC map associated with the IR, optionally filled by this class
140   */
141  private final GCIRMap map;
142
143  private final VariableMap osrMap;
144
145  /**
146   * For each register, the set of live interval elements describing the
147   * register.
148   */
149  private ArrayList<LiveIntervalElement>[] registerMap;
150
151  private LiveInterval liveIntervals;
152
153  /** Debugging info */
154  private static final boolean DEBUG = false;
155
156  /** Even more debugging info */
157  private static final boolean VERBOSE = false;
158
159  @Override
160  public String getName() {
161    return "Live Analysis";
162  }
163
164  /**
165   * The constructor is used to specify whether GC maps should be computed
166   * along with live analysis.
167   *
168   * @param createGCMaps should we create GC maps?
169   * @param skipLocal should we skip the (final) local propagation phase?
170   */
171  public LiveAnalysis(boolean createGCMaps, boolean skipLocal) {
172    this(createGCMaps, skipLocal, false, true);
173  }
174
175  /**
176   * The constructor is used to specify whether GC maps should be computed
177   * along with live analysis.
178   *
179   * @param createGCMaps should we create GC maps?
180   * @param skipLocal should we skip the (final) local propagation phase?
181   * @param storeLiveAtHandlers should we store liveness info at the
182   * top of each handler block?
183   */
184  public LiveAnalysis(boolean createGCMaps, boolean skipLocal, boolean storeLiveAtHandlers) {
185    this(createGCMaps, skipLocal, storeLiveAtHandlers, true);
186  }
187
188  /**
189   * The constructor is used to specify whether GC maps should be computed
190   * along with live analysis.
191   *
192   * @param createGCMaps should we create GC maps?
193   * @param skipLocal should we skip the (final) local propagation phase?
194   * @param storeLiveAtHandlers should we store liveness info at the
195   * top of each handler block?
196   * @param skipGuards should we ignore validation registers?
197   */
198  public LiveAnalysis(boolean createGCMaps, boolean skipLocal, boolean storeLiveAtHandlers, boolean skipGuards) {
199    super(new Object[]{createGCMaps, skipLocal, storeLiveAtHandlers, skipGuards});
200    this.createGCMaps = createGCMaps;
201    this.skipLocal = skipLocal;
202    this.storeLiveAtHandlers = storeLiveAtHandlers;
203    this.skipGuards = skipGuards;
204    if (createGCMaps) {
205      // Create the IR-based Map we will use during compilation
206      // At a later phase this map is converted into the "runtime"
207      //  map, which is called OptReferenceMap.
208      map = new GCIRMap();
209      osrMap = new VariableMap();
210    } else {
211      map = null;
212      osrMap = null;
213    }
214  }
215
216  /**
217   *  By default we don't create GC maps and do perform the local prop phase
218   */
219  public LiveAnalysis() {
220    this(false, false, false, true);
221  }
222
223  /**
224   * Constructor for this compiler phase
225   */
226  private static final Constructor<CompilerPhase> constructor =
227      getCompilerPhaseConstructor(LiveAnalysis.class,
228                                  new Class[]{Boolean.TYPE, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE});
229
230  /**
231   * Get a constructor object for this compiler phase
232   * @return compiler phase constructor
233   */
234  @Override
235  public Constructor<CompilerPhase> getClassConstructor() {
236    return constructor;
237  }
238
239  /**
240   * The entry point into this class
241   * Perform live variable analysis on this IR, constructing live
242   * range info and (optionally) GC map info as we go.
243   *
244   * @param ir the ir
245   */
246  @Override
247  public void perform(IR ir) {
248    liveIntervals = new LiveInterval();
249
250    // Debugging information
251    // Live Intervals, GC Maps, and fixed-point results
252    final boolean dumpFinalLiveIntervals = DEBUG ||
253      ir.options.PRINT_GC_MAPS &&
254         (!ir.options.hasMETHOD_TO_PRINT() ||
255          (ir.options.hasMETHOD_TO_PRINT() && ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString()))
256         );
257    final boolean dumpFinalMaps = dumpFinalLiveIntervals;
258    final boolean dumpFixedPointResults = dumpFinalLiveIntervals;
259
260    // make sure IR info is up-to-date
261    DefUse.recomputeSpansBasicBlock(ir);
262    debugBegining(ir, createGCMaps, dumpFinalLiveIntervals, dumpFinalMaps, dumpFixedPointResults);
263    bbLiveInfo = new BBLiveElement[ir.cfg.numberOfNodes()];
264
265    for (int i = 0; i < ir.cfg.numberOfNodes(); i++) {
266      bbLiveInfo[i] = new BBLiveElement();
267    }
268
269    // allocate the "currentSet" which is used to cache the current results
270    currentSet = new LiveSet();
271    boolean reuseCurrentSet = false;
272
273    // make sure reverse top sort order is built
274    // currentBlock is the first node in the list
275    BasicBlock currentBlock = (BasicBlock) ir.cfg.buildRevTopSort();
276
277    // 2nd param: true means forward analysis; false means backward analysis
278    SortedGraphIterator bbIter = new SortedGraphIterator(currentBlock, false);
279    while (currentBlock != null) {
280      boolean changed = processBlock(currentBlock, reuseCurrentSet, ir);
281
282      // mark this block as processed and get the next one
283      BasicBlock nextBlock = (BasicBlock) bbIter.markAndGetNextTopSort(changed);
284
285      // check to see if nextBlock has only one successor, currentBlock.
286      // If so, we can reuse the current set and avoid performing a meet.
287      reuseCurrentSet = nextBlock != null && bbIter.isSinglePredecessor(currentBlock, nextBlock);
288      currentBlock = nextBlock;
289    }
290    debugPostGlobal(ir, dumpFinalLiveIntervals, dumpFinalMaps, dumpFixedPointResults);
291
292    // Now compute live ranges, using results from the fixed point computation
293    // Also, optionally create GC maps
294    // SSA doesn't need this part so we allow it to be optional.
295    // However, if we don't perform it than the final maps and intervals aren't
296    // created, so we can't print them.
297    if (!skipLocal) {
298      performLocalPropagation(ir, createGCMaps);
299
300      if (createGCMaps && dumpFinalMaps) {
301        System.out.println("**** START OF IR for method: " +
302                           ir.method.getName() +
303                           " in class: " +
304                           ir.method.getDeclaringClass());
305        ir.printInstructions();
306        System.out.println("**** END   OF IR INSTRUCTION DUMP ****");
307
308        printFinalMaps(ir);
309      }
310      if (dumpFinalLiveIntervals) {
311        printFinalLiveIntervals(ir);
312      }
313      // If we performed the local propagation, live interval information
314      // lives off of each basic block.
315      // Thus, we no longer need bbLiveInfo (the fixed points results)
316      // When we don't perform the local propagation, such as translating
317      // out of SSA, then we need to keep bbLiveInfo around
318      bbLiveInfo = null;
319
320      // compute the mapping from registers to live interval elements
321      computeRegisterMap(ir);
322    }
323
324    // No longer need currentSet, which is simply a cache of a LiveSet).
325    currentSet = null;
326
327    // This will be null if createGCMaps is false
328    if (createGCMaps) {
329      ir.MIRInfo.gcIRMap = map;
330      ir.MIRInfo.osrVarMap = osrMap;
331    }
332
333    // record whether or not we stored liveness information for handlers.
334    ir.setHandlerLivenessComputed(storeLiveAtHandlers);
335    ir.setLivenessInformation(liveIntervals);
336  }
337
338  public Iterator<LiveIntervalElement> iterateLiveIntervals(Register r) {
339    ArrayList<LiveIntervalElement> set = registerMap[r.getNumber()];
340    if (set == null) {
341      return EmptyIterator.<LiveIntervalElement>getInstance();
342    } else {
343      return set.iterator();
344    }
345  }
346
347  /**
348   * Update the data structures to reflect that all live intervals for r2
349   * are now intervals for r1.
350   *
351   * @param r1 old register
352   * @param r2 new register
353   */
354  public void merge(Register r1, Register r2) {
355    Iterator<LiveIntervalElement> i = iterateLiveIntervals(r2);
356    while (i.hasNext()) {
357      LiveIntervalElement interval = i.next();
358      interval.setRegister(r1);
359      addToRegisterMap(r1, interval);
360      i.remove();
361    }
362  }
363
364  /**
365   * Sets up a mapping from each register to the set of live intervals for
366   * the register.
367   * <p>
368   * Side effect: map each live interval element to its basic block.
369   *
370   * @param ir the governing IR
371   */
372  @SuppressWarnings("unchecked")
373  private void computeRegisterMap(IR ir) {
374    registerMap = new ArrayList[ir.regpool.getNumberOfSymbolicRegisters()];
375    for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
376      BasicBlock bb = e.nextElement();
377      for (Enumeration<LiveIntervalElement> i = liveIntervals.enumerateLiveIntervals(bb); i.hasMoreElements();) {
378        LiveIntervalElement lie = i.nextElement();
379        lie.setBasicBlock(bb);
380        if (lie.getRegister().isSymbolic()) {
381          addToRegisterMap(lie.getRegister(), lie);
382        }
383      }
384    }
385  }
386
387  private void addToRegisterMap(Register r, LiveIntervalElement i) {
388    int regNumber = r.getNumber();
389    ArrayList<LiveIntervalElement> set = registerMap[regNumber];
390    if (set == null) {
391      set = new ArrayList<LiveIntervalElement>(3);
392      registerMap[regNumber] = set;
393    }
394    set.add(i);
395  }
396
397  /**
398   * Compute summary (local) live variable analysis for a basic block, which
399   * is basically Gen and Kill information.<p>
400   *
401   * For more details, see the paper "Efficient and Precise Modeling of
402   * Exceptions for the Analysis of Java Programs" by Choi, Grove, Hind
403   * and Sarkar in ACM PASTE99 workshop.
404   *
405   * @param bblock the basic block
406   * @param ir the governing IR
407   */
408  private void computeBlockGenAndKill(BasicBlock bblock, IR ir) {
409    if (VERBOSE) {
410      System.out.println(" --> Computing Gen/Kill for block " + bblock);
411    }
412
413    // Tells whether we've seen the first PEI
414    boolean seenFirstPEI = false;
415
416    // Because control flow may emanate from a potentially excepting
417    // instruction (PEI) out of the basic block, care must be taken
418    // when computing what can be killed by a basic block.
419    //
420    //  S1:  y =
421    //  S2:  <exception-raising inst>
422    //  S3:  x =
423    // For example in the block above, live variables coming from
424    // the normal exit of the block (i.e., after S3) can be killed
425    // by S1 or S3 (depending on the variable).  However, live variables
426    // coming from the PEI edge (at S2) can only be killed by S1.
427    // Thus, when a block contains PEIs, we need to distinguish the
428    // kill sets.  Namely, we need
429    //    Kill_tot  -  what can be killed anywhere in the block
430    //    Kill_n    -  what can be killed from PEI_n on up
431    //    Kill_n-1  -  what can be killed from PEI_n-1 on up
432    //      ...
433    //    Kill_1    -  what can be killed from PEI_1 on up
434    // We would then compute In as follows
435    //
436    //  In = Out_norm - Kill_tot   (all vars entering from bottom are eligible
437    //                                to be killed)
438    //     U Out_n - Kill_n
439    //     U Out_n-1 - Kill_n-1
440    //     ...
441    //     U Out_1 - Kill_1
442    //     U Gen
443    //  where Out_n is the out information at PEI i, i.e., the IN information
444    //  for whatever handlers may catch PEI i
445    //    ...
446    //    PEI 1
447    //    ...
448    //    PEI n-1
449    //    ...
450    //    PEI n
451    //    ...
452    //  If we conservatively assume all handlers for the block of interest
453    //  can be reached by all PEIs in this block then the equation becomes
454    //   In = (Out_norm - Kill_tot)
455    //     U (Out_hand - Kill_n)
456    //     U (Out_hand - Kill_n-1)
457    //     ...
458    //     U (Out_hand - Kill_1)
459    //     U Gen
460    // where "Out_hand" is the union of the in sets for all handlers.
461    // Since Kill_i is a subset of Kill_j, for i < j, we can simplify to
462    //   In = (Out_norm - Kill_tot)
463    //     U (Out_hand - Kill_1)    (1)
464    //     U Gen
465    // Since kill_1 is a subset of kill_tot, we don't need the
466    // the parenthesis (and the intermediate set)
467    // If there are no handlers than (1) is empty and we don't need
468    // to compute Kill_1.  We will take this approach for now.
469    // So for each block we will have at most 2 kill sets: Kill_tot and Kill_1
470    // This code finds the first PEI in the block
471
472    Instruction firstPEI = null;
473    if (bblock.canThrowExceptions()) {
474      for (Instruction inst = bblock.firstInstruction(); inst != bblock.lastInstruction(); inst =
475          inst.nextInstructionInCodeOrder()) {
476        if (inst.isPEI() && bblock.getApplicableExceptionalOut(inst).hasMoreElements()) {
477          firstPEI = inst;
478          // remember that this block has a PEI with a handler for use
479          //  later in "processBlock"
480          bbLiveInfo[bblock.getNumber()].setContainsPEIWithHandler(true);
481          break;
482        }
483      }
484    }
485
486    // Get any uses from PHIs, which are in the successor blocks
487    getUsesFromPhis(bblock);
488
489    // Traverse instructions in reverse order within the basic block.
490    for (Instruction inst = bblock.lastInstruction(); inst != bblock.firstInstruction(); inst =
491        inst.prevInstructionInCodeOrder()) {
492
493      // traverse from defs to uses becauses uses happen after
494      // (in a backward sense) defs
495      Enumeration<Operand> defs = inst.getPureDefs();
496      while (defs.hasMoreElements()) {
497        Operand def = defs.nextElement();
498        if (def instanceof RegisterOperand) {
499          RegisterOperand regOp = (RegisterOperand) def;
500
501          // Do we care about this reg?
502          if (isSkippableReg(regOp, ir)) {
503            continue;
504          }
505          TypeReference regType = regOp.getType();
506
507          // Because the summary we compute is used to propagate to other
508          // basic blocks, if a register is block local, we don't need to
509          // include it.  It will be picked up later by local propagation phase.
510          if (regOp.getRegister().spansBasicBlock() && regType != null) {
511
512            // if it is a DEF we place it is the BBKillSet and remove it from
513            // the GEN set, (GEN should only contain upward-exposed uses,
514            // i.e., uses that are NOT dominated by a DEF).
515            // We don't need to worry about PEIs here because
516            // later instructions (traversing backwards like we are)
517            // will always dominate earlier instructions *of this block*
518            bbLiveInfo[bblock.getNumber()].BBKillSet().add(regOp);
519            bbLiveInfo[bblock.getNumber()].getGen().remove(regOp);
520
521            // However, if an exception can emanate from this basic block
522            // we are not guaranteed that all instructions will be executed
523            // in this block.  We allow killing of instructions
524            // after the last (in a backwards sense) potential exception
525            // throwing statement. (PEI)
526            // If there are no PEIs in this block we don't bother to add
527            if (seenFirstPEI) {
528              bbLiveInfo[bblock.getNumber()].firstPEIKillSet().add(regOp);
529            }
530          }
531        }
532      }
533
534      // Now process the uses, unless this is a PHI operator
535      if (inst.operator() != PHI) {
536        for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements();) {
537          Operand use = uses.nextElement();
538          if (use instanceof RegisterOperand) {
539            RegisterOperand regOp = (RegisterOperand) use;
540
541            // Do we care about this reg?
542            if (isSkippableReg(regOp, ir)) {
543              continue;
544            }
545
546            TypeReference regType = regOp.getType();
547
548            // Because the summary we compute is used to propagate to
549            // other basic blocks, if a register is block local,
550            // we don't need to include it.  It will be picked up
551            // later by local propagation phase.
552            if (regOp.getRegister().spansBasicBlock() && regType != null) {
553              bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
554            }
555          }                     // is RegOp
556        }       // foreach use
557      }         // not a PHI
558      // check whether the instruction we just processed is the first
559      // (last, thinking backwards) exception-raising instruction.
560      // If so, set the flag so we can start killing.
561      if (firstPEI == inst) {
562        seenFirstPEI = true;
563      }
564    }           // foreach instruction in block
565    if (VERBOSE) {
566      System.out.println("  Gen: " + bbLiveInfo[bblock.getNumber()].getGen());
567      System.out.println("  Kill: " + bbLiveInfo[bblock.getNumber()].BBKillSet());
568      System.out.println("  1st PEI Kill: " + bbLiveInfo[bblock.getNumber()].firstPEIKillSet());
569      System.out.println(" ---> Done computing Gen/Kill for block");
570    }
571  }
572
573  /**
574   * The rvals of phi nodes are logically uses in the phi's predecessor
575   * blocks, so here we collect phi rvals from the current block's
576   * successors into the gen set for this block, being careful to
577   * collect only the appropriate rval
578   *
579   * @param bblock the basic block of interest
580   *
581   * pre: Assumes the liveInfo array is allocated for this block
582   * post: May add to liveInfo for this block
583   */
584  private void getUsesFromPhis(BasicBlock bblock) {
585    Enumeration<BasicBlock> successors = bblock.getOut();
586    while (successors.hasMoreElements()) {
587      BasicBlock sb = successors.nextElement();
588      if (sb.isExit()) {
589        continue;
590      }
591
592      for (Instruction phi = sb.firstInstruction(); phi != sb.lastInstruction(); phi =
593          phi.nextInstructionInCodeOrder()) {
594        if (phi.operator() == PHI) {
595          for (int j = 0; j < Phi.getNumberOfValues(phi); j++) {
596            BasicBlockOperand bbop = Phi.getPred(phi, j);
597            if (bbop.block == bblock) {
598              Operand myRval = Phi.getValue(phi, j);
599              if (myRval instanceof RegisterOperand) {
600                RegisterOperand regOp = (RegisterOperand) myRval;
601                TypeReference regType = regOp.getType();
602                if (regOp.getRegister().spansBasicBlock() && regType != null) {
603                  bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
604                }
605              }
606            }
607          }
608        }
609      }
610    }
611  }
612
613  /**
614   *  Computes the in set for this block given the out, gen, and kill set
615   *  @param block the block of interest
616   *  @param reuseCurrentSet whether we can reuse the "currentSet" or else
617   *                         clear it out and recompute the meet of our succs
618   *  @param ir the governing ir
619   *
620   *  @return {@code true} if something changed
621   */
622  private boolean processBlock(BasicBlock block, boolean reuseCurrentSet, IR ir) {
623    if (VERBOSE) {
624      System.out.println(" *** processing block " + block + " # out edges: " + block.getNumberOfOut());
625      block.printExtended();
626    }
627
628    // We compute Gen and Kill the first time we process the block.
629    // This computation must happen early iun this method because it also computes
630    // summary information about the block (eg getContainsPEIWithHandler).
631    if (bbLiveInfo[block.getNumber()].BBKillSet() == null) {
632      bbLiveInfo[block.getNumber()].createKillAndGen();
633      computeBlockGenAndKill(block, ir);
634    }
635
636    // A summary of the IN sets of all exception handlers for the block
637    LiveSet exceptionBlockSummary = new LiveSet();
638
639    boolean blockHasHandlers = bbLiveInfo[block.getNumber()].getContainsPEIWithHandler();
640
641    // The computation of the Kill set takes into consideration exception
642    // semantics, i.e., that live information may flow into the middle
643    // of a basic block due to implicit edges at exception points.
644    // We keep 2 kill sets.
645    //     BBKillSet() contains variables that are killed if the block
646    //              is exited in the normal fashion
647    //     firstPEIKillSet() contains variables that are definitely killed
648    //              before the first PEI is executed.
649    //       This set contains only variables that are definitely
650    //       killed in this block despite the implicit exception edges.
651    //
652    if (!reuseCurrentSet) {
653      currentSet.clear();
654
655      // visit each successor, if it is a regular successor, add
656      // it to "currentSet".  If it is a handler block, add it to
657      // ExceptionBlockSummary.
658      for (Enumeration<BasicBlock> bbEnum = block.getOut(); bbEnum.hasMoreElements();) {
659        BasicBlock succ = bbEnum.nextElement();
660
661        // sometimes we may have a CFG edge to a handler, but no longer a
662        //   PEI that can make the edge realizable.  Thus, we have two
663        //   conditions in the following test.
664        if (blockHasHandlers && succ.isExceptionHandlerBasicBlock()) {
665          exceptionBlockSummary.add(bbLiveInfo[succ.getNumber()].getIn());
666        } else {
667          currentSet.add(bbLiveInfo[succ.getNumber()].getIn());
668        }
669      }
670    }
671    if (VERBOSE) {
672      System.out.println("\t Before applying transfor function:");
673      System.out.println("\t currentSet: " + currentSet);
674      System.out.println("\t exceptionBlockSummary: " + exceptionBlockSummary);
675    }
676
677    // At this point, currentSet contains the union of our normal successors'
678    // IN sets.
679    // Compute:    In = currentSet - BBKillSet
680    //                  U (exceptionBlockSummary - firstPEIKillSet)   (1)
681    //                  U Gen
682    // Since firstPEIKillSet is a subset of BBKillSet, we don't need the
683    // the parenthesis (and the intermediate set)
684    //
685    // If there are no handlers than exceptionBlockSummary is empty and
686    // we don't need to perform line (1)
687
688    // currentSet = currentSet - BBKillSet
689    // first kill off variables that are killed anywhere in the block
690    currentSet.remove(bbLiveInfo[block.getNumber()].BBKillSet());
691    if (blockHasHandlers) {
692
693      // currentSet = currentSet U exceptionBlockSummary
694      // add in the IN sets for the handlers
695      currentSet.add(exceptionBlockSummary);
696
697      // currentSet = currentSet - firstPEIKillSet
698      // kill off variables that are definitely killed, i.e., killed before
699      // the first PEI
700      currentSet.remove(bbLiveInfo[block.getNumber()].firstPEIKillSet());
701    }
702
703    // currentSet = currentSet U gen
704    // add in the GEN set
705    currentSet.add(bbLiveInfo[block.getNumber()].getGen());
706
707    // since we have monotonicity, we can add currentSet to
708    // the previous In set.  If it results in an addition we have
709    // a change and return true, otherwise return false.
710    if (bbLiveInfo[block.getNumber()].getIn().add(currentSet)) {
711      if (VERBOSE) {
712        System.out.println(" *** processBlock returning true, currentSet: " + currentSet);
713      }
714      return true;
715    } else {
716      if (VERBOSE) {
717        System.out.println(" *** processBlock returning false, currentSet: " + currentSet);
718      }
719      return false;
720    }
721  }
722
723  /**
724   *  This method performs the last phase of the analysis, local propagation.
725   *  It uses the results from the fixed point analysis to determine the
726   *  local live information within a basic block.<p>
727   *
728   *  It walks the IR and, using the live information computed for each
729   *  basic block, i.e., the results of the iterative solution, makes a single
730   *  pass backward walk through the basic block, GENing and KILLing
731   *  local information.  This produces the set of live variables at each
732   *  instruction.<p>
733   *
734   *  This information is saved into two data structures:
735   *  <ul>
736   *    <li>at all GC points, live references are recorded
737   *    <li>at all instructions, live range information is recorded
738   *  </ul>
739   *
740   *  @param ir the IR
741   *  @param createGCMaps whether GC maps need to be created
742   */
743  private void performLocalPropagation(IR ir, boolean createGCMaps) {
744    if (DEBUG) {
745      System.out.println(" .... starting local propagation\n");
746    }
747    Stack<MapElement> blockStack = null;
748    if (createGCMaps) {
749      // We want to add GC map entries in IR instruction order. However, we are
750      // visiting instructions in reverse order within a block. We solve this
751      // by pushing all additions to a local stack and pop (and add)
752      // the information to the GC map after the block has been processed.
753      blockStack = new Stack<MapElement>();
754    }
755    for (BasicBlock block = ir.firstBasicBlockInCodeOrder(); block != null; block =
756        block.nextBasicBlockInCodeOrder()) {
757      if (VERBOSE) {
758        System.out.print(" ....   processing block # " + block.getNumber() + " ...");
759      }
760
761      // This set will hold the live variables for the current
762      // instruction.  It is initialized from the "In" set of the block's
763      // successors and updated during the walk up the basic block.
764      LiveSet local = new LiveSet();
765
766      // The union of the IN sets of all exception blocks that can
767      // be reached (directly) from this block
768      LiveSet exceptionBlockSummary = new LiveSet();
769
770      // Create the out set by unioning the successors' in sets.
771      // During this processing we should NOT include exception-catching
772      // blocks, but instead remember them for use at exception-raising
773      // statements in this block
774      for (Enumeration<BasicBlock> bbEnum = block.getOut(); bbEnum.hasMoreElements();) {
775        BasicBlock succ = bbEnum.nextElement();
776        if (succ.isExceptionHandlerBasicBlock()) {
777          exceptionBlockSummary.add(bbLiveInfo[succ.getNumber()].getIn());
778        } else {
779          local.add(bbLiveInfo[succ.getNumber()].getIn());
780        }
781      }
782      if (VERBOSE) {
783        System.out.println(" Completed succ walk. exceptionBlockSummary: " +
784                           exceptionBlockSummary +
785                           "\n local: " +
786                           local);
787      }
788
789      // For each item in "local", create live interval info for this block.
790      liveIntervals.createEndLiveRange(local, block, null);
791
792      // Process the block, an instruction at a time.
793      for (Instruction inst = block.lastInstruction(); inst != block.firstInstruction(); inst =
794          inst.prevInstructionInCodeOrder()) {
795        if (VERBOSE) {
796          System.out.println("Processing: " + inst);
797        }
798
799        // If this instruction can raise an exception, then the catch
800        // block can be a direct successor to it
801        // To compensate this, we must first add in the live information
802        // for all such blocks, which we computed above and stored
803        // in "exceptionBlockSummary"
804        if (inst.isPEI()) {
805          local.add(exceptionBlockSummary);
806
807          // For each item in "exceptionBlockSummary", create live interval
808          // info for this block.
809          liveIntervals.createEndLiveRange(exceptionBlockSummary, block, inst);
810        }
811
812        // compute In set for this instruction & GC point info
813        // traverse from defs to uses, do "kill" then "gen" (backwards analysis)
814        // Def loop
815        for (Enumeration<Operand> defs = inst.getPureDefs(); defs.hasMoreElements();) {
816          Operand op = defs.nextElement();
817          if (op instanceof RegisterOperand) {
818            RegisterOperand regOp = (RegisterOperand) op;
819            // Currently, clients of live information do not need to know
820            // about validation reges.  (Reg Alloc cares about physical regs.)
821            if (isSkippableReg(regOp, ir)) {
822              continue;
823            }
824            if (regOp.getType() != null) {
825              // process the def as a kill
826              local.remove(regOp);
827              if (VERBOSE) {
828                System.out.println("  Killing: " + regOp + "\n local: " + local);
829              }
830
831              // mark this instruction as the start of the live range for reg
832              liveIntervals.setStartLiveRange(regOp.getRegister(), inst, block);
833            }
834          } // if operand is a Register
835        }   // defs
836
837        // GC Map Code:
838        //
839        // Now that we have processed all of the defs, if any, we check
840        // if the instruction is a potential GC point, insert it into
841        // the map.
842        // We do this after processing the defs (remember, this is a backward
843        // analysis) because the GC will occur (at least in the case of calls)
844        // after the uses have occurred (in the forward sense).  Thus, we
845        // don't yet factor in the uses for this instruction.
846        // For a statement like "x = y", we are capturing the program point
847        // "in the middle", i.e., during the execution, after the y has been
848        // fetched, but before the x has been defined.
849
850        // Above observation is not true for an OSR instruction. The current
851        // design of the OSR instruction requires the compiler build a GC map
852        // for variables used by the instruction.
853        // Otherwise, the compiler generates an empty gc map for the
854        // instruction. This results run away references if GC happens
855        // when a thread is being OSRed.
856        //
857        // TODO: better design of yieldpoint_osr instruction.
858        // -- Feng July 15, 2003
859        if (createGCMaps && !OsrPoint.conforms(inst) && inst.isGCPoint()) {
860          // make deep copy (and translate to regList) because we reuse
861          // local above.
862          // NOTE: this translation does some screening, see GCIRMap.java
863          List<RegSpillListElement> regList = map.createDU(local);
864          blockStack.push(new MapElement(inst, regList));
865          if (VERBOSE) {
866            System.out.println("SAVING GC Map");
867          }
868        }       // is GC instruction, and map not already made
869
870        // now process the uses
871        for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements();) {
872          Operand op = uses.nextElement();
873          if (op instanceof RegisterOperand) {
874            RegisterOperand regOp = (RegisterOperand) op;
875            // Do we care about this reg?
876            if (isSkippableReg(regOp, ir)) {
877              continue;
878            }
879            TypeReference regType = regOp.getType();
880            // see Def loop comment about magics
881            if (regType != null) {
882              // process the use as a gen
883              local.add(regOp);
884              if (VERBOSE) {
885                System.out.println("  Gen-ing: " + regOp);
886                System.out.println("local: " + local);
887              }
888              // mark this instruction as the end of the live range for reg
889              liveIntervals.createEndLiveRange(regOp.getRegister(), block, inst);
890            }
891          }     // if operand is a Register
892        }     // uses
893
894        if (createGCMaps && OsrPoint.conforms(inst)) {
895          // delayed gc map generation for Osr instruction,
896          // see comments before processing uses -- Feng, July 15, 2003
897          List<RegSpillListElement> regList = map.createDU(local);
898          blockStack.push(new MapElement(inst, regList));
899
900          // collect osr info using live set
901          collectOsrInfo(inst, local);
902        }
903      }     // end instruction loop
904
905      // The register allocator prefers that any registers that are live
906      // on entry be listed first.  This call makes it so.
907      liveIntervals.moveUpwardExposedRegsToFront(block);
908      if (createGCMaps) {
909        // empty the stack, insert the information into the map
910        while (!blockStack.isEmpty()) {
911          MapElement elem = blockStack.pop();
912          map.insert(elem.getInst(), elem.getList());
913        }
914      }
915
916      if (storeLiveAtHandlers && block.isExceptionHandlerBasicBlock()) {
917        ExceptionHandlerBasicBlock handlerBlock = (ExceptionHandlerBasicBlock) block;
918
919        // use local because we need to get a fresh one anyway.
920        handlerBlock.setLiveSet(local);
921        local = null;
922      } else {
923
924        // clear the local set for the next block
925        local.clear();
926      }
927    }           // end basic block for loop
928    if (DEBUG) {
929      System.out.println(" .... completed local propagation\n");
930    }
931  }
932
933  /**
934   * Should this register be included in the liveness solution?
935   *
936   * @param regOp the register operand to consider skipping
937   * @param ir the governing ir
938   * @return whether the register should be skipped, i.e., not be
939   *          present in the liveness solution
940   */
941  private boolean isSkippableReg(RegisterOperand regOp, IR ir) {
942    // The old test would exclude all physical registers.  However,
943    // register allocation needs to know about physical registers, except
944    // for the ones listed below.  Such regs are inserted in the IR
945    // during call expansion.
946    return regOp.getRegister().isExcludedLiveA() || (regOp.getRegister().isValidation() && skipGuards);
947  }
948
949  /**
950   * Just a helper method to encapsulate the optional debugging info
951   * that is performed at the beginning of the perform method
952   * @param ir  the IR
953   * @param createGCMaps are we creating GC maps?
954   * @param dumpFixedPointResults debug info
955   * @param dumpFinalMaps debug info
956   * @param dumpFinalLiveIntervals debug info
957   */
958  private void debugBegining(IR ir, boolean createGCMaps, boolean dumpFixedPointResults, boolean dumpFinalMaps, boolean dumpFinalLiveIntervals) {
959    if (dumpFixedPointResults || dumpFinalMaps || dumpFinalLiveIntervals) {
960      System.out.print("\n ====>  Performing liveness analysis ");
961      if (createGCMaps) {
962        System.out.print("and GC Maps ");
963      }
964      System.out.println("for method: " + ir.method.getName() + " in class: " + ir.method.getDeclaringClass() + "\n");
965      System.out.println("  method has " + ir.cfg.numberOfNodes() + " basic blocks");
966    }
967    if (dumpFinalMaps) {
968      System.out.println("**** START OF IR for method: " +
969                         ir.method.getName() +
970                         " in class: " +
971                         ir.method.getDeclaringClass());
972      ir.printInstructions();
973      System.out.println("**** END   OF IR INSTRUCTION DUMP ****");
974    }
975  }
976
977  /**
978   * Just a helper method to encapsulate the optional debugging info
979   * that is performed after the global propagation step of "perform"
980   *
981   * @param ir the IR
982   * @param dumpFixedPointResults debug info
983   * @param dumpFinalMaps debug info
984   * @param dumpFinalLiveIntervals debug info
985   */
986  private void debugPostGlobal(IR ir, boolean dumpFixedPointResults, boolean dumpFinalMaps, boolean dumpFinalLiveIntervals) {
987    if (DEBUG) {
988      System.out.println(" .... Completed global live computation ....");
989      if (VERBOSE) {
990        // Print the basic blocks
991        System.out.println(" .... CFG:");
992        System.out.println(ir.cfg);
993      }
994    }
995    if (dumpFixedPointResults) {
996      printFixedPointResults(ir);
997    }
998  }
999
1000  /**
1001   *  Prints the results of the fixed point computation.
1002   *  (Use printFinalMaps for the final GC map)
1003   *  @param ir the IR
1004   */
1005  private void printFixedPointResults(IR ir) {
1006    System.out.println("\n  ***** Fixed point results for IR-based GC Maps for " +
1007                       ir.method.getDeclaringClass() +
1008                       "." +
1009                       ir.method.getName());
1010    int length = bbLiveInfo.length;
1011    for (int i = 0; i < length; i++) {
1012      System.out.println("Live Info for Block #" + i);
1013      System.out.println(bbLiveInfo[i]);
1014    }
1015  }
1016
1017  private void printFinalMaps(IR ir) {
1018    System.out.println("\n  =-=-=-=-=- Final IR-based GC Maps for " +
1019                       ir.method.getDeclaringClass() +
1020                       "." +
1021                       ir.method.getName());
1022    map.dump();
1023    System.out.println("  =-=-=-=-=- End Final IR-based GC Maps\n");
1024  }
1025
1026  /**
1027   * Prints the Final Live Intervals
1028   * @param ir the IR
1029   */
1030  private void printFinalLiveIntervals(IR ir) {
1031    ir.printInstructions();
1032    System.out.println("\n  *+*+*+*+*+ Final Live Intervals for " +
1033                       ir.method.getDeclaringClass() +
1034                       "." +
1035                       ir.method.getName());
1036    for (BasicBlock block = ir.firstBasicBlockInCodeOrder(); block != null; block =
1037        block.nextBasicBlockInCodeOrder()) {
1038      liveIntervals.printLiveIntervalList(block);
1039    }
1040    System.out.println("  *+*+*+*+*+ End Final Live Intervals\n");
1041  }
1042
1043  /**
1044   * REturns the live information for a particular block
1045   * @param bb the basic block of interest
1046   * @return the live information for the block
1047   */
1048  public BBLiveElement getLiveInfo(BasicBlock bb) {
1049    return bbLiveInfo[bb.getNumber()];
1050  }
1051
1052  /**
1053   * Return the set of registers that are live on the control-flow edge
1054   * basic block bb1 to basic block bb2
1055   *
1056   * @param bb1 start block of the edge
1057   * @param bb2 end block of the edge
1058   * @return live registers on the edge
1059   */
1060  public HashSet<Register> getLiveRegistersOnEdge(BasicBlock bb1, BasicBlock bb2) {
1061    HashSet<Register> s1 = getLiveRegistersOnExit(bb1);
1062    HashSet<Register> s2 = getLiveRegistersOnEntry(bb2);
1063    s1.retainAll(s2);
1064    return s1;
1065  }
1066
1067  /**
1068   * @param bb the basic block we're interested in
1069   * @return the set of registers that are live across a basic block, and who
1070   * are live after the basic block exit.
1071   */
1072  HashSet<Register> getLiveRegistersOnExit(BasicBlock bb) {
1073    HashSet<Register> result = new HashSet<Register>(10);
1074    for (Enumeration<LiveIntervalElement> e = liveIntervals.enumerateLiveIntervals(bb); e.hasMoreElements();) {
1075      LiveIntervalElement lie = e.nextElement();
1076      Instruction end = lie.getEnd();
1077      if (end == null) result.add(lie.getRegister());
1078    }
1079    return result;
1080  }
1081
1082  /**
1083   * @param bb the basic block we're interested in
1084   * @return the set of registers that are live across a basic block, and who
1085   * are live before the basic block entry.
1086   */
1087  HashSet<Register> getLiveRegistersOnEntry(BasicBlock bb) {
1088    HashSet<Register> result = new HashSet<Register>(10);
1089    for (Enumeration<LiveIntervalElement> e = liveIntervals.enumerateLiveIntervals(bb); e.hasMoreElements();) {
1090      LiveIntervalElement lie = e.nextElement();
1091      Instruction begin = lie.getBegin();
1092      if (begin == null) result.add(lie.getRegister());
1093    }
1094    return result;
1095  }
1096
1097  // A simple class used to store live info
1098  public static final class BBLiveElement {
1099    private LiveSet gen;
1100    private LiveSet BBKillSet;
1101    private LiveSet firstPEIKillSet;
1102    private final LiveSet in;
1103    private boolean containsPEIWithHandler = false;
1104
1105    /**
1106     *  The constructor
1107     */
1108    BBLiveElement() {
1109      in = new LiveSet();
1110    }
1111
1112    /**
1113     * Returns the kill set
1114     * @return the Kill set for this block
1115     */
1116    public LiveSet BBKillSet() {
1117      return BBKillSet;
1118    }
1119
1120    /**
1121     * Returns the first PEI kill set, i.e., the Kill set up to the first PEI
1122     * @return the Kill set up to the first PEI
1123     */
1124    public LiveSet firstPEIKillSet() {
1125      return firstPEIKillSet;
1126    }
1127
1128    /**
1129     * Returns the Gen set
1130     * @return the Gen set for this block
1131     */
1132    public LiveSet getGen() {
1133      return gen;
1134    }
1135
1136    /**
1137     * Returns the In set
1138     * @return the In set for this block
1139     */
1140    public LiveSet getIn() {
1141      return in;
1142    }
1143
1144    /**
1145     * Returns whether this block has a PEI with a handler in this method
1146     * @return whether this block has a PEI with a handler in this method
1147     */
1148    public boolean getContainsPEIWithHandler() {
1149      return containsPEIWithHandler;
1150    }
1151
1152    /**
1153     * @param value whether this block has a PEI with a handler in this method
1154     */
1155    public void setContainsPEIWithHandler(boolean value) {
1156      containsPEIWithHandler = value;
1157    }
1158
1159    /**
1160     * creates (allocates) the Gen and Kill Sets
1161     */
1162    public void createKillAndGen() {
1163      BBKillSet = new LiveSet();
1164      firstPEIKillSet = new LiveSet();
1165      gen = new LiveSet();
1166    }
1167
1168    /**
1169     * creates a string representation of this object
1170     * @return string representation of this object
1171     */
1172    @Override
1173    public String toString() {
1174      StringBuilder buf = new StringBuilder();
1175      buf.append(" Gen: ").append(gen).append("\n");
1176      buf.append(" BB Kill: ").append(BBKillSet).append("\n");
1177      buf.append(" first PEI Kill: ").append(firstPEIKillSet).append("\n");
1178      buf.append(" In: ").append(in).append("\n");
1179      return buf.toString();
1180    }
1181
1182  }
1183
1184  /**
1185   * A simple class used just in this file when creating GC maps
1186   */
1187  static final class MapElement {
1188
1189    private final Instruction inst;
1190    private final List<RegSpillListElement> list;
1191
1192    MapElement(Instruction inst, List<RegSpillListElement> list) {
1193      this.inst = inst;
1194      this.list = list;
1195    }
1196
1197    /**
1198     * @return the instruction
1199     */
1200    public Instruction getInst() {
1201      return inst;
1202    }
1203
1204    /**
1205     * @return the list
1206     */
1207    public List<RegSpillListElement> getList() {
1208      return list;
1209    }
1210  }
1211
1212  /* collect osr info according to live information */
1213  private void collectOsrInfo(Instruction inst, LiveSet lives) {
1214    // create an entry to the OSRIRMap, order: callee => caller
1215    LinkedList<MethodVariables> mvarList = new LinkedList<MethodVariables>();
1216
1217    // get the type info for locals and stacks
1218    InlinedOsrTypeInfoOperand typeInfo = OsrPoint.getInlinedTypeInfo(inst);
1219
1220    /* iterator over type info and create LocalRegTuple
1221    * for each variable.
1222    * NOTE: we do not process LONG type register operand here,
1223    * which was splitted in BURS.
1224    */
1225    byte[][] ltypes = typeInfo.localTypeCodes;
1226    byte[][] stypes = typeInfo.stackTypeCodes;
1227
1228    int nummeth = typeInfo.methodids.length;
1229
1230    int elm_idx = 0;
1231    int snd_long_idx = typeInfo.validOps;
1232    for (int midx = 0; midx < nummeth; midx++) {
1233
1234      LinkedList<LocalRegPair> tupleList = new LinkedList<LocalRegPair>();
1235
1236      byte[] ls = ltypes[midx];
1237      byte[] ss = stypes[midx];
1238
1239      /* record maps for local variables, skip dead ones */
1240      for (int i = 0, n = ls.length; i < n; i++) {
1241        if (ls[i] != VoidTypeCode) {
1242          // check liveness
1243          Operand op = OsrPoint.getElement(inst, elm_idx++);
1244          LocalRegPair tuple = new LocalRegPair(LOCAL, i, ls[i], op);
1245          // put it in the list
1246          tupleList.add(tuple);
1247
1248          // get another half of a long type operand
1249          if (VM.BuildFor32Addr && (ls[i] == LongTypeCode)) {
1250            Operand other_op = OsrPoint.getElement(inst, snd_long_idx++);
1251            tuple._otherHalf = new LocalRegPair(LOCAL, i, ls[i], other_op);
1252
1253          }
1254        }
1255      }
1256
1257      /* record maps for stack slots */
1258      for (int i = 0, n = ss.length; i < n; i++) {
1259        if (ss[i] != VoidTypeCode) {
1260          LocalRegPair tuple =
1261              new LocalRegPair(STACK, i, ss[i], OsrPoint.getElement(inst, elm_idx++));
1262
1263          tupleList.add(tuple);
1264
1265          if (VM.BuildFor32Addr && (ss[i] == LongTypeCode)) {
1266            tuple._otherHalf =
1267                new LocalRegPair(STACK, i, ss[i], OsrPoint.getElement(inst, snd_long_idx++));
1268          }
1269        }
1270      }
1271
1272      // create MethodVariables
1273      MethodVariables mvar = new MethodVariables(typeInfo.methodids[midx], typeInfo.bcindexes[midx], tupleList);
1274      mvarList.add(mvar);
1275    }
1276
1277    // put the method variables for this OSR in the osrMap, encoding later.
1278    osrMap.insertFirst(inst, mvarList);
1279  }
1280}