Class DynamicObject
java.lang.Object
com.oracle.truffle.api.object.DynamicObject
- All Implemented Interfaces:
TruffleObject
Represents a dynamic object, members of which can be dynamically added and removed at run time.
To use it, extend
Simple use of
Member name equality check omitted for brevity.
DynamicObject and use nodes nested under DynamicObject such as
DynamicObject.GetNode for object accesses.
When constructing a DynamicObject, it has
to be initialized with an empty initial shape. Initial shapes are created using
Shape.newBuilder() and should ideally be shared per TruffleLanguage instance to
allow shape caches to be shared across contexts.
Subclasses can provide in-object dynamic field slots using the DynamicObject.DynamicField annotation
and Shape.Builder.layout.
Example:
public class MyObject extends DynamicObject implements TruffleObject {
MyObject(Shape shape) {
super(shape);
}
static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
}
public abstract class MyTruffleLanguage extends TruffleLanguage<MyContext> {
final Shape initialShape = Shape.newBuilder().build();
public MyObject newObject() {
return new MyObject(initialShape);
}
}
Using DynamicObject nodes
DynamicObject nodes is the central interface for accessing and mutating properties and other state (flags, dynamic type) ofDynamicObjects. All nodes provide cached and uncached
variants.
Note: Property keys are always compared using object identity (==), never with
equals, for efficiency reasons. If the node is not used with a fixed key, and some keys might be
equals but not have the same identity (==), you must either intern the keys
first, or cache the key by equality using an inline cache and use the cached key with the
DynamicObject node to ensure equal keys with different identity will use the same cache entry and
not overflow the cache:
abstract static class GetStringKeyNode extends Node {
abstract Object execute(DynamicObject receiver, Object key);
@Specialization(guards = "equalNode.execute(key, cachedKey, UTF_16)", limit = "3")
static Object doCached(MyDynamicObjectSubclass receiver, TruffleString key,
@Cached("key") TruffleString cachedKey,
@Cached TruffleString.EqualNode equalNode,
@Cached DynamicObject.GetNode getNode) {
return getNode.execute(receiver, cachedKey, NULL_VALUE);
}
}
Usage examples:
Simple use of DynamicObject.GetNode with a pre-interned symbol key.
abstract static class GetSimpleNode extends Node {
abstract Object execute(DynamicObject receiver, Object key);
@Specialization
static Object doCached(MyDynamicObjectSubclass receiver, Symbol key,
@Cached DynamicObject.GetNode getNode) {
return getNode.execute(receiver, key, NULL_VALUE);
}
}
Implementing InteropLibrary messages using DynamicObject access nodes:
@ExportLibrary(InteropLibrary.class)
static class MyDynamicObjectSubclass extends DynamicObject {
MyDynamicObjectSubclass(Shape shape) {
super(shape);
}
@ExportMessage
Object readMember(String member,
@Cached DynamicObject.GetNode getNode) throws UnknownIdentifierException {
Object result = getNode.execute(this, member, null);
if (result == null) {
throw UnknownIdentifierException.create(member);
}
return result;
}
Adding extra dynamic fields to a DynamicObject subclass:
public class MyObjectWithFields extends DynamicObject implements TruffleObject {
@DynamicField private Object extra1;
@DynamicField private Object extra2;
@DynamicField private long extraLong1;
@DynamicField private long extraLong2;
MyObjectWithFields(Shape shape) {
super(shape);
}
static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
}
Shape initialShape = Shape.newBuilder().layout(MyObject.class, MyObject.LOOKUP).build();
MyObject obj = new MyObject(initialShape);
- Since:
- 0.8 or earlier
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classChecks if this object contains a property with the given key.static classCopies all properties of a DynamicObject to another, preserving property flags.protected static @interfaceUsing this annotation, subclasses can define additional dynamic fields to be used by the object layout.static classGets the language-specific dynamic type identifier currently associated with this object.static classGets a snapshot of the object's property keys, in insertion order.static classGets the value of a property or returns a default value if no such property exists.static classGets a snapshot of the object's properties, in insertion order.static classGets the property flags associated with the requested property key.static classGets a property descriptor for the requested property key ornullif no such property exists.static classGets the language-specific object shape flags.static classChecks whether this object is marked as shared.static classMarks this object as shared.static classAdds or sets multiple properties in bulk.static classSets the value of an existing property or adds a new property if no such property exists.static classSets the value of an existing property or adds a new property if no such property exists.static classRemoves the property with the given key from the object.static classEmpties and resets the object to the given root shape.static classSets the language-specific dynamic type identifier.static classSets or updates property flags associated with the requested property key.static classSets or updates language-specific object shape flags.static classEnsures the object's shape is up-to-date. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedDynamicObject(Shape shape) Constructor forDynamicObjectsubclasses. -
Method Summary
Modifier and TypeMethodDescriptionprotected Objectclone()Theclone()method is not supported byDynamicObjectat this point in time, so it always throwsCloneNotSupportedException, even if theCloneableinterface is implemented in a subclass.final ShapegetShape()Get the object's current shape.
-
Constructor Details
-
DynamicObject
Constructor forDynamicObjectsubclasses. Initializes the object with the provided shape. The shape must have been constructed with a layout class assignable from this class (i.e., the concrete subclass, a superclass thereof, includingDynamicObject) and must not have any instance properties (but may have constant properties).Examples:
Shape shape =
Shape.newBuilder().build(); DynamicObject myObject = new MyObject(shape);Shape shape =
Shape.newBuilder().layout(MyObject.class, MethodHandles.lookup()).build(); DynamicObject myObject = new MyObject(shape);- Parameters:
shape- the initial shape of this object- Throws:
IllegalArgumentException- if called with an illegal (incompatible) shape- Since:
- 19.0
-
-
Method Details
-
getShape
-
clone
Theclone()method is not supported byDynamicObjectat this point in time, so it always throwsCloneNotSupportedException, even if theCloneableinterface is implemented in a subclass. Subclasses may however override this method and create a copy of this object by constructing a new object and copying any properties over manually.- Overrides:
clonein classObject- Throws:
CloneNotSupportedException- Since:
- 20.2.0
-