/** @since 0.17 or earlier */ protected ShapeImpl directReplaceProperty(ShapeImpl shape, Property oldProperty, Property newProperty) { Transition replacePropertyTransition = new Transition.DirectReplacePropertyTransition(oldProperty, newProperty); ShapeImpl cachedShape = shape.queryTransition(replacePropertyTransition); if (cachedShape != null) { return ensureValid(cachedShape); } PropertyMap newPropertyMap = shape.getPropertyMap().replaceCopy(oldProperty, newProperty); BaseAllocator allocator = shape.allocator().addLocation(newProperty.getLocation()); ShapeImpl newShape = shape.createShape(shape.getLayout(), shape.getSharedData(), shape, shape.getObjectType(), newPropertyMap, replacePropertyTransition, allocator, shape.getId()); shape.addDirectTransition(replacePropertyTransition, newShape); return newShape; }
public final ShapeImpl applyTransition(Transition transition, boolean append) { if (transition instanceof AddPropertyTransition) { return append ? append(((AddPropertyTransition) transition).getProperty()) : addProperty(((AddPropertyTransition) transition).getProperty()); } else if (transition instanceof ObjectTypeTransition) { return changeType(((ObjectTypeTransition) transition).getObjectType()); } else if (transition instanceof ReservePrimitiveArrayTransition) { return reservePrimitiveExtensionArray(); } else { throw new UnsupportedOperationException(); } }
/** @since 0.17 or earlier */ public final void addDirectTransition(Transition transition, ShapeImpl next) { assert next.getParent() == this && transition.isDirect(); addTransitionInternal(transition, next); }
/** @since 0.17 or earlier */ protected ShapeImpl cloneRoot(ShapeImpl from, Object newSharedData) { return createShape(from.layout, newSharedData, null, from.objectType, from.propertyMap, null, from.allocator(), from.id); }
/** * Clone off a separate shape with new shared data. */ @TruffleBoundary @Override public final ShapeImpl createSeparateShape(Object newSharedData) { if (parent == null) { return cloneRoot(this, newSharedData); } else { return this.cloneOnto(parent.createSeparateShape(newSharedData)); } }
/** @since 0.17 or earlier */ public final void addIndirectTransition(Transition transition, ShapeImpl next) { assert !isShared(); assert next.getParent() != this && !transition.isDirect(); addTransitionInternal(transition, next); }
@Override @TruffleBoundary public final ShapeImpl changeType(ObjectType newOps) { ObjectTypeTransition transition = new ObjectTypeTransition(newOps); ShapeImpl cachedShape = queryTransition(transition); if (cachedShape != null) { return cachedShape; } ShapeImpl newShape = createShape(layout, sharedData, this, newOps, propertyMap, transition, allocator(), id); addDirectTransition(transition, newShape); return newShape; }
/** @since 0.17 or earlier */ protected ShapeImpl addPrimitiveExtensionArray(ShapeImpl shape) { LayoutImpl layout = shape.getLayout(); assert layout.hasPrimitiveExtensionArray() && !shape.hasPrimitiveArray(); Transition transition = new ReservePrimitiveArrayTransition(); ShapeImpl cachedShape = shape.queryTransition(transition); if (cachedShape != null) { return layout.getStrategy().ensureValid(cachedShape); } ShapeImpl oldShape = ensureSpace(shape, layout.getPrimitiveArrayLocation()); ShapeImpl newShape = ShapeImpl.makeShapeWithPrimitiveExtensionArray(oldShape, transition); oldShape.addDirectTransition(transition, newShape); return newShape; }
/** @since 0.17 or earlier */ protected ShapeImpl applyTransition(ShapeImpl shape, Transition transition, boolean append) { if (transition instanceof AddPropertyTransition) { Property property = ((AddPropertyTransition) transition).getProperty(); if (append) { return shape.append(property); } else { shape.onPropertyTransition(property); return addProperty(shape, property, false); } } else if (transition instanceof ObjectTypeTransition) { return shape.changeType(((ObjectTypeTransition) transition).getObjectType()); } else if (transition instanceof ReservePrimitiveArrayTransition) { return shape.reservePrimitiveExtensionArray(); } else if (transition instanceof DirectReplacePropertyTransition) { Property oldProperty = ((DirectReplacePropertyTransition) transition).getPropertyBefore(); Property newProperty = ((DirectReplacePropertyTransition) transition).getPropertyAfter(); if (append) { oldProperty = shape.getProperty(oldProperty.getKey()); newProperty = newProperty.relocate(shape.allocator().moveLocation(newProperty.getLocation())); } return directReplaceProperty(shape, oldProperty, newProperty); } else { throw new UnsupportedOperationException(transition.getClass().getName()); } }
/** * Create a new shape that reserves the primitive extension array field. */ private static ShapeImpl makeShapeWithPrimitiveExtensionArray(ShapeImpl parent, Transition transition) { assert parent.getLayout().hasPrimitiveExtensionArray(); assert !parent.hasPrimitiveArray(); BaseAllocator allocator = parent.allocator().addLocation(parent.getLayout().getPrimitiveArrayLocation()); ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, parent.propertyMap, transition, allocator, parent.id); assert newShape.hasPrimitiveArray(); assert newShape.depth == allocator.depth; return newShape; }
/** @since 0.17 or earlier */ protected ShapeImpl addProperty(ShapeImpl shape, Property property, boolean ensureValid) { assert !(shape.hasProperty(property.getKey())) : "duplicate property " + property.getKey(); AddPropertyTransition addTransition = new AddPropertyTransition(property); ShapeImpl cachedShape = shape.queryTransition(addTransition); if (cachedShape != null) { return ensureValid ? ensureValid(cachedShape) : cachedShape; } ShapeImpl oldShape = ensureSpace(shape, property.getLocation()); ShapeImpl newShape = ShapeImpl.makeShapeWithAddedProperty(oldShape, addTransition); oldShape.addDirectTransition(addTransition, newShape); return newShape; }
public final ShapeImpl replaceProperty(Property oldProperty, Property newProperty) { Transition replacePropertyTransition = new Transition.ReplacePropertyTransition(oldProperty, newProperty); ShapeImpl cachedShape = queryTransition(replacePropertyTransition); if (cachedShape != null) { return cachedShape; List<Transition> transitionList = new ArrayList<>(); boolean found = false; while (top != getRoot() && !found) { Transition transition = top.getTransitionFromParent(); transitionList.add(transition); if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) { Transition transition = iterator.previous(); if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) { newShape = newShape.addProperty(newProperty); } else { newShape = newShape.applyTransition(transition, false); addIndirectTransition(replacePropertyTransition, newShape); return newShape;
this.objectType = Objects.requireNonNull(objectType); this.propertyMap = Objects.requireNonNull(propertyMap); this.root = parent != null ? parent.getRoot() : this; this.parent = parent; this.transitionFromParent = transitionFromParent; this.objectArraySize = objectArraySize; this.objectArrayCapacity = capacityFromSize(objectArraySize); this.objectFieldSize = objectFieldSize; this.primitiveFieldSize = primitiveFieldSize; this.primitiveArraySize = primitiveArraySize; this.primitiveArrayCapacity = capacityFromSize(primitiveArraySize); this.hasPrimitiveArray = hasPrimitiveArray; this.propertyCount = makePropertyCount(parent, propertyMap); this.propertyArray = makePropertiesList(parent, propertyMap); this.depth = parent.depth + 1; } else { this.validAssumption = createValidAssumption(); this.extraData = objectType.createShapeData(this); debugRegisterShape(this);
this.objectType = Objects.requireNonNull(objectType); this.propertyMap = Objects.requireNonNull(propertyMap); this.root = parent != null ? parent.getRoot() : this; this.parent = parent; this.objectArrayCapacity = capacityFromSize(objectArraySize); this.objectFieldSize = objectFieldSize; this.primitiveFieldSize = primitiveFieldSize; this.primitiveArraySize = primitiveArraySize; this.primitiveArrayCapacity = capacityFromSize(primitiveArraySize); this.hasPrimitiveArray = hasPrimitiveArray; this.shared = transitionFromParent instanceof ShareShapeTransition || (parent != null && parent.shared); this.propertyCount = makePropertyCount(parent, propertyMap); this.depth = parent.depth + 1; } else { this.validAssumption = createValidAssumption();
/** * Create a separate clone of a shape. * * @param newParent the cloned parent shape * @since 0.17 or earlier */ protected final ShapeImpl cloneOnto(ShapeImpl newParent) { ShapeImpl from = this; ShapeImpl newShape = createShape(newParent.layout, newParent.sharedData, newParent, from.objectType, from.propertyMap, from.transitionFromParent, from.allocator(), newParent.id); shapeCloneCount.inc(); newParent.addDirectTransition(from.transitionFromParent, newShape); return newShape; }
/** @since 0.17 or earlier */ protected ShapeImpl removeProperty(ShapeImpl shape, Property property) { assert !shape.isShared(); RemovePropertyTransition transition = new RemovePropertyTransition(property); ShapeImpl cachedShape = shape.queryTransition(transition); if (cachedShape != null) { return ensureValid(cachedShape); } ShapeImpl owningShape = getShapeFromProperty(shape, property.getKey()); if (owningShape != null) { List<Transition> transitionList = new ArrayList<>(); ShapeImpl current = shape; while (current != owningShape) { if (!(current.getTransitionFromParent() instanceof Transition.DirectReplacePropertyTransition) || !((Transition.DirectReplacePropertyTransition) current.getTransitionFromParent()).getPropertyBefore().getKey().equals(property.getKey())) { transitionList.add(current.getTransitionFromParent()); } current = current.parent; } ShapeImpl newShape = owningShape.parent; for (ListIterator<Transition> iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) { Transition previous = iterator.previous(); newShape = applyTransition(newShape, previous, true); } shape.addIndirectTransition(transition, newShape); return newShape; } else { return null; } }
@TruffleBoundary @Override public final ShapeImpl removeProperty(Property prop) { RemovePropertyTransition transition = new RemovePropertyTransition(prop); ShapeImpl cachedShape = queryTransition(transition); if (cachedShape != null) { return cachedShape; } ShapeImpl shape = getShapeFromProperty(prop); if (shape != null) { List<Transition> transitionList = new ArrayList<>(); ShapeImpl current = this; while (current != shape) { transitionList.add(current.getTransitionFromParent()); current = current.parent; } ShapeImpl newShape = shape.parent; for (ListIterator<Transition> iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) { Transition previous = iterator.previous(); newShape = newShape.applyTransition(previous, true); } addIndirectTransition(transition, newShape); return newShape; } else { return null; } }
/** @since 0.17 or earlier */ protected ShapeImpl generalizeProperty(Property oldProperty, Object value, ShapeImpl currentShape, ShapeImpl nextShape) { Location oldLocation = oldProperty.getLocation(); Location newLocation = currentShape.allocator().locationForValueUpcast(value, oldLocation); Property newProperty = oldProperty.relocate(newLocation); ShapeImpl newShape = nextShape.replaceProperty(oldProperty, newProperty); return newShape; }
@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, true), flags)); updateShape(); newShape.getLastProperty().setGeneric(this, value, oldShape, newShape); } else { defineExisting(id, value, flags, existing, oldShape); } }
/** @since 0.17 or earlier */ @TruffleBoundary @Override public final ShapeImpl append(Property oldProperty) { return addProperty(oldProperty.relocate(allocator().moveLocation(oldProperty.getLocation()))); }