< prev index next >

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

Print this page
rev 56282 : [mq]: graal

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -22,20 +22,24 @@
  */
 
 
 package org.graalvm.compiler.lir;
 
+import static jdk.vm.ci.code.ValueUtil.asStackSlot;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.OUTGOING;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.EnumSet;
 
 import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;

@@ -298,36 +302,136 @@
     /**
      * An operation that saves registers to the stack. The set of saved registers can be
      * {@linkplain #remove(EconomicSet) pruned} and a mapping from registers to the frame slots in
      * which they are saved can be {@linkplain #getMap(FrameMap) retrieved}.
      */
-    public interface SaveRegistersOp {
+    public abstract static class SaveRegistersOp extends LIRInstruction {
+        public static final LIRInstructionClass<SaveRegistersOp> TYPE = LIRInstructionClass.create(SaveRegistersOp.class);
 
         /**
-         * Determines if the {@link #remove(EconomicSet)} operation is supported for this object.
+         * The registers (potentially) saved by this operation.
          */
-        boolean supportsRemove();
+        protected final Register[] savedRegisters;
+
+        /**
+         * The slots to which the registers are saved.
+         */
+        @Def(STACK) protected final AllocatableValue[] slots;
+
+        /**
+         *
+         * @param savedRegisters the registers saved by this operation which may be subject to
+         *            {@linkplain #remove(EconomicSet) pruning}
+         * @param savedRegisterLocations the slots to which the registers are saved
+         */
+        protected SaveRegistersOp(LIRInstructionClass<? extends SaveRegistersOp> c, Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) {
+            super(c);
+            assert Arrays.asList(savedRegisterLocations).stream().allMatch(LIRValueUtil::isVirtualStackSlot);
+            this.savedRegisters = savedRegisters;
+            this.slots = savedRegisterLocations;
+        }
 
         /**
          * Prunes {@code doNotSave} from the registers saved by this operation.
          *
          * @param doNotSave registers that should not be saved by this operation
          * @return the number of registers pruned
-         * @throws UnsupportedOperationException if removal is not {@linkplain #supportsRemove()
-         *             supported}
          */
-        int remove(EconomicSet<Register> doNotSave);
+        public int remove(EconomicSet<Register> doNotSave) {
+            return prune(doNotSave, savedRegisters);
+        }
 
         /**
          * Gets a map from the saved registers saved by this operation to the frame slots in which
          * they are saved.
          *
          * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a
          *            virtual slot to a frame slot index
          */
-        RegisterSaveLayout getMap(FrameMap frameMap);
 
+        public RegisterSaveLayout getMap(FrameMap frameMap) {
+            int total = 0;
+            for (int i = 0; i < savedRegisters.length; i++) {
+                if (savedRegisters[i] != null) {
+                    total++;
+                }
+            }
+            Register[] keys = new Register[total];
+            int[] values = new int[total];
+            if (total != 0) {
+                int mapIndex = 0;
+                for (int i = 0; i < savedRegisters.length; i++) {
+                    if (savedRegisters[i] != null) {
+                        keys[mapIndex] = savedRegisters[i];
+                        assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
+                        StackSlot slot = asStackSlot(slots[i]);
+                        values[mapIndex] = indexForStackSlot(frameMap, slot);
+                        mapIndex++;
+                    }
+                }
+                assert mapIndex == total;
+            }
+            return new RegisterSaveLayout(keys, values);
+        }
+
+        public Register[] getSavedRegisters() {
+            return savedRegisters;
+        }
+
+        public EconomicSet<Register> getSaveableRegisters() {
+            EconomicSet<Register> registers = EconomicSet.create(Equivalence.IDENTITY);
+            for (Register r : savedRegisters) {
+                registers.add(r);
+            }
+            return registers;
+        }
+
+        public AllocatableValue[] getSlots() {
+            return slots;
+        }
+
+        @Override
+        public abstract void emitCode(CompilationResultBuilder crb);
+
+        static int prune(EconomicSet<Register> toRemove, Register[] registers) {
+            int pruned = 0;
+            for (int i = 0; i < registers.length; i++) {
+                if (registers[i] != null) {
+                    if (toRemove.contains(registers[i])) {
+                        registers[i] = null;
+                        pruned++;
+                    }
+                }
+            }
+            return pruned;
+        }
+
+        /**
+         * Computes the index of a stack slot relative to slot 0. This is also the bit index of
+         * stack slots in the reference map.
+         *
+         * @param slot a stack slot
+         * @return the index of the stack slot
+         */
+        private static int indexForStackSlot(FrameMap frameMap, StackSlot slot) {
+            assert frameMap.offsetForStackSlot(slot) % frameMap.getTarget().wordSize == 0;
+            int value = frameMap.offsetForStackSlot(slot) / frameMap.getTarget().wordSize;
+            return value;
+        }
+    }
+
+    /**
+     * Marker interface for an operation that restores the registers saved by
+     * {@link SaveRegistersOp}.
+     */
+    public interface RestoreRegistersOp {
+    }
+
+    /**
+     * Marker interface for an operation that kills some set register and stack locations.
+     */
+    public interface ZapRegistersOp {
     }
 
     /**
      * A LIR operation that does nothing. If the operation records its position, it can be
      * subsequently {@linkplain #replace(LIR, LIRInstruction) replaced}.
< prev index next >