changeset 22338:15c9dda91e50

SL: simplify write property cache node
author Andreas Woess <andreas.woess@oracle.com>
date Fri, 30 Oct 2015 19:11:36 +0100
parents 4f3eda22dbe9
children 559087369317
files truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java
diffstat 2 files changed, 63 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java	Mon Nov 02 16:34:22 2015 +0100
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java	Fri Oct 30 19:11:36 2015 +0100
@@ -73,11 +73,10 @@
      * We use a separate long specialization to avoid boxing for long.
      */
     @Specialization(limit = "CACHE_LIMIT", guards = {"longLocation != null", "shape.check(receiver)"}, assumptions = "shape.getValidAssumption()")
-    @SuppressWarnings("unused")
     protected long doCachedLong(DynamicObject receiver,   //
                     @Cached("receiver.getShape()") Shape shape,   //
                     @Cached("getLongLocation(shape)") LongLocation longLocation) {
-        return longLocation.getLong(receiver, true);
+        return longLocation.getLong(receiver, shape);
     }
 
     protected LongLocation getLongLocation(Shape shape) {
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java	Mon Nov 02 16:34:22 2015 +0100
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java	Fri Oct 30 19:11:36 2015 +0100
@@ -42,9 +42,9 @@
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.object.FinalLocationException;
@@ -52,8 +52,11 @@
 import com.oracle.truffle.api.object.Location;
 import com.oracle.truffle.api.object.Property;
 import com.oracle.truffle.api.object.Shape;
+import com.oracle.truffle.api.utilities.AlwaysValidAssumption;
+import com.oracle.truffle.api.utilities.NeverValidAssumption;
 
 public abstract class SLWritePropertyCacheNode extends Node {
+    protected static final int CACHE_LIMIT = 3;
 
     protected final String propertyName;
 
@@ -63,105 +66,73 @@
 
     public abstract void executeObject(DynamicObject receiver, Object value);
 
-    @Specialization(guards = "location.isValid(receiver, value)", assumptions = "location.getAssumptions()")
-    public void writeCached(DynamicObject receiver, Object value,   //
-                    @Cached("createCachedWrite(receiver, value)") CachedWriteLocation location) {
-        if (location.writeUnchecked(receiver, value)) {
-            // write successful
-        } else {
+    @Specialization(guards = {"location != null", "shape.check(receiver)", "location.canSet(receiver, value)"}, assumptions = {"shape.getValidAssumption()"}, limit = "CACHE_LIMIT")
+    public void writeExistingPropertyCached(DynamicObject receiver, Object value, //
+                    @Cached("lookupLocation(receiver, value)") Location location, //
+                    @Cached("receiver.getShape()") Shape shape, //
+                    @Cached("ensureValid(receiver)") Assumption validAssumption) {
+        try {
+            validAssumption.check();
+        } catch (InvalidAssumptionException e) {
             executeObject(receiver, value);
+            return;
         }
-    }
-
-    @Specialization(contains = "writeCached")
-    @TruffleBoundary
-    public void writeGeneric(DynamicObject receiver, Object value,   //
-                    @Cached("new(createCachedWrite(receiver, value))") LRUCachedWriteLocation lru) {
-        CachedWriteLocation location = lru.location;
-        if (!location.isValid(receiver, value) || !location.areAssumptionsValid()) {
-            location = createCachedWrite(receiver, value);
-            lru.location = location;
-        }
-        if (location.writeUnchecked(receiver, value)) {
-            // write successful
-        } else {
-            executeObject(receiver, value);
+        try {
+            location.set(receiver, value, shape);
+        } catch (IncompatibleLocationException | FinalLocationException e) {
+            throw new IllegalStateException(e);
         }
     }
 
-    protected CachedWriteLocation createCachedWrite(DynamicObject receiver, Object value) {
-        while (receiver.updateShape()) {
-            // multiple shape updates might be needed.
-        }
-
-        Shape oldShape = receiver.getShape();
-        Shape newShape;
-        Property property = oldShape.getProperty(propertyName);
-
-        if (property != null && property.getLocation().canSet(receiver, value)) {
-            newShape = oldShape;
-        } else {
-            receiver.define(propertyName, value, 0);
-            newShape = receiver.getShape();
-            property = newShape.getProperty(propertyName);
-        }
-
-        if (!oldShape.check(receiver)) {
-            return createCachedWrite(receiver, value);
+    @Specialization(guards = {"existing == null", "shapeBefore.check(receiver)", "shapeAfter != null", "newLocation.canSet(receiver, value)"}, assumptions = {"shapeBefore.getValidAssumption()",
+                    "shapeAfter.getValidAssumption()"}, limit = "CACHE_LIMIT")
+    public void writeNewPropertyCached(DynamicObject receiver, Object value, //
+                    @Cached("lookupLocation(receiver, value)") @SuppressWarnings("unused") Location existing, //
+                    @Cached("receiver.getShape()") Shape shapeBefore, //
+                    @Cached("defineProperty(receiver, value)") Shape shapeAfter, //
+                    @Cached("getLocation(shapeAfter)") Location newLocation, //
+                    @Cached("ensureValid(receiver)") Assumption validAssumption) {
+        try {
+            validAssumption.check();
+        } catch (InvalidAssumptionException e) {
+            executeObject(receiver, value);
+            return;
         }
-
-        return new CachedWriteLocation(oldShape, newShape, property.getLocation());
-
-    }
-
-    protected static final class CachedWriteLocation {
-
-        private final Shape oldShape;
-        private final Shape newShape;
-        private final Location location;
-        private final Assumption validLocation = Truffle.getRuntime().createAssumption();
-
-        public CachedWriteLocation(Shape oldShape, Shape newShape, Location location) {
-            this.oldShape = oldShape;
-            this.newShape = newShape;
-            this.location = location;
-        }
-
-        public boolean areAssumptionsValid() {
-            return validLocation.isValid() && oldShape.getValidAssumption().isValid() && newShape.getValidAssumption().isValid();
-        }
-
-        public Assumption[] getAssumptions() {
-            return new Assumption[]{oldShape.getValidAssumption(), newShape.getValidAssumption(), validLocation};
-        }
-
-        public boolean isValid(DynamicObject receiver, Object value) {
-            return oldShape.check(receiver) && location.canSet(receiver, value);
-        }
-
-        public boolean writeUnchecked(DynamicObject receiver, Object value) {
-            try {
-                if (oldShape == newShape) {
-                    location.set(receiver, value, oldShape);
-                } else {
-                    location.set(receiver, value, oldShape, newShape);
-                }
-                return true;
-            } catch (IncompatibleLocationException | FinalLocationException e) {
-                validLocation.invalidate();
-                return false;
-            }
+        try {
+            newLocation.set(receiver, value, shapeBefore, shapeAfter);
+        } catch (IncompatibleLocationException e) {
+            throw new IllegalStateException(e);
         }
     }
 
-    protected static final class LRUCachedWriteLocation {
-
-        private CachedWriteLocation location;
-
-        public LRUCachedWriteLocation(CachedWriteLocation location) {
-            this.location = location;
-        }
-
+    @Specialization(contains = {"writeExistingPropertyCached", "writeNewPropertyCached"})
+    @TruffleBoundary
+    public void writeUncached(DynamicObject receiver, Object value) {
+        receiver.define(propertyName, value);
     }
 
+    protected final Location lookupLocation(DynamicObject object, Object value) {
+        final Shape oldShape = object.getShape();
+        final Property property = oldShape.getProperty(propertyName);
+
+        if (property != null && property.getLocation().canSet(object, value)) {
+            return property.getLocation();
+        } else {
+            return null;
+        }
+    }
+
+    protected final Shape defineProperty(DynamicObject receiver, Object value) {
+        Shape oldShape = receiver.getShape();
+        Shape newShape = oldShape.defineProperty(propertyName, value, 0);
+        return newShape;
+    }
+
+    protected final Location getLocation(Shape newShape) {
+        return newShape.getProperty(propertyName).getLocation();
+    }
+
+    protected static Assumption ensureValid(DynamicObject receiver) {
+        return receiver.updateShape() ? NeverValidAssumption.INSTANCE : AlwaysValidAssumption.INSTANCE;
+    }
 }