Mercurial > hg > truffle
changeset 22288:47172a9b40ac
Object model refactoring, add Shape#defineProperty
author | Andreas Woess <andreas.woess@oracle.com> |
---|---|
date | Wed, 07 Oct 2015 19:15:14 +0200 |
parents | 479028cce974 |
children | cf203af4610c |
files | truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java |
diffstat | 7 files changed, 140 insertions(+), 88 deletions(-) [+] |
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java Wed Oct 07 19:15:14 2015 +0200 @@ -25,6 +25,7 @@ package com.oracle.truffle.api.object; import com.oracle.truffle.api.Assumption; + import java.util.EnumSet; import java.util.List; @@ -57,6 +58,20 @@ public abstract Shape addProperty(Property property); /** + * Add or change property in the map, yielding a new or cached Shape object. + * + * @return the shape after defining the property + */ + public abstract Shape defineProperty(Object key, Object value, int flags); + + /** + * Add or change property in the map, yielding a new or cached Shape object. + * + * @return the shape after defining the property + */ + public abstract Shape defineProperty(Object key, Object value, int flags, LocationFactory locationFactory); + + /** * An {@link Iterable} over the shape's properties in insertion order. */ public abstract Iterable<Property> getProperties();
--- a/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java Wed Oct 07 19:15:14 2015 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.object.basic; +import java.util.Objects; + import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.Layout; import com.oracle.truffle.api.object.Location; @@ -32,15 +34,16 @@ import com.oracle.truffle.object.LocationImpl; import com.oracle.truffle.object.ShapeImpl; import com.oracle.truffle.object.ShapeImpl.BaseAllocator; -import java.util.Objects; -class DefaultStrategy implements LayoutStrategy { +class DefaultStrategy extends LayoutStrategy { + @Override public boolean updateShape(DynamicObject object) { assert object.getShape().isValid(); return false; } - public Shape returnCached(Shape newShape) { + @Override + public Shape ensureValid(Shape newShape) { assert newShape.isValid(); return newShape; } @@ -52,39 +55,33 @@ return true; } + @Override public Shape ensureSpace(Shape shape, Location location) { Objects.requireNonNull(location); assert assertLocationInRange(shape, location); return shape; } + @Override public boolean isAutoExtArray() { return false; } - public Property generalizeProperty(DynamicObject object, Property oldProperty, Object value) { - Shape oldShape = object.getShape(); - Location oldLocation = oldProperty.getLocation(); - Location newLocation = ((BasicAllocator) oldShape.allocator()).locationForValueUpcast(value, oldLocation); - Property newProperty = oldProperty.relocate(newLocation); - Shape newShape = oldShape.replaceProperty(oldProperty, newProperty); - newProperty.setSafe(object, value, oldShape, newShape); - return newProperty; - } - - public Property generalizeProperty(DynamicObject object, Property oldProperty, Object value, Shape currentShape, Shape oldNewShape) { + @Override + public ShapeAndProperty generalizeProperty(Property oldProperty, Object value, Shape currentShape, Shape nextShape) { Location oldLocation = oldProperty.getLocation(); Location newLocation = ((BasicAllocator) currentShape.allocator()).locationForValueUpcast(value, oldLocation); Property newProperty = oldProperty.relocate(newLocation); - Shape newShape = oldNewShape.replaceProperty(oldProperty, newProperty); - newProperty.setSafe(object, value, currentShape, newShape); - return newProperty; + Shape newShape = nextShape.replaceProperty(oldProperty, newProperty); + return new ShapeAndProperty(newShape, newProperty); } + @Override public BaseAllocator createAllocator(Shape shape) { return new DefaultAllocatorImpl((ShapeImpl) shape); } + @Override public BaseAllocator createAllocator(Layout layout) { return new DefaultAllocatorImpl((LayoutImpl) layout); }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Wed Oct 07 19:15:14 2015 +0200 @@ -283,43 +283,21 @@ @Override @TruffleBoundary public void define(Object id, Object value, int flags) { - ShapeImpl oldShape = getShape(); - Property existing = oldShape.getProperty(id); - if (existing == null) { - updateShape(); - oldShape = getShape(); - Shape newShape = oldShape.addProperty(Property.create(id, oldShape.allocator().locationForValue(value, true, value != null), flags)); - updateShape(); - newShape.getLastProperty().setGeneric(this, value, oldShape, newShape); - } else { - defineExisting(id, value, flags, existing, oldShape); - } - } - - private void defineExisting(Object id, Object value, int flags, Property existing, ShapeImpl oldShape) { - if (existing.getFlags() == flags) { - existing.setGeneric(this, value, null); - } else { - Property newProperty = Property.create(id, oldShape.getLayout().existingLocationForValue(value, existing.getLocation(), oldShape), flags); - Shape newShape = oldShape.replaceProperty(existing, newProperty); - this.setShapeAndResize(newShape); - newProperty.setInternal(this, value); - } + define(id, value, flags, ShapeImpl.DEFAULT_LAYOUT_FACTORY); } @Override @TruffleBoundary public void define(Object id, Object value, int flags, LocationFactory locationFactory) { ShapeImpl oldShape = getShape(); - Property existing = oldShape.getProperty(id); - if (existing == null) { - updateShape(); - oldShape = getShape(); - Shape newShape = oldShape.addProperty(Property.create(id, locationFactory.createLocation(oldShape, value), flags)); - updateShape(); - newShape.getLastProperty().setGeneric(this, value, oldShape, newShape); + ShapeImpl newShape = oldShape.defineProperty(id, value, flags, locationFactory); + updateShape(); + Property property = newShape.getProperty(id); + + if (oldShape == newShape) { + property.setSafe(this, value, oldShape); } else { - defineExisting(id, value, flags, existing, oldShape); + property.setSafe(this, value, oldShape, newShape); } }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java Wed Oct 07 19:15:14 2015 +0200 @@ -48,8 +48,8 @@ private static final int INT_TO_DOUBLE_FLAG = 1; private static final int INT_TO_LONG_FLAG = 2; - private final LayoutStrategy strategy; - private final Class<? extends DynamicObject> clazz; + protected final LayoutStrategy strategy; + protected final Class<? extends DynamicObject> clazz; private final int allowedImplicitCasts; protected LayoutImpl(EnumSet<ImplicitCast> allowedImplicitCasts, Class<? extends DynamicObjectImpl> clazz, LayoutStrategy strategy) {
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java Wed Oct 07 19:15:14 2015 +0200 @@ -29,20 +29,36 @@ import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.object.ShapeImpl.BaseAllocator; -public interface LayoutStrategy { - boolean updateShape(DynamicObject object); +public abstract class LayoutStrategy { + public abstract boolean updateShape(DynamicObject object); + + public abstract Shape ensureValid(Shape newShape); + + public abstract Shape ensureSpace(Shape shape, Location location); - Shape returnCached(Shape newShape); + public abstract boolean isAutoExtArray(); + + public abstract BaseAllocator createAllocator(Layout shape); - Shape ensureSpace(Shape shape, Location location); + public abstract BaseAllocator createAllocator(Shape shape); - boolean isAutoExtArray(); + protected abstract ShapeAndProperty generalizeProperty(Property oldProperty, Object value, Shape currentShape, Shape nextShape); - Property generalizeProperty(DynamicObject object, Property oldProperty, Object value); + public static class ShapeAndProperty { + private final Shape shape; + private final Property property; - Property generalizeProperty(DynamicObject object, Property oldProperty, Object value, Shape oldShape, Shape newShape); + public ShapeAndProperty(Shape shape, Property property) { + this.shape = shape; + this.property = property; + } - BaseAllocator createAllocator(Layout shape); + public Shape getShape() { + return shape; + } - BaseAllocator createAllocator(Shape shape); + public Property getProperty() { + return property; + } + } }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java Wed Oct 07 19:15:14 2015 +0200 @@ -22,17 +22,16 @@ */ package com.oracle.truffle.object; +import java.util.Objects; + import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.FinalLocationException; import com.oracle.truffle.api.object.HiddenKey; import com.oracle.truffle.api.object.IncompatibleLocationException; import com.oracle.truffle.api.object.Location; -import com.oracle.truffle.api.object.LocationModifier; import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.object.Locations.DeclaredLocation; -import java.util.EnumSet; -import java.util.Objects; /** * Property objects represent the mapping between property identifiers (keys) and storage locations. @@ -213,27 +212,32 @@ } private void setSlowCase(DynamicObject store, Object value) { - if (getLocation() instanceof DeclaredLocation) { - setDeclaredLocation(store, value); - } else { - generalize(store, value); + Shape oldShape = store.getShape(); + Shape newShape = oldShape.defineProperty(getKey(), value, getFlags()); + if (store.updateShape()) { + oldShape = store.getShape(); } + assert newShape.isValid() && oldShape.isValid(); + Property newProperty = newShape.getProperty(getKey()); + newProperty.setSafe(store, value, oldShape, newShape); } - private void setDeclaredLocation(DynamicObject store, Object value) { - store.updateShape(); - Shape oldShape = store.getShape(); - Shape newShape = oldShape.addProperty(this.relocateShadow(oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)))); - store.updateShape(); - newShape.getLastProperty().setGeneric(store, value, oldShape, newShape); - } + private void setWithShapeSlowCase(DynamicObject store, Object value, Shape currentShape, Shape nextShape) { + Shape oldShape = currentShape; + if (store.updateShape()) { + oldShape = store.getShape(); + } + LayoutStrategy strategy = ((LayoutImpl) currentShape.getLayout()).getStrategy(); + LayoutStrategy.ShapeAndProperty newShapeAndProperty = strategy.generalizeProperty(this, value, oldShape, nextShape); + if (store.updateShape()) { + oldShape = store.getShape(); + } - private Property generalize(DynamicObject store, Object value) { - return ((LayoutImpl) store.getShape().getLayout()).getStrategy().generalizeProperty(store, this, value); - } + Shape newNextShape = newShapeAndProperty.getShape(); + Property newProperty = newShapeAndProperty.getProperty(); - private void setWithShapeSlowCase(DynamicObject store, Object value, Shape oldShape, Shape newShape) { - ((LayoutImpl) store.getShape().getLayout()).getStrategy().generalizeProperty(store, this, value, oldShape, newShape); + assert newNextShape.isValid() && oldShape.isValid(); + newProperty.setSafe(store, value, oldShape, newNextShape); } @Override @@ -246,7 +250,7 @@ return shadow; } - private Property relocateShadow(Location newLocation) { + Property relocateShadow(Location newLocation) { assert !isShadow() && getLocation() instanceof DeclaredLocation && relocatable; return new PropertyImpl(key, newLocation, flags, true, relocatable); }
--- a/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Wed Oct 07 20:27:40 2015 +0200 +++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Wed Oct 07 19:15:14 2015 +0200 @@ -22,6 +22,16 @@ */ package com.oracle.truffle.object; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -34,6 +44,7 @@ import com.oracle.truffle.api.object.DynamicObjectFactory; import com.oracle.truffle.api.object.Layout; import com.oracle.truffle.api.object.Location; +import com.oracle.truffle.api.object.LocationFactory; import com.oracle.truffle.api.object.ObjectLocation; import com.oracle.truffle.api.object.ObjectType; import com.oracle.truffle.api.object.Property; @@ -53,15 +64,6 @@ import com.oracle.truffle.object.Transition.PropertyTransition; import com.oracle.truffle.object.Transition.RemovePropertyTransition; import com.oracle.truffle.object.Transition.ReservePrimitiveArrayTransition; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; /** * Shape objects create a mapping of Property objects to indexes. The mapping of those indexes to an @@ -312,7 +314,7 @@ ShapeImpl cachedShape = this.getTransitionMapForRead().get(transition); if (cachedShape != null) { // Shape already exists? shapeCacheHitCount.inc(); - return (ShapeImpl) layout.getStrategy().returnCached(cachedShape); + return (ShapeImpl) layout.getStrategy().ensureValid(cachedShape); } shapeCacheMissCount.inc(); @@ -339,6 +341,40 @@ } } + @TruffleBoundary + @Override + public ShapeImpl defineProperty(Object key, Object value, int flags) { + return defineProperty(key, value, flags, DEFAULT_LAYOUT_FACTORY); + } + + @TruffleBoundary + @Override + public ShapeImpl defineProperty(Object key, Object value, int flags, LocationFactory locationFactory) { + ShapeImpl oldShape = this; + if (!oldShape.isValid()) { + oldShape = (ShapeImpl) layout.getStrategy().ensureValid(oldShape); + } + PropertyImpl existing = (PropertyImpl) oldShape.getProperty(key); + if (existing == null) { + return oldShape.addProperty(Property.create(key, locationFactory.createLocation(oldShape, value), flags)); + } else { + if (existing.getFlags() == flags) { + if (existing.getLocation().canSet(value)) { + return oldShape; + } else { + if (existing.getLocation() instanceof DeclaredLocation) { + return oldShape.addProperty(existing.relocateShadow(locationFactory.createLocation(oldShape, value))); + } else { + return (ShapeImpl) layout.getStrategy().generalizeProperty(existing, value, oldShape, oldShape).getShape(); + } + } + } else { + Property newProperty = Property.create(key, oldShape.getLayout().existingLocationForValue(value, existing.getLocation(), oldShape), flags); + return oldShape.replaceProperty(existing, newProperty); + } + } + } + /** * Add a new property in the map, yielding a new or cached Shape object. * @@ -1105,6 +1141,12 @@ } }; + static final LocationFactory DEFAULT_LAYOUT_FACTORY = new LocationFactory() { + public Location createLocation(Shape shape, Object value) { + return ((ShapeImpl) shape).allocator().locationForValue(value, true, value != null); + } + }; + private static final DebugCounter shapeCount = DebugCounter.create("Shapes allocated total"); private static final DebugCounter shapeCloneCount = DebugCounter.create("Shapes allocated cloned"); private static final DebugCounter shapeCacheHitCount = DebugCounter.create("Shape cache hits");