src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java

Print this page




   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.lir.stackslotalloc;
  24 
  25 import static org.graalvm.compiler.lir.LIRValueUtil.asVirtualStackSlot;
  26 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
  27 
  28 import java.util.ArrayDeque;

  29 import java.util.BitSet;
  30 import java.util.Deque;
  31 import java.util.EnumSet;
  32 import java.util.HashSet;
  33 import java.util.List;
  34 import java.util.Set;
  35 
  36 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  37 import org.graalvm.compiler.core.common.cfg.BlockMap;
  38 import org.graalvm.compiler.debug.Debug;
  39 import org.graalvm.compiler.debug.DebugCounter;
  40 import org.graalvm.compiler.debug.Indent;
  41 import org.graalvm.compiler.lir.InstructionValueConsumer;
  42 import org.graalvm.compiler.lir.InstructionValueProcedure;
  43 import org.graalvm.compiler.lir.LIR;
  44 import org.graalvm.compiler.lir.LIRInstruction;
  45 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
  46 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;


  47 import org.graalvm.compiler.lir.VirtualStackSlot;
  48 
  49 import jdk.vm.ci.meta.Value;
  50 
  51 /**
  52  * Calculates the stack intervals using a worklist-based backwards data-flow analysis.
  53  */
  54 final class FixPointIntervalBuilder {
  55     private final BlockMap<BitSet> liveInMap;
  56     private final BlockMap<BitSet> liveOutMap;
  57     private final LIR lir;
  58     private final int maxOpId;
  59     private final StackInterval[] stackSlotMap;
  60     private final HashSet<LIRInstruction> usePos;
  61 
  62     /**
  63      * The number of allocated stack slots.
  64      */
  65     private static final DebugCounter uninitializedSlots = Debug.counter("StackSlotAllocator[uninitializedSlots]");
  66 
  67     FixPointIntervalBuilder(LIR lir, StackInterval[] stackSlotMap, int maxOpId) {
  68         this.lir = lir;
  69         this.stackSlotMap = stackSlotMap;
  70         this.maxOpId = maxOpId;
  71         liveInMap = new BlockMap<>(lir.getControlFlowGraph());
  72         liveOutMap = new BlockMap<>(lir.getControlFlowGraph());
  73         this.usePos = new HashSet<>();
  74     }
  75 
  76     /**
  77      * Builds the lifetime intervals for {@link VirtualStackSlot virtual stack slots}, sets up
  78      * {@link #stackSlotMap} and returns a set of use positions, i.e. instructions that contain
  79      * virtual stack slots.
  80      */
  81     Set<LIRInstruction> build() {
  82         Deque<AbstractBlockBase<?>> worklist = new ArrayDeque<>();
  83         AbstractBlockBase<?>[] blocks = lir.getControlFlowGraph().getBlocks();
  84         for (int i = blocks.length - 1; i >= 0; i--) {
  85             worklist.add(blocks[i]);
  86         }
  87         for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
  88             liveInMap.put(block, new BitSet(stackSlotMap.length));
  89         }
  90         while (!worklist.isEmpty()) {
  91             AbstractBlockBase<?> block = worklist.poll();
  92             processBlock(block, worklist);
  93         }
  94         return usePos;
  95     }
  96 
  97     /**
  98      * Merge outSet with in-set of successors.
  99      */
 100     private boolean updateOutBlock(AbstractBlockBase<?> block) {
 101         BitSet union = new BitSet(stackSlotMap.length);
 102         for (AbstractBlockBase<?> succ : block.getSuccessors()) {
 103             union.or(liveInMap.get(succ));
 104         }
 105         BitSet outSet = liveOutMap.get(block);
 106         // check if changed
 107         if (outSet == null || !union.equals(outSet)) {
 108             liveOutMap.put(block, union);
 109             return true;
 110         }
 111         return false;
 112     }
 113 
 114     @SuppressWarnings("try")
 115     private void processBlock(AbstractBlockBase<?> block, Deque<AbstractBlockBase<?>> worklist) {
 116         if (updateOutBlock(block)) {
 117             try (Indent indent = Debug.logAndIndent("handle block %s", block)) {
 118                 List<LIRInstruction> instructions = lir.getLIRforBlock(block);
 119                 // get out set and mark intervals
 120                 BitSet outSet = liveOutMap.get(block);
 121                 markOutInterval(outSet, getBlockEnd(instructions));
 122                 printLiveSet("liveOut", outSet);
 123 
 124                 // process instructions
 125                 BlockClosure closure = new BlockClosure((BitSet) outSet.clone());
 126                 for (int i = instructions.size() - 1; i >= 0; i--) {
 127                     LIRInstruction inst = instructions.get(i);
 128                     closure.processInstructionBottomUp(inst);
 129                 }
 130 
 131                 // add predecessors to work list
 132                 for (AbstractBlockBase<?> b : block.getPredecessors()) {
 133                     worklist.add(b);
 134                 }
 135                 // set in set and mark intervals
 136                 BitSet inSet = closure.getCurrentSet();
 137                 liveInMap.put(block, inSet);
 138                 markInInterval(inSet, getBlockBegin(instructions));


 289         return stackSlotMap[stackSlot.getId()];
 290     }
 291 
 292     private void put(VirtualStackSlot stackSlot, StackInterval interval) {
 293         stackSlotMap[stackSlot.getId()] = interval;
 294     }
 295 
 296     private StackInterval getOrCreateInterval(VirtualStackSlot stackSlot) {
 297         StackInterval interval = get(stackSlot);
 298         if (interval == null) {
 299             interval = new StackInterval(stackSlot, stackSlot.getValueKind());
 300             put(stackSlot, interval);
 301         }
 302         return interval;
 303     }
 304 
 305     private StackInterval getIntervalFromStackId(int id) {
 306         return stackSlotMap[id];
 307     }
 308 
 309     private static int getBlockBegin(List<LIRInstruction> instructions) {
 310         return instructions.get(0).id();
 311     }
 312 
 313     private static int getBlockEnd(List<LIRInstruction> instructions) {
 314         return instructions.get(instructions.size() - 1).id() + 1;
 315     }
 316 
 317 }


   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.lir.stackslotalloc;
  24 
  25 import static org.graalvm.compiler.lir.LIRValueUtil.asVirtualStackSlot;
  26 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
  27 
  28 import java.util.ArrayDeque;
  29 import java.util.ArrayList;
  30 import java.util.BitSet;
  31 import java.util.Deque;
  32 import java.util.EnumSet;



  33 
  34 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  35 import org.graalvm.compiler.core.common.cfg.BlockMap;
  36 import org.graalvm.compiler.debug.Debug;
  37 import org.graalvm.compiler.debug.DebugCounter;
  38 import org.graalvm.compiler.debug.Indent;
  39 import org.graalvm.compiler.lir.InstructionValueConsumer;
  40 import org.graalvm.compiler.lir.InstructionValueProcedure;
  41 import org.graalvm.compiler.lir.LIR;
  42 import org.graalvm.compiler.lir.LIRInstruction;
  43 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
  44 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
  45 import org.graalvm.util.Equivalence;
  46 import org.graalvm.util.EconomicSet;
  47 import org.graalvm.compiler.lir.VirtualStackSlot;
  48 
  49 import jdk.vm.ci.meta.Value;
  50 
  51 /**
  52  * Calculates the stack intervals using a worklist-based backwards data-flow analysis.
  53  */
  54 final class FixPointIntervalBuilder {
  55     private final BlockMap<BitSet> liveInMap;
  56     private final BlockMap<BitSet> liveOutMap;
  57     private final LIR lir;
  58     private final int maxOpId;
  59     private final StackInterval[] stackSlotMap;
  60     private final EconomicSet<LIRInstruction> usePos;
  61 
  62     /**
  63      * The number of allocated stack slots.
  64      */
  65     private static final DebugCounter uninitializedSlots = Debug.counter("StackSlotAllocator[uninitializedSlots]");
  66 
  67     FixPointIntervalBuilder(LIR lir, StackInterval[] stackSlotMap, int maxOpId) {
  68         this.lir = lir;
  69         this.stackSlotMap = stackSlotMap;
  70         this.maxOpId = maxOpId;
  71         liveInMap = new BlockMap<>(lir.getControlFlowGraph());
  72         liveOutMap = new BlockMap<>(lir.getControlFlowGraph());
  73         this.usePos = EconomicSet.create(Equivalence.IDENTITY);
  74     }
  75 
  76     /**
  77      * Builds the lifetime intervals for {@link VirtualStackSlot virtual stack slots}, sets up
  78      * {@link #stackSlotMap} and returns a set of use positions, i.e. instructions that contain
  79      * virtual stack slots.
  80      */
  81     EconomicSet<LIRInstruction> build() {
  82         Deque<AbstractBlockBase<?>> worklist = new ArrayDeque<>();
  83         AbstractBlockBase<?>[] blocks = lir.getControlFlowGraph().getBlocks();
  84         for (int i = blocks.length - 1; i >= 0; i--) {
  85             worklist.add(blocks[i]);
  86         }
  87         for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
  88             liveInMap.put(block, new BitSet(stackSlotMap.length));
  89         }
  90         while (!worklist.isEmpty()) {
  91             AbstractBlockBase<?> block = worklist.poll();
  92             processBlock(block, worklist);
  93         }
  94         return usePos;
  95     }
  96 
  97     /**
  98      * Merge outSet with in-set of successors.
  99      */
 100     private boolean updateOutBlock(AbstractBlockBase<?> block) {
 101         BitSet union = new BitSet(stackSlotMap.length);
 102         for (AbstractBlockBase<?> succ : block.getSuccessors()) {
 103             union.or(liveInMap.get(succ));
 104         }
 105         BitSet outSet = liveOutMap.get(block);
 106         // check if changed
 107         if (outSet == null || !union.equals(outSet)) {
 108             liveOutMap.put(block, union);
 109             return true;
 110         }
 111         return false;
 112     }
 113 
 114     @SuppressWarnings("try")
 115     private void processBlock(AbstractBlockBase<?> block, Deque<AbstractBlockBase<?>> worklist) {
 116         if (updateOutBlock(block)) {
 117             try (Indent indent = Debug.logAndIndent("handle block %s", block)) {
 118                 ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(block);
 119                 // get out set and mark intervals
 120                 BitSet outSet = liveOutMap.get(block);
 121                 markOutInterval(outSet, getBlockEnd(instructions));
 122                 printLiveSet("liveOut", outSet);
 123 
 124                 // process instructions
 125                 BlockClosure closure = new BlockClosure((BitSet) outSet.clone());
 126                 for (int i = instructions.size() - 1; i >= 0; i--) {
 127                     LIRInstruction inst = instructions.get(i);
 128                     closure.processInstructionBottomUp(inst);
 129                 }
 130 
 131                 // add predecessors to work list
 132                 for (AbstractBlockBase<?> b : block.getPredecessors()) {
 133                     worklist.add(b);
 134                 }
 135                 // set in set and mark intervals
 136                 BitSet inSet = closure.getCurrentSet();
 137                 liveInMap.put(block, inSet);
 138                 markInInterval(inSet, getBlockBegin(instructions));


 289         return stackSlotMap[stackSlot.getId()];
 290     }
 291 
 292     private void put(VirtualStackSlot stackSlot, StackInterval interval) {
 293         stackSlotMap[stackSlot.getId()] = interval;
 294     }
 295 
 296     private StackInterval getOrCreateInterval(VirtualStackSlot stackSlot) {
 297         StackInterval interval = get(stackSlot);
 298         if (interval == null) {
 299             interval = new StackInterval(stackSlot, stackSlot.getValueKind());
 300             put(stackSlot, interval);
 301         }
 302         return interval;
 303     }
 304 
 305     private StackInterval getIntervalFromStackId(int id) {
 306         return stackSlotMap[id];
 307     }
 308 
 309     private static int getBlockBegin(ArrayList<LIRInstruction> instructions) {
 310         return instructions.get(0).id();
 311     }
 312 
 313     private static int getBlockEnd(ArrayList<LIRInstruction> instructions) {
 314         return instructions.get(instructions.size() - 1).id() + 1;
 315     }
 316 
 317 }
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File