Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.oracle.truffle.api.object.Shape Maven / Gradle / Ivy
Go to download
Truffle is a multi-language framework for executing dynamic languages
that achieves high performance when combined with Graal.
/*
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.truffle.api.object;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.Equivalence;
import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.object.Layout.ImplicitCast;
import com.oracle.truffle.api.utilities.NeverValidAssumption;
/**
* A Shape is an immutable descriptor of the current object "shape" of a DynamicObject, i.e., object
* layout, metadata ({@linkplain Shape#getDynamicType() type}, {@linkplain Shape#getFlags() flags}),
* and a mapping of {@linkplain Property properties} to storage locations. This allows cached
* {@link DynamicObjectLibrary} to do a simple shape check to determine the contents of an object
* and do fast, constant-time property accesses.
*
*
* Shapes are shared between objects that assume the same shape if they follow the same shape
* transitions, like adding the same properties in the same order, starting from a common root
* shape. Shape transitions are automatically, weakly cached.
*
*
* Dynamic objects start off with an initial shape that has no instance properties (but may have
* constant properties that are stored in the shape). Initial shapes are created via
* {@link Shape#newBuilder()}.
*
* @see DynamicObject
* @see Shape#newBuilder()
* @see Property
* @since 0.8 or earlier
*/
public abstract class Shape {
static final int OBJECT_FLAGS_MASK = 0x0000_00ff;
static final int OBJECT_FLAGS_SHIFT = 0;
static final int OBJECT_SHARED = 1 << 16;
static final int OBJECT_PROPERTY_ASSUMPTIONS = 1 << 17;
/**
* Creates a new initial shape builder.
*
*
* The builder instance is not thread-safe and must not be used from multiple threads at the
* same time.
*
* @since 20.2.0
*/
public static Builder newBuilder() {
CompilerAsserts.neverPartOfCompilation();
return new Builder();
}
/**
* Internal superclass shared by {@link Builder} and {@link DerivedBuilder}.
*
* @since 20.2.0
*/
abstract static class AbstractBuilder> {
/**
* Sets initial dynamic object type identifier.
*
* See {@link DynamicObjectLibrary#setDynamicType(DynamicObject, Object)} for more
* information.
*
* @param dynamicType a non-null object type identifier
* @throws NullPointerException if the type is {@code null}
* @since 20.2.0
*/
public abstract T dynamicType(Object dynamicType);
/**
* Sets initial shape flags (default: 0). Currently limited to 8 bits.
*
* See {@link DynamicObjectLibrary#setShapeFlags(DynamicObject, int)} for more information.
*
* @param flags an int value in the range from 0 to 255 (inclusive)
* @throws IllegalArgumentException if the flags value is not in the supported range
* @since 20.2.0
*/
public abstract T shapeFlags(int flags);
/**
* Adds a property with a constant value to the shape. The key must not be {@code null} and
* must not be equal to any previously added property's key.
*
* @param key the property's key
* @param value the property's value
* @param flags the property's flags
* @throws NullPointerException if the key is {@code null}
* @throws IllegalArgumentException if a property with the key already exists
* @see DynamicObjectLibrary#putConstant(DynamicObject, Object, Object, int)
* @since 20.2.0
*/
public abstract T addConstantProperty(Object key, Object value, int flags);
static Object checkDynamicType(Object dynamicType) {
Objects.requireNonNull(dynamicType, "dynamicType");
return dynamicType;
}
static int checkShapeFlags(int flags) {
if ((flags & ~OBJECT_FLAGS_MASK) != 0) {
throw new IllegalArgumentException("flags must be in the range (0, 255)");
}
return flags;
}
}
/**
* Builder class to construct initial {@link Shape} instances.
*
* The builder instance is not thread-safe and must not be used from multiple threads at the
* same time.
*
* @see Shape#newBuilder()
* @since 20.2.0
*/
@SuppressWarnings("hiding")
public static final class Builder extends AbstractBuilder {
private Class extends DynamicObject> layoutClass = DynamicObject.class;
private Object dynamicType = ObjectType.DEFAULT;
private int shapeFlags;
private boolean shared;
private boolean propertyAssumptions;
private Object sharedData;
private Assumption singleContextAssumption;
private EconomicMap properties;
private EnumSet allowedImplicitCasts = EnumSet.noneOf(ImplicitCast.class);
Builder() {
}
/**
* Sets custom object layout class (default: {@link DynamicObject} base class).
*
* Enables the use of dynamic object fields declared in subclasses using the
* {@code DynamicField} annotation.
*
*
* Examples:
*
*
*
* public class MyObject extends DynamicObject implements TruffleObject {
*
* @DynamicField private Object _obj1;
* @DynamicField private Object _obj2;
* @DynamicField private long _long1;
* @DynamicField private long _long2;
*
* public MyObject(Shape shape) {
* super(shape);
* }
* }
*
*
* Shape myObjShape = Shape.newBuilder().layout(MyObject.class).build();
* MyObject obj = new MyObject(myObjShape);
*
*
*
* @param layoutClass custom object layout class
* @since 20.2.0
*/
public Builder layout(Class extends DynamicObject> layoutClass) {
CompilerAsserts.neverPartOfCompilation();
if (!DynamicObject.class.isAssignableFrom(layoutClass)) {
throw new IllegalArgumentException(String.format("Expected a subclass of %s but got: %s",
DynamicObject.class.getName(), layoutClass.getTypeName()));
}
this.layoutClass = layoutClass;
return this;
}
/**
* {@inheritDoc}
*
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @see DynamicObjectLibrary#getDynamicType(DynamicObject)
* @see DynamicObjectLibrary#setDynamicType(DynamicObject, Object)
* @since 20.2.0
*/
@Override
public Builder dynamicType(Object dynamicType) {
CompilerAsserts.neverPartOfCompilation();
this.dynamicType = checkDynamicType(dynamicType);
return this;
}
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException {@inheritDoc}
* @see DynamicObjectLibrary#getShapeFlags(DynamicObject)
* @see DynamicObjectLibrary#setShapeFlags(DynamicObject, int)
* @since 20.2.0
*/
@Override
public Builder shapeFlags(int flags) {
CompilerAsserts.neverPartOfCompilation();
this.shapeFlags = checkShapeFlags(flags);
return this;
}
/**
* If {@code true}, makes the object shared (default: {@code false}).
*
* @see Shape#isShared()
* @see DynamicObjectLibrary#isShared(DynamicObject)
* @see DynamicObjectLibrary#markShared(DynamicObject)
* @since 20.2.0
*/
public Builder shared(boolean isShared) {
CompilerAsserts.neverPartOfCompilation();
this.shared = isShared;
return this;
}
/**
* If {@code true}, enables the use of {@linkplain Shape#getPropertyAssumption(Object)
* property assumptions} for this object shape and any derived shapes (default:
* {@code false}). Property assumptions allow speculating on select properties being absent
* or stable across shape changes.
*
*
* Use of property assumptions can be beneficial in single-context mode for long-lived
* objects with stable properties but recurrent shape changes due to properties being added
* (e.g. global objects of a context), in which case a shape cache would be unstable while
* the property assumption allows for a stable cache.
*
* @see Shape#getPropertyAssumption(Object)
* @since 20.2.0
*/
public Builder propertyAssumptions(boolean enable) {
CompilerAsserts.neverPartOfCompilation();
this.propertyAssumptions = enable;
return this;
}
/**
* Sets shared data to be associated with the root shape and any derived shapes (e.g. a
* {@code TruffleLanguage} instance). May be null (the default).
*
* @see Shape#getSharedData()
* @since 20.2.0
*/
public Builder sharedData(Object sharedData) {
CompilerAsserts.neverPartOfCompilation();
this.sharedData = sharedData;
return this;
}
/**
* Sets an assumption that allows specializations on constant object instances with this
* shape, as long as the assumption is valid. The assumption should be valid only if code is
* not shared across contexts and invalidated when this is not longer true. The assumption
* may be {@code null} in which case this feature is disabled (the default).
*
* @see #propertyAssumptions(boolean)
* @since 20.2.0
*/
public Builder singleContextAssumption(Assumption assumption) {
CompilerAsserts.neverPartOfCompilation();
this.singleContextAssumption = assumption;
return this;
}
/**
* {@inheritDoc}
*
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @see DynamicObjectLibrary#putConstant(DynamicObject, Object, Object, int)
* @since 20.2.0
*/
@Override
public Builder addConstantProperty(Object key, Object value, int flags) {
CompilerAsserts.neverPartOfCompilation();
Objects.requireNonNull(key, "key");
if (properties == null) {
properties = EconomicMap.create(Equivalence.DEFAULT);
}
if (properties.containsKey(key)) {
throw new IllegalArgumentException(String.format("Property already exists: %s.", key));
}
Layout layout = Layout.newLayout().type(DynamicObject.class).build();
Location location = layout.createAllocator().constantLocation(value);
properties.put(key, Property.create(key, location, flags));
return this;
}
/**
* Allows values to be implicitly cast from int to long in this shape and any derived
* shapes.
*
* @see #layout(Class)
* @since 20.2.0
*/
public Builder allowImplicitCastIntToLong(boolean allow) {
if (allow) {
this.allowedImplicitCasts.add(Layout.ImplicitCast.IntToLong);
} else {
this.allowedImplicitCasts.remove(Layout.ImplicitCast.IntToLong);
}
return this;
}
/**
* Allows values to be implicitly cast from int to double in this shape and any derived
* shapes.
*
* @see #layout(Class)
* @since 20.2.0
*/
public Builder allowImplicitCastIntToDouble(boolean allow) {
if (allow) {
this.allowedImplicitCasts.add(Layout.ImplicitCast.IntToDouble);
} else {
this.allowedImplicitCasts.remove(Layout.ImplicitCast.IntToDouble);
}
return this;
}
/**
* Builds a new shape using the configuration of this builder.
*
* @since 20.2.0
*/
public Shape build() {
CompilerAsserts.neverPartOfCompilation();
int flags = shapeFlags;
if (shared) {
flags = shapeFlags | OBJECT_SHARED;
}
if (propertyAssumptions) {
flags = shapeFlags | OBJECT_PROPERTY_ASSUMPTIONS;
}
Layout layout = Layout.newLayout().type(layoutClass).setAllowedImplicitCasts(allowedImplicitCasts).build();
Shape shape = layout.buildShape(dynamicType, sharedData, flags, singleContextAssumption);
if (properties != null) {
for (Property property : properties.getValues()) {
shape = shape.addProperty(property);
}
}
assert shape.isShared() == shared && shape.getFlags() == shapeFlags && shape.getDynamicType() == dynamicType;
return shape;
}
}
/**
* Creates a new derived shape builder that allows changing a root shape's flags and dynamic
* type and adding constant properties.
*
* The builder instance is not thread-safe and must not be used from multiple threads at the
* same time.
*
* @param baseShape the shape to be modified
* @see Shape#newBuilder()
* @since 20.2.0
*/
public static DerivedBuilder newBuilder(Shape baseShape) {
CompilerAsserts.neverPartOfCompilation();
return new DerivedBuilder(baseShape);
}
/**
* Builder class to construct derived {@link Shape} instances.
*
* The builder instance is not thread-safe and must not be used from multiple threads at the
* same time.
*
* @see Shape#newBuilder(Shape)
* @since 20.2.0
*/
@SuppressWarnings("hiding")
public static final class DerivedBuilder extends AbstractBuilder {
private final Shape baseShape;
private Object dynamicType;
private int shapeFlags;
private EconomicMap properties;
DerivedBuilder(Shape baseShape) {
this.baseShape = baseShape;
this.dynamicType = baseShape.getDynamicType();
this.shapeFlags = baseShape.getFlags();
}
/**
* {@inheritDoc}
*
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @see DynamicObjectLibrary#getDynamicType(DynamicObject)
* @see DynamicObjectLibrary#setDynamicType(DynamicObject, Object)
* @since 20.2.0
*/
@Override
public DerivedBuilder dynamicType(Object dynamicType) {
CompilerAsserts.neverPartOfCompilation();
this.dynamicType = checkDynamicType(dynamicType);
return this;
}
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException {@inheritDoc}
* @see DynamicObjectLibrary#getShapeFlags(DynamicObject)
* @see DynamicObjectLibrary#setShapeFlags(DynamicObject, int)
* @since 20.2.0
*/
@Override
public DerivedBuilder shapeFlags(int flags) {
CompilerAsserts.neverPartOfCompilation();
this.shapeFlags = checkShapeFlags(flags);
return this;
}
/**
* {@inheritDoc}
*
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @see DynamicObjectLibrary#putConstant(DynamicObject, Object, Object, int)
* @since 20.2.0
*/
@Override
public DerivedBuilder addConstantProperty(Object key, Object value, int flags) {
CompilerAsserts.neverPartOfCompilation();
Objects.requireNonNull(key, "key");
if (properties == null) {
properties = EconomicMap.create(Equivalence.DEFAULT);
}
if (baseShape.getProperty(key) != null || properties.containsKey(key)) {
throw new IllegalArgumentException(String.format("Property already exists: %s.", key));
}
Location location = baseShape.allocator().constantLocation(value);
properties.put(key, Property.create(key, location, flags));
return this;
}
/**
* Builds a derived shape from the base shape supplied to the constructor using the
* configuration of this builder.
*
* @return a new or cached shape
* @since 20.2.0
*/
public Shape build() {
CompilerAsserts.neverPartOfCompilation();
Shape derivedShape = baseShape;
if (dynamicType != derivedShape.getDynamicType()) {
derivedShape = derivedShape.setDynamicType(dynamicType);
}
if (shapeFlags != derivedShape.getFlags()) {
derivedShape = derivedShape.setFlags(shapeFlags);
}
if (properties != null) {
for (Property property : properties.getValues()) {
derivedShape = derivedShape.addProperty(property);
}
}
return derivedShape;
}
}
/**
* Constructor for subclasses.
*
* @since 0.8 or earlier
*/
protected Shape() {
}
/**
* Get a property entry by key.
*
* @param key the identifier to look up
* @return a Property object, or {@code null} if not found
* @since 0.8 or earlier
*/
public abstract Property getProperty(Object key);
/**
* Add a new property in the map, yielding a new or cached Shape object.
*
* Planned to be deprecated. Use {@link DynamicObjectLibrary#put} or
* {@link DynamicObjectLibrary#putWithFlags} to add properties to an object.
*
* @param property the property to add
* @return the new Shape
* @since 0.8 or earlier
*/
public abstract Shape addProperty(Property property);
/**
* Add or change property in the map, yielding a new or cached Shape object.
*
* Planned to be deprecated. Use {@link DynamicObjectLibrary#put} or
* {@link DynamicObjectLibrary#putWithFlags} to add properties to an object.
*
* @return the shape after defining the property
* @since 0.8 or earlier
*/
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
* @since 0.8 or earlier
* @deprecated Use {@link #defineProperty(Object, Object, int)} or
* {@link DynamicObjectLibrary#put(DynamicObject, Object, Object)} or
* {@link DynamicObjectLibrary#putWithFlags(DynamicObject, Object, Object, int)} or
* {@link DynamicObjectLibrary#putConstant(DynamicObject, Object, Object, int)}
*/
@Deprecated
public abstract Shape defineProperty(Object key, Object value, int flags, LocationFactory locationFactory);
/**
* An {@link Iterable} over the shape's properties in insertion order.
*
* @since 0.8 or earlier
*/
public abstract Iterable getProperties();
/**
* Get a list of properties that this Shape stores.
*
* @return list of properties
* @since 0.8 or earlier
* @deprecated use {@link #getPropertyList()} instead
*/
@Deprecated
public abstract List getPropertyList(Pred filter);
/**
* Get a list of all properties that this Shape stores.
*
* Properties with a {@link HiddenKey} are not included.
*
* @return list of properties
* @since 0.8 or earlier
*/
public abstract List getPropertyList();
/**
* Returns all (also hidden) property objects in this shape.
*
* @param ascending desired order ({@code true} for insertion order, {@code false} for reverse
* insertion order)
* @since 0.8 or earlier
*/
public abstract List getPropertyListInternal(boolean ascending);
/**
* Get a filtered list of property keys in insertion order.
*
* @since 0.8 or earlier
* @deprecated use {@link #getKeyList()} instead
*/
@Deprecated
public abstract List getKeyList(Pred filter);
/**
* Get a list of all property keys in insertion order.
*
*
* Properties with a {@link HiddenKey} are not included.
*
* @since 0.8 or earlier
*/
public abstract List getKeyList();
/**
* Get all property keys in insertion order.
*
* @since 0.8 or earlier
*/
public abstract Iterable getKeys();
/**
* Get an assumption that the shape is valid.
*
* @since 0.8 or earlier
*/
public abstract Assumption getValidAssumption();
/**
* Check whether this shape is valid.
*
* @since 0.8 or earlier
*/
public abstract boolean isValid();
/**
* Get an assumption that the shape is a leaf.
*
* @since 0.8 or earlier
*/
public abstract Assumption getLeafAssumption();
/**
* Check whether this shape is a leaf in the transition graph, i.e. transitionless.
*
* @since 0.8 or earlier
*/
public abstract boolean isLeaf();
/**
* @return the parent shape or {@code null} if none.
* @since 0.8 or earlier
* @deprecated no replacement, do not rely on a specific parent shape
*/
@Deprecated
public abstract Shape getParent();
/**
* Check whether the shape has a property with the given key.
*
* @since 0.8 or earlier
*/
public abstract boolean hasProperty(Object key);
/**
* Remove the given property from the shape.
*
* @since 0.8 or earlier
* @deprecated Use {@link DynamicObjectLibrary#removeKey} to remove properties from an object.
*/
@Deprecated
public abstract Shape removeProperty(Property property);
/**
* Replace a property in the shape.
*
* @since 0.8 or earlier
* @deprecated Use {@link DynamicObjectLibrary#put} to replace properties in an object.
*/
@Deprecated
public abstract Shape replaceProperty(Property oldProperty, Property newProperty);
/**
* Get the last property.
*
* @since 0.8 or earlier
*/
public abstract Property getLastProperty();
/**
* @see #getFlags()
* @since 0.8 or earlier
* @deprecated no replacement, returns 0
*/
@Deprecated
public abstract int getId();
/**
* Returns the language-specific shape flags previously set using
* {@link DynamicObjectLibrary#setShapeFlags(DynamicObject, int)} or
* {@link Shape.Builder#shapeFlags(int)}. If no shape flags were explicitly set, the default of
* 0 is returned.
*
* These flags may be used to tag objects that possess characteristics that need to be queried
* efficiently on fast and slow paths. For example, they can be used to mark objects as frozen.
*
* @see DynamicObjectLibrary#getShapeFlags(DynamicObject)
* @see DynamicObjectLibrary#setShapeFlags(DynamicObject, int)
* @see Shape.Builder#shapeFlags(int)
* @since 20.2.0
*/
public int getFlags() {
CompilerAsserts.neverPartOfCompilation();
throw CompilerDirectives.shouldNotReachHere();
}
/**
* Returns a copy of the shape, with the shape flags set to {@code newFlags}.
*
* @param newFlags the new shape flags; an int value in the range from 0 to 255 (inclusive)
* @throws IllegalArgumentException if the flags value is not in the supported range
* @see Shape.Builder#shapeFlags(int)
* @since 20.2.0
*/
protected Shape setFlags(int newFlags) {
CompilerAsserts.neverPartOfCompilation();
throw CompilerDirectives.shouldNotReachHere();
}
/**
* Append the property, relocating it to the next allocated location.
*
* @since 0.8 or earlier
* @deprecated no replacement
*/
@Deprecated
public abstract Shape append(Property oldProperty);
/**
* Obtain an {@link Allocator} instance for the purpose of allocating locations.
*
* @since 0.8 or earlier
*/
public abstract Allocator allocator();
/**
* Returns the number of properties in this shape.
*
* @since 0.8 or earlier
*/
public abstract int getPropertyCount();
/**
* Get the shape's object type info.
*
* @since 0.8 or earlier
* @see #getDynamicType()
* @deprecated Deprecated since 20.3.0. Replaced by {@link #getDynamicType()}.
*/
@Deprecated
public abstract ObjectType getObjectType();
/**
* Get the shape's dynamic object type identifier.
*
* @since 20.2.0
*/
public Object getDynamicType() {
CompilerAsserts.neverPartOfCompilation();
throw CompilerDirectives.shouldNotReachHere();
}
/**
* Returns a copy of the shape, with the dynamic object type identifier set to
* {@code objectType}. Currently, the object type must be an instance of {@link ObjectType}.
*
* @param objectType the new dynamic object type identifier
* @throws IllegalArgumentException if the type is not an instance of {@link ObjectType}
* @see Shape.Builder#dynamicType(Object)
* @since 20.2.0
*/
protected Shape setDynamicType(Object objectType) {
CompilerAsserts.neverPartOfCompilation();
throw CompilerDirectives.shouldNotReachHere();
}
/**
* Get the root shape.
*
* Planned to be deprecated.
*
* @since 0.8 or earlier
*/
public abstract Shape getRoot();
/**
* Checks whether the given object's shape is identical to this shape.
*
* @since 0.8 or earlier
*/
public abstract boolean check(DynamicObject subject);
/**
* Get the shape's layout.
*
* @see Shape.Builder#layout(Class)
* @since 0.8 or earlier
*/
public abstract Layout getLayout();
/**
* Get the shape's shared data.
*
* @see Shape.Builder#sharedData(Object)
* @since 0.8 or earlier
*/
public abstract Object getSharedData();
/**
* Query whether the shape has a transition with the given key.
*
* @since 0.8 or earlier
* @deprecated the result of this method may change at any time
*/
@Deprecated
public abstract boolean hasTransitionWithKey(Object key);
/**
* Clone off a separate shape with new shared data.
*
* @since 0.8 or earlier
* @deprecated no replacement
*/
@Deprecated
public abstract Shape createSeparateShape(Object sharedData);
/**
* Change the shape's type, yielding a new shape.
*
* Planned to be deprecated. To be replaced by {@link #setDynamicType(Object)}.
*
* @since 0.8 or earlier
*/
public abstract Shape changeType(ObjectType newOps);
/**
* Reserve the primitive extension array field.
*
* @since 0.8 or earlier
* @deprecated It is unnecessary to call this method, it has no effect and always returns this.
*/
@Deprecated
public abstract Shape reservePrimitiveExtensionArray();
/**
* Create a new {@link DynamicObject} instance with this shape.
*
* @throws UnsupportedOperationException if this layout does not support construction
* @since 0.8 or earlier
*/
public abstract DynamicObject newInstance();
/**
* Create a {@link DynamicObjectFactory} for creating instances of this shape.
*
* @throws UnsupportedOperationException if this layout does not support construction
* @since 0.8 or earlier
*/
public abstract DynamicObjectFactory createFactory();
/**
* Get mutex object shared by related shapes, i.e. shapes with a common root.
*
* Planned to be deprecated.
*
* @since 0.8 or earlier
*/
public abstract Object getMutex();
/**
* Are these two shapes related, i.e. do they have the same root?
*
* @param other Shape to compare to
* @return true if one shape is an upcast of the other, or the Shapes are equal
* @since 0.8 or earlier
* @deprecated no replacement
*/
@Deprecated
public abstract boolean isRelated(Shape other);
/**
* Try to merge two related shapes to a more general shape that has the same properties and can
* store at least the values of both shapes.
*
* @return this, other, or a new shape that is compatible with both shapes
* @since 0.8 or earlier
*/
public abstract Shape tryMerge(Shape other);
/**
* Returns {@code true} if this shape is {@link Shape#makeSharedShape() shared}.
*
* @see DynamicObjectLibrary#isShared(DynamicObject)
* @see DynamicObjectLibrary#markShared(DynamicObject)
* @see Shape.Builder#shared(boolean)
* @since 0.18
*/
public boolean isShared() {
return false;
}
/**
* Make a shared variant of this shape, to allow safe usage of this object between threads.
* Shared shapes will not reuse storage locations for other fields. In combination with careful
* synchronization on writes, this can prevent reading out-of-thin-air values.
*
* @return a cached and shared variant of this shape
* @see #isShared()
* @see DynamicObjectLibrary#markShared(DynamicObject)
* @since 0.18
*/
public Shape makeSharedShape() {
CompilerAsserts.neverPartOfCompilation();
throw CompilerDirectives.shouldNotReachHere();
}
/**
* Returns {@code true} if this shape has instance properties (i.e., stored in the object).
*
* @since 20.2.0
*/
protected boolean hasInstanceProperties() {
return true;
}
/**
* Gets a stable property assumption for the given property key. May be invalid. If a valid
* assumption is returned, it may be used to assume this particular property is still absent or
* present at the current storage location in objects of this shape. The assumption is
* invalidated if a shape change is triggered because of a property with the given key was
* added, removed, or changed, or a {@link DynamicObjectLibrary#resetShape resetShape}.
*
*
* Only applicable if {@linkplain Builder#propertyAssumptions(boolean) property assumptions} are
* enabled for this shape, otherwise always returns an invalid assumption.
*
* @param key the property key of interest
* @return an assumption that the property is stable or an invalid assumption
* @see Shape.Builder#propertyAssumptions(boolean)
* @since 20.2.0
*/
public Assumption getPropertyAssumption(Object key) {
return NeverValidAssumption.INSTANCE;
}
/**
* Tests if all properties in the shape match the provided predicate. May not evaluate the
* predicate on all properties if a predicate did not match. If the shape does not contain any
* properties, returns {@code true} and does not evaluate the predicate.
*
* @return {@code true} if the all properties match the predicate, else {@code false}
* @since 20.2.0
*/
public boolean allPropertiesMatch(@SuppressWarnings("unused") Predicate predicate) {
CompilerAsserts.neverPartOfCompilation();
throw CompilerDirectives.shouldNotReachHere();
}
/**
* Utility class to allocate locations in an object layout.
*
* Planned to be deprecated.
*
* @since 0.8 or earlier
*/
public abstract static class Allocator {
/**
* @since 0.8 or earlier
*/
protected Allocator() {
}
/** @since 0.8 or earlier */
@Deprecated
protected abstract Location locationForValue(Object value, boolean useFinal, boolean nonNull);
/**
* Create a new location compatible with the given initial value.
*
* Use {@link #locationForType(Class)} or {@link Shape#defineProperty(Object, Object, int)}
* instead.
*
* @param value the initial value this location is going to be assigned
* @since 0.8 or earlier
*/
@Deprecated
public final Location locationForValue(Object value) {
return locationForValue(value, false, value != null);
}
/**
* Create a new location compatible with the given initial value.
*
* @param value the initial value this location is going to be assigned
* @param modifiers additional restrictions and semantics
* @since 0.8 or earlier
* @deprecated use {@link #locationForType(Class, EnumSet)} or
* {@link Shape#defineProperty(Object, Object, int)} instead
*/
@Deprecated
public final Location locationForValue(Object value, EnumSet modifiers) {
assert value != null || !modifiers.contains(LocationModifier.NonNull);
return locationForValue(value, modifiers.contains(LocationModifier.Final), modifiers.contains(LocationModifier.NonNull));
}
/** @since 0.8 or earlier */
protected abstract Location locationForType(Class> type, boolean useFinal, boolean nonNull);
/**
* Create a new location for a fixed type. It can only be assigned to values of this type.
*
* @param type the Java type this location must be compatible with (may be primitive)
* @since 0.8 or earlier
*/
public final Location locationForType(Class> type) {
return locationForType(type, false, false);
}
/**
* Create a new location for a fixed type.
*
* @param type the Java type this location must be compatible with (may be primitive)
* @param modifiers additional restrictions and semantics
* @since 0.8 or earlier
*/
public final Location locationForType(Class> type, EnumSet modifiers) {
return locationForType(type, modifiers.contains(LocationModifier.Final), modifiers.contains(LocationModifier.NonNull));
}
/**
* Creates a new location from a constant value. The value is stored in the shape rather
* than in the object.
*
* @since 0.8 or earlier
*/
public abstract Location constantLocation(Object value);
/**
* Creates a new declared location with a default value. A declared location only assumes a
* type after the first set (initialization).
*
* @since 0.8 or earlier
*/
public abstract Location declaredLocation(Object value);
/**
* Reserves space for the given location, so that it will not be available to subsequently
* allocated locations.
*
* @since 0.8 or earlier
*/
public abstract Allocator addLocation(Location location);
/**
* Creates an copy of this allocator state.
*
* @since 0.8 or earlier
*/
public abstract Allocator copy();
}
/**
* Represents a predicate (boolean-valued function) of one argument.
*
* For Java 7 compatibility (equivalent to Predicate).
*
* @param the type of the input to the predicate
* @since 0.8 or earlier
* @deprecated all methods that use this interface are deprecated; use
* {@link java.util.function.Predicate} instead.
*/
@Deprecated
public interface Pred {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate, otherwise {@code false}
* @since 0.8 or earlier
*/
boolean test(T t);
}
}