changeset 18609:c7fe48cd8087

Add ReferenceMap.mergeMaps().
author Josef Eisl <josef.eisl@jku.at>
date Wed, 03 Dec 2014 19:42:38 +0100
parents 66e31efead2f
children 6a6291c31657
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java
diffstat 3 files changed, 134 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Tue Dec 02 17:39:01 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Wed Dec 03 19:42:38 2014 +0100
@@ -44,4 +44,9 @@
     void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg);
 
     ReferenceMap clone();
+
+    /**
+     * Merge in references marked in the {@code other} {@link ReferenceMap}.
+     */
+    void mergeMaps(ReferenceMap other);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Tue Dec 02 17:39:01 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java	Wed Dec 03 19:42:38 2014 +0100
@@ -230,6 +230,131 @@
         }
     }
 
+    public void mergeMaps(ReferenceMap otherArg) {
+        HotSpotReferenceMap other = (HotSpotReferenceMap) otherArg;
+        if (registerRefMap != null) {
+            assert other.registerRefMap != null;
+            mergeBitSetRaw(registerRefMap, other.registerRefMap);
+        } else {
+            assert other.registerRefMap == null || other.registerRefMap.cardinality() == 0 : "Target register reference map is empty but the source is not: " + other.registerRefMap;
+        }
+        mergeBitSetRaw(frameRefMap, other.frameRefMap);
+    }
+
+    /**
+     * Merge the references from {@code src} into {@code dst}.
+     *
+     * @see HotSpotReferenceMap#registerRefMap
+     * @see HotSpotReferenceMap#frameRefMap
+     */
+    private static void mergeBitSetRaw(BitSet dst, BitSet src) {
+        assert dst.size() == src.size();
+        assert MergeVerifier.verifyMerge(dst, src);
+        dst.or(src);
+    }
+
+    private enum MergeVerifier {
+        NoReference,
+        WideOop,
+        NarrowOopLowerHalf,
+        NarrowOopUpperHalf,
+        TwoNarrowOops,
+        Illegal;
+
+        /**
+         * Create enum values from BitSet.
+         * <p>
+         * These bits can have the following values (LSB first):
+         *
+         * <pre>
+         * 000 - contains no references
+         * 100 - contains a wide oop
+         * 110 - contains a narrow oop in the lower half
+         * 101 - contains a narrow oop in the upper half
+         * 111 - contains two narrow oops
+         * </pre>
+         *
+         * @see HotSpotReferenceMap#registerRefMap
+         * @see HotSpotReferenceMap#frameRefMap
+         */
+        static MergeVerifier getFromBits(int idx, BitSet set) {
+            int n = (set.get(idx) ? 1 : 0) << 0 | (set.get(idx + 1) ? 1 : 0) << 1 | (set.get(idx + 2) ? 1 : 0) << 2;
+            switch (n) {
+                case 0:
+                    return NoReference;
+                case 1:
+                    return WideOop;
+                case 3:
+                    return NarrowOopLowerHalf;
+                case 5:
+                    return NarrowOopUpperHalf;
+                case 7:
+                    return TwoNarrowOops;
+                default:
+                    return Illegal;
+            }
+        }
+
+        String toBitString() {
+            int bits = toBit(this);
+            if (bits == -1) {
+                return "---";
+            }
+            return String.format("%3s", Integer.toBinaryString(bits)).replace(' ', '0');
+        }
+
+        static int toBit(MergeVerifier type) {
+            switch (type) {
+                case NoReference:
+                    return 0;
+                case WideOop:
+                    return 1;
+                case NarrowOopLowerHalf:
+                    return 3;
+                case NarrowOopUpperHalf:
+                    return 5;
+                case TwoNarrowOops:
+                    return 7;
+                default:
+                    return -1;
+            }
+        }
+
+        private static boolean verifyMerge(BitSet dst, BitSet src) {
+            for (int idx = 0; idx < dst.size(); idx += BITS_PER_WORD) {
+                if (!verifyMergeEntry(idx, dst, src)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private static boolean verifyMergeEntry(int idx, BitSet dst, BitSet src) {
+            MergeVerifier dstType = MergeVerifier.getFromBits(idx, dst);
+            MergeVerifier srcType = MergeVerifier.getFromBits(idx, src);
+
+            if (dstType == MergeVerifier.Illegal || srcType == MergeVerifier.Illegal) {
+                assert false : String.format("Illegal RefMap bit pattern: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString());
+                return false;
+            }
+            switch (dstType) {
+                case NoReference:
+                    return true;
+                case WideOop:
+                    switch (srcType) {
+                        case NoReference:
+                        case WideOop:
+                            return true;
+                        default:
+                            assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString());
+                            return false;
+                    }
+                default:
+                    return true;
+            }
+        }
+    }
+
     @Override
     public int hashCode() {
         throw new UnsupportedOperationException();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Tue Dec 02 17:39:01 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Dec 03 19:42:38 2014 +0100
@@ -133,6 +133,10 @@
         frameMap.setReference(location, debugInfo.getReferenceMap());
     }
 
+    public void markLocation(ReferenceMap refMap) {
+        debugInfo.getReferenceMap().mergeMaps(refMap);
+    }
+
     /**
      * Called by the register allocator after all locations are marked.
      *