diff graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java @ 20994:68ff637e95b1

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Thu, 16 Apr 2015 17:09:06 +0200
parents abc059cb0acf
children e413295a3c95
line wrap: on
line diff
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java	Thu Apr 16 17:01:53 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java	Thu Apr 16 17:09:06 2015 +0200
@@ -54,10 +54,55 @@
 
     @Override
     protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory) {
-        new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build();
+        new Marker<B>(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build();
     }
 
-    private static final class Marker {
+    /**
+     * Ensures that an element is only in the worklist once.
+     *
+     * @param <T>
+     */
+    static class UniqueWorkList<T extends AbstractBlockBase<T>> extends ArrayDeque<T> {
+        private static final long serialVersionUID = 8009554570990975712L;
+        BitSet valid;
+
+        public UniqueWorkList(int size) {
+            this.valid = new BitSet(size);
+        }
+
+        @Override
+        public T poll() {
+            T result = super.poll();
+            if (result != null) {
+                valid.set(result.getId(), false);
+            }
+            return result;
+        }
+
+        @Override
+        public boolean add(T pred) {
+            if (!valid.get(pred.getId())) {
+                valid.set(pred.getId(), true);
+                return super.add(pred);
+            }
+            return false;
+        }
+
+        @Override
+        public boolean addAll(Collection<? extends T> collection) {
+            boolean changed = false;
+            for (T element : collection) {
+                if (!valid.get(element.getId())) {
+                    valid.set(element.getId(), true);
+                    super.add(element);
+                    changed = true;
+                }
+            }
+            return changed;
+        }
+    }
+
+    private static final class Marker<T extends AbstractBlockBase<T>> {
         private final LIR lir;
         private final FrameMap frameMap;
         private final RegisterAttributes[] registerAttributes;
@@ -72,16 +117,17 @@
             liveOutMap = new BlockMap<>(lir.getControlFlowGraph());
         }
 
-        private void build() {
-            Deque<AbstractBlockBase<?>> worklist = new ArrayDeque<>();
+        @SuppressWarnings("unchecked")
+        void build() {
+            UniqueWorkList<T> worklist = new UniqueWorkList<>(lir.getControlFlowGraph().getBlocks().size());
             for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) {
-                worklist.add(lir.getControlFlowGraph().getBlocks().get(i));
+                worklist.add((T) lir.getControlFlowGraph().getBlocks().get(i));
             }
             for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
                 liveInMap.put(block, frameMap.initReferenceMap(true));
             }
             while (!worklist.isEmpty()) {
-                AbstractBlockBase<?> block = worklist.poll();
+                AbstractBlockBase<T> block = worklist.poll();
                 processBlock(block, worklist);
             }
         }
@@ -101,7 +147,7 @@
             return false;
         }
 
-        private void processBlock(AbstractBlockBase<?> block, Deque<AbstractBlockBase<?>> worklist) {
+        private void processBlock(AbstractBlockBase<T> block, UniqueWorkList<T> worklist) {
             if (updateOutBlock(block)) {
                 try (Indent indent = Debug.logAndIndent("handle block %s", block)) {
                     BlockClosure closure = new BlockClosure(liveOutMap.get(block).clone());
@@ -119,14 +165,6 @@
         private static final EnumSet<OperandFlag> REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG);
         private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object);
 
-        private void forEachDestroyedCallerSavedRegister(LIRInstruction op, ValueConsumer consumer) {
-            if (op.destroysCallerSavedRegisters()) {
-                for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
-                    consumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET);
-                }
-            }
-        }
-
         private final class BlockClosure {
             private final ReferenceMap currentSet;
 
@@ -145,50 +183,57 @@
             private void processInstructionBottomUp(LIRInstruction op) {
                 try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) {
                     // kills
-                    op.visitEachTemp(this::defConsumer);
-                    op.visitEachOutput(this::defConsumer);
-                    forEachDestroyedCallerSavedRegister(op, this::defConsumer);
+
+                    op.visitEachTemp(defConsumer);
+                    op.visitEachOutput(defConsumer);
+                    if (op.destroysCallerSavedRegisters()) {
+                        for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
+                            defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET);
+                        }
+                    }
 
                     // gen - values that are considered alive for this state
-                    op.visitEachAlive(this::useConsumer);
-                    op.visitEachState(this::useConsumer);
+                    op.visitEachAlive(useConsumer);
+                    op.visitEachState(useConsumer);
                     // mark locations
-                    op.forEachState((inst, info) -> markLocation(inst, info, this.getCurrentSet()));
+                    op.forEachState(stateConsumer);
                     // gen
-                    op.visitEachInput(this::useConsumer);
+                    op.visitEachInput(useConsumer);
                 }
             }
 
-            /**
-             * @see InstructionValueConsumer
-             * @param operand
-             * @param mode
-             * @param flags
-             */
-            private void useConsumer(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                LIRKind kind = operand.getLIRKind();
-                if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) {
-                    // no need to insert values and derived reference
-                    Debug.log("set operand: %s", operand);
-                    frameMap.setReference(operand, currentSet);
+            InstructionStateProcedure stateConsumer = new InstructionStateProcedure() {
+                public void doState(LIRInstruction inst, LIRFrameState info) {
+                    markLocation(inst, info, getCurrentSet());
                 }
-            }
+            };
 
-            /**
-             * @see InstructionValueConsumer
-             * @param operand
-             * @param mode
-             * @param flags
-             */
-            private void defConsumer(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                if (shouldProcessValue(operand)) {
-                    Debug.log("clear operand: %s", operand);
-                    frameMap.clearReference(operand, currentSet);
-                } else {
-                    assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s",
-                                    operand, mode);
+            ValueConsumer useConsumer = new ValueConsumer() {
+                public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                    LIRKind kind = operand.getLIRKind();
+                    if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) {
+                        // no need to insert values and derived reference
+                        if (Debug.isLogEnabled()) {
+                            Debug.log("set operand: %s", operand);
+                        }
+                        frameMap.setReference(operand, currentSet);
+                    }
                 }
-            }
+            };
+
+            ValueConsumer defConsumer = new ValueConsumer() {
+                public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                    if (shouldProcessValue(operand)) {
+                        if (Debug.isLogEnabled()) {
+                            Debug.log("clear operand: %s", operand);
+                        }
+                        frameMap.clearReference(operand, currentSet);
+                    } else {
+                        assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format(
+                                        "Illegal PlatformKind is only allowed for TEMP mode: %s, %s", operand, mode);
+                    }
+                }
+            };
 
             protected boolean shouldProcessValue(Value operand) {
                 return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal;