changeset 18905:c46e268fd091

Truffle: add (and switch to) safe node field access implementation using reflection
author Andreas Woess <andreas.woess@jku.at>
date Thu, 22 Jan 2015 01:01:29 +0100
parents 6ba170cb6f53
children 48dd71b3dc03
files graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java
diffstat 1 files changed, 91 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Jan 22 00:37:29 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Jan 22 01:01:29 2015 +0100
@@ -43,6 +43,7 @@
  * Utility class that manages the special access methods for node instances.
  */
 public final class NodeUtil {
+    private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe");
 
     /**
      * Interface that allows the customization of field offsets used for {@link Unsafe} field
@@ -88,14 +89,14 @@
     /**
      * Information about a field in a {@link Node} class.
      */
-    public static final class NodeField {
+    public abstract static class NodeField {
 
         private final NodeFieldKind kind;
-        private final Class<?> type;
         private final String name;
-        private long offset;
+        protected final Class<?> type;
+        protected final long offset;
 
-        private NodeField(NodeFieldKind kind, Field field) {
+        protected NodeField(NodeFieldKind kind, Field field) {
             this.kind = kind;
             this.type = field.getType();
             this.name = field.getName();
@@ -103,7 +104,11 @@
         }
 
         protected static NodeField create(NodeFieldKind kind, Field field) {
-            return new NodeField(kind, field);
+            if (USE_UNSAFE) {
+                return new UnsafeNodeField(kind, field);
+            } else {
+                return new ReflectionNodeField(kind, field);
+            }
         }
 
         public NodeFieldKind getKind() {
@@ -122,16 +127,45 @@
             return offset;
         }
 
-        public void putObject(Object receiver, Object value) {
+        public abstract void putObject(Node receiver, Object value);
+
+        public abstract Object getObject(Node receiver);
+
+        public abstract Object loadValue(Node node);
+
+        @Override
+        public int hashCode() {
+            return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NodeField) {
+                NodeField other = (NodeField) obj;
+                return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
+            }
+            return false;
+        }
+    }
+
+    private static final class UnsafeNodeField extends NodeField {
+        protected UnsafeNodeField(NodeFieldKind kind, Field field) {
+            super(kind, field);
+        }
+
+        @Override
+        public void putObject(Node receiver, Object value) {
             assert !type.isPrimitive() && value == null || type.isInstance(value);
             unsafe.putObject(receiver, offset, value);
         }
 
-        public Object getObject(Object receiver) {
+        @Override
+        public Object getObject(Node receiver) {
             assert !type.isPrimitive();
             return unsafe.getObject(receiver, offset);
         }
 
+        @Override
         public Object loadValue(Node node) {
             if (type == boolean.class) {
                 return unsafe.getBoolean(node, offset);
@@ -153,19 +187,62 @@
                 return unsafe.getObject(node, offset);
             }
         }
+    }
+
+    private static final class ReflectionNodeField extends NodeField {
+        private final Field field;
+
+        protected ReflectionNodeField(NodeFieldKind kind, Field field) {
+            super(kind, field);
+            this.field = field;
+            field.setAccessible(true);
+        }
 
         @Override
-        public int hashCode() {
-            return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
+        public void putObject(Node receiver, Object value) {
+            assert !type.isPrimitive() && value == null || type.isInstance(value);
+            try {
+                field.set(receiver, value);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
         }
 
         @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof NodeField) {
-                NodeField other = (NodeField) obj;
-                return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
+        public Object getObject(Node receiver) {
+            assert !type.isPrimitive();
+            try {
+                return field.get(receiver);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
             }
-            return false;
+        }
+
+        @Override
+        public Object loadValue(Node node) {
+            try {
+                if (type == boolean.class) {
+                    return field.getBoolean(node);
+                } else if (type == byte.class) {
+                    return field.getByte(node);
+                } else if (type == short.class) {
+                    return field.getShort(node);
+                } else if (type == char.class) {
+                    return field.getChar(node);
+                } else if (type == int.class) {
+                    return field.getInt(node);
+                } else if (type == long.class) {
+                    return field.getLong(node);
+                } else if (type == float.class) {
+                    return field.getFloat(node);
+                } else if (type == double.class) {
+                    return field.getDouble(node);
+                } else {
+                    return field.get(node);
+                }
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
         }
     }