changeset 7049:ccade022ec83

virtualization of unsafeload and unsafestore
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 27 Nov 2012 17:32:40 +0100
parents 2a1ec8b0bfe0
children 6cbaae52bab9
files graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java
diffstat 9 files changed, 133 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Tue Nov 27 17:32:40 2012 +0100
@@ -234,4 +234,12 @@
      * Returns the {@link java.lang.Class} object representing this type.
      */
     Class< ? > toJava();
+
+    /**
+     * Returns the instance field of this class (or one of its super classes) at the given offset, or {@code null} if there is no such field.
+     *
+     * @param offset the offset of the field to look for
+     * @return the field with the given offset, or {@code null} if there is no such field.
+     */
+    ResolvedJavaField findFieldWithOffset(long offset);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Tue Nov 27 17:32:40 2012 +0100
@@ -466,4 +466,15 @@
     public long prototypeMarkWord() {
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this);
     }
+
+    @Override
+    public ResolvedJavaField findFieldWithOffset(long offset) {
+        ResolvedJavaField[] declaredFields = getInstanceFields(true);
+        for (ResolvedJavaField field : declaredFields) {
+            if (((HotSpotResolvedJavaField) field).offset() == offset) {
+                return field;
+            }
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java	Tue Nov 27 17:32:40 2012 +0100
@@ -182,4 +182,9 @@
     @Override
     public void initialize() {
     }
+
+    @Override
+    public ResolvedJavaField findFieldWithOffset(long offset) {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Tue Nov 27 17:32:40 2012 +0100
@@ -26,12 +26,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Load of a value from a location specified as an offset relative to an object.
  * No null check is performed before the load.
  */
-public class UnsafeLoadNode extends FixedWithNextNode implements Lowerable {
+public class UnsafeLoadNode extends FixedWithNextNode implements Lowerable, Virtualizable {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -75,6 +76,26 @@
         tool.getRuntime().lower(this, tool);
     }
 
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        VirtualObjectNode virtual = tool.getVirtualState(object());
+        if (virtual != null) {
+            ValueNode indexValue = tool.getReplacedValue(offset());
+            if (indexValue.isConstant()) {
+                int fieldIndex = virtual.fieldIndexForOffset(indexValue.asConstant().asLong());
+                if (fieldIndex != -1) {
+                    ValueNode result = tool.getVirtualEntry(virtual, fieldIndex);
+                    VirtualObjectNode virtualResult = tool.getVirtualState(result);
+                    if (virtualResult != null) {
+                        tool.replaceWithVirtual(virtualResult);
+                    } else {
+                        tool.replaceWithValue(result);
+                    }
+                }
+            }
+        }
+    }
+
     @NodeIntrinsic
     public static native <T> T load(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind kind);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Nov 27 17:32:40 2012 +0100
@@ -26,12 +26,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * Store of a value at a location specified as an offset relative to an object.
  * No null check is performed before the store.
  */
-public class UnsafeStoreNode extends FixedWithNextNode implements StateSplit, Lowerable {
+public class UnsafeStoreNode extends FixedWithNextNode implements StateSplit, Lowerable, Virtualizable {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -96,6 +97,21 @@
         tool.getRuntime().lower(this, tool);
     }
 
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        VirtualObjectNode virtual = tool.getVirtualState(object());
+        if (virtual != null) {
+            ValueNode indexValue = tool.getReplacedValue(offset());
+            if (indexValue.isConstant()) {
+                int fieldIndex = virtual.fieldIndexForOffset(indexValue.asConstant().asLong());
+                if (fieldIndex != -1) {
+                    tool.setVirtualEntry(virtual, fieldIndex, value());
+                    tool.delete();
+                }
+            }
+        }
+    }
+
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
     @NodeIntrinsic
     public static native void store(Object object, @ConstantNodeParameter int displacement, long offset, Object value, @ConstantNodeParameter Kind kind);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java	Tue Nov 27 17:32:40 2012 +0100
@@ -58,4 +58,10 @@
         assert index == 0;
         return "value";
     }
+
+    @Override
+    public int fieldIndexForOffset(long constantOffset) {
+        // (lstadler) unsafe access to a newly created boxing object should only ever touch the value field
+        return 0;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java	Tue Nov 27 17:32:40 2012 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import sun.misc.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
@@ -70,4 +72,59 @@
     public String fieldName(int index) {
         return "[" + index + "]";
     }
+
+    @Override
+    public int fieldIndexForOffset(long constantOffset) {
+        int baseOffset;
+        int indexScale;
+        switch (componentType.getKind()) {
+            case Boolean:
+                baseOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
+                break;
+            case Byte:
+                baseOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_BYTE_INDEX_SCALE;
+                break;
+            case Short:
+                baseOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_SHORT_INDEX_SCALE;
+                break;
+            case Char:
+                baseOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_CHAR_INDEX_SCALE;
+                break;
+            case Int:
+                baseOffset = Unsafe.ARRAY_INT_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_INT_INDEX_SCALE;
+                break;
+            case Long:
+                baseOffset = Unsafe.ARRAY_LONG_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_LONG_INDEX_SCALE;
+                break;
+            case Float:
+                baseOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_FLOAT_INDEX_SCALE;
+                break;
+            case Double:
+                baseOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
+                break;
+            case Object:
+                baseOffset = Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+                indexScale = Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+                break;
+            default:
+                return -1;
+        }
+        long index = constantOffset - baseOffset;
+        if (index % indexScale != 0) {
+            return -1;
+        }
+        long elementIndex = index / indexScale;
+        if (elementIndex < 0 || elementIndex >= length) {
+            return -1;
+        }
+        return (int) elementIndex;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Tue Nov 27 17:32:40 2012 +0100
@@ -75,4 +75,9 @@
         Integer index = fieldMap.get(field);
         return index == null ? -1 : index;
     }
+
+    @Override
+    public int fieldIndexForOffset(long constantOffset) {
+        return fieldIndex(type.findFieldWithOffset(constantOffset));
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Nov 27 17:29:42 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Tue Nov 27 17:32:40 2012 +0100
@@ -57,4 +57,6 @@
     public void materializeAt(@SuppressWarnings("unused") FixedNode fixed) {
         // nothing to do in here - this method allows subclasses to respond to materialization
     }
+
+    public abstract int fieldIndexForOffset(long constantOffset);
 }