public abstract class DynamicObjectLibrary extends Library
DynamicObject
access library.
This is the central interface for accessing and mutating properties and other state (flags,
dynamic type) of DynamicObject
s.
It is recommended that you use the CachedLibrary
annotation in Truffle DSL nodes. You can
also use the library either without caching or create a
manually or
automatically dispatched cached library. Cached
libraries must be adopted before use.
The cached library instances dispatch by object shape and, if applicable,
automatically by property key.
Property keys are compared using object identity (==
) first and then
Object.equals(Object)
. It is therefore recommended to use the same string/key instances
for each access of the property in order to avoid pulling in equals
. Keys must not be
null
.
Note: cached library nodes may not profile the class of the object parameter; it is therefore the caller's responsibility to do any desired profiling and ensure accurate type information.
@Specialization(limit = "3") static Object read(DynamicObject receiver, Object key, @CachedLibrary("receiver") DynamicObjectLibrary objLib) { return objLib.getOrDefault(receiver, key, NULL_VALUE); }
@ExportMessage Object readMember(String name, @CachedLibrary("this") DynamicObjectLibrary objLib) throws UnknownIdentifierException { Object result = objLib.getOrDefault(this, name, null); if (result == null) { throw UnknownIdentifierException.create(name); } return result; }
Node.Child, Node.Children
Modifier | Constructor and Description |
---|---|
protected |
DynamicObjectLibrary() |
Modifier and Type | Method and Description |
---|---|
abstract boolean |
containsKey(DynamicObject object,
Object key)
Returns
true if this object contains a property with the given key. |
double |
getDoubleOrDefault(DynamicObject object,
Object key,
Object defaultValue)
Gets the value of an existing property or returns the provided default value if no such
property exists.
|
abstract Object |
getDynamicType(DynamicObject object)
Gets the dynamic type identifier currently associated with this object.
|
static LibraryFactory<DynamicObjectLibrary> |
getFactory()
Returns the library factory for
DynamicObjectLibrary . |
int |
getIntOrDefault(DynamicObject object,
Object key,
Object defaultValue)
Gets the value of an existing property or returns the provided default value if no such
property exists.
|
abstract Object[] |
getKeyArray(DynamicObject object)
Gets a snapshot of the object's property keys, in insertion order.
|
long |
getLongOrDefault(DynamicObject object,
Object key,
Object defaultValue)
Gets the value of an existing property or returns the provided default value if no such
property exists.
|
abstract Object |
getOrDefault(DynamicObject object,
Object key,
Object defaultValue)
Gets the value of an existing property or returns the provided default value if no such
property exists.
|
abstract Property |
getProperty(DynamicObject object,
Object key)
Gets a property descriptor for the requested property key.
|
abstract Property[] |
getPropertyArray(DynamicObject object)
Gets an array snapshot of the object's properties, in insertion order.
|
int |
getPropertyFlagsOrDefault(DynamicObject object,
Object key,
int defaultValue)
Gets the property flags associated with the requested property key.
|
abstract Shape |
getShape(DynamicObject object)
Gets the
shape of the object. |
abstract int |
getShapeFlags(DynamicObject object)
Gets the language-specific object shape flags previously set using
DynamicObjectLibrary.setShapeFlags(DynamicObject, int) or
Shape.Builder.shapeFlags(int) . |
static DynamicObjectLibrary |
getUncached()
Gets the shared
DynamicObjectLibrary instance for uncached accesses. |
abstract boolean |
isShared(DynamicObject object)
Checks whether this object is marked as shared.
|
abstract void |
markShared(DynamicObject object)
Marks this object as shared.
|
abstract void |
put(DynamicObject object,
Object key,
Object value)
Sets the value of an existing property or adds a new property if no such property exists.
|
abstract void |
putConstant(DynamicObject object,
Object key,
Object value,
int flags)
Adds a property with a constant value or replaces an existing one.
|
void |
putDouble(DynamicObject object,
Object key,
double value)
|
abstract boolean |
putIfPresent(DynamicObject object,
Object key,
Object value)
Sets the value of the property if present, otherwise returns
false . |
void |
putInt(DynamicObject object,
Object key,
int value)
|
void |
putLong(DynamicObject object,
Object key,
long value)
|
abstract void |
putWithFlags(DynamicObject object,
Object key,
Object value,
int flags)
Like
DynamicObjectLibrary.put(com.oracle.truffle.api.object.DynamicObject, java.lang.Object, java.lang.Object) , but additionally assigns flags to the property. |
abstract boolean |
removeKey(DynamicObject object,
Object key)
Removes the property with the given key from the object.
|
abstract boolean |
resetShape(DynamicObject object,
Shape otherShape)
Empties and resets the object to the given root shape, which must not contain any instance
properties (but may contain properties with a constant value).
|
abstract boolean |
setDynamicType(DynamicObject object,
Object type)
Sets the object's dynamic type identifier.
|
abstract boolean |
setPropertyFlags(DynamicObject object,
Object key,
int propertyFlags)
Sets the property flags associated with the requested property.
|
abstract boolean |
setShapeFlags(DynamicObject object,
int flags)
Sets language-specific object shape flags, changing the object's shape if need be.
|
abstract boolean |
updateShape(DynamicObject object)
Ensures the object's shape is up-to-date.
|
accept, adoptChildren, atomic, atomic, copy, deepCopy, getChildren, getCost, getDebugProperties, getDescription, getEncapsulatingSourceSection, getLock, getParent, getRootNode, getSourceSection, insert, insert, isAdoptable, isSafelyReplaceableBy, notifyInserted, onReplace, replace, replace, reportPolymorphicSpecialize, toString
public static LibraryFactory<DynamicObjectLibrary> getFactory()
DynamicObjectLibrary
.public static DynamicObjectLibrary getUncached()
DynamicObjectLibrary
instance for uncached accesses. Equivalent to
DynamicObjectLibrary.getFactory().getUncached()
.public abstract Shape getShape(DynamicObject object)
shape
of the object. Returns the cached shape if the library is a
cached library instance.Shape
DynamicObject.getShape()
public abstract Object getOrDefault(DynamicObject object, Object key, Object defaultValue)
@Specialization(limit = "3") static Object read(DynamicObject receiver, Object key, @CachedLibrary("receiver") DynamicObjectLibrary objLib) { return objLib.getOrDefault(receiver, key, NULL_VALUE); }
key
- the property keydefaultValue
- value to be returned if the property does not existdefaultValue
.public int getIntOrDefault(DynamicObject object, Object key, Object defaultValue) throws UnexpectedResultException
key
- the property keydefaultValue
- the value to be returned if the property does not existdefaultValue
.UnexpectedResultException
- if the (default) value is not an int
DynamicObjectLibrary.getOrDefault(DynamicObject, Object, Object)
public double getDoubleOrDefault(DynamicObject object, Object key, Object defaultValue) throws UnexpectedResultException
key
- the property keydefaultValue
- the value to be returned if the property does not existdefaultValue
.UnexpectedResultException
- if the (default) value is not a double
DynamicObjectLibrary.getOrDefault(DynamicObject, Object, Object)
public long getLongOrDefault(DynamicObject object, Object key, Object defaultValue) throws UnexpectedResultException
key
- the property keydefaultValue
- the value to be returned if the property does not existdefaultValue
.UnexpectedResultException
- if the (default) value is not a long
DynamicObjectLibrary.getOrDefault(DynamicObject, Object, Object)
public abstract void put(DynamicObject object, Object key, Object value)
DynamicObjectLibrary.putWithFlags(com.oracle.truffle.api.object.DynamicObject, java.lang.Object, java.lang.Object, int)
to set property flags as well.
@ExportMessage Object writeMember(String member, Object value, @CachedLibrary("this") DynamicObjectLibrary objLib) { objLib.put(this, member, value); }
key
- the property keyvalue
- the value to be setDynamicObjectLibrary.putInt(DynamicObject, Object, int)
,
DynamicObjectLibrary.putDouble(DynamicObject, Object, double)
,
DynamicObjectLibrary.putLong(DynamicObject, Object, long)
,
DynamicObjectLibrary.putIfPresent(DynamicObject, Object, Object)
,
DynamicObjectLibrary.putWithFlags(DynamicObject, Object, Object, int)
public void putInt(DynamicObject object, Object key, int value)
DynamicObjectLibrary.put(com.oracle.truffle.api.object.DynamicObject, java.lang.Object, java.lang.Object)
.DynamicObjectLibrary.put(DynamicObject, Object, Object)
public void putDouble(DynamicObject object, Object key, double value)
DynamicObjectLibrary.put(com.oracle.truffle.api.object.DynamicObject, java.lang.Object, java.lang.Object)
.DynamicObjectLibrary.put(DynamicObject, Object, Object)
public void putLong(DynamicObject object, Object key, long value)
DynamicObjectLibrary.put(com.oracle.truffle.api.object.DynamicObject, java.lang.Object, java.lang.Object)
.DynamicObjectLibrary.put(DynamicObject, Object, Object)
public abstract boolean putIfPresent(DynamicObject object, Object key, Object value)
false
.key
- property identifiervalue
- value to be settrue
if the property was present and the value set, otherwise false
DynamicObjectLibrary.put(DynamicObject, Object, Object)
public abstract void putWithFlags(DynamicObject object, Object key, Object value, int flags)
DynamicObjectLibrary.put(com.oracle.truffle.api.object.DynamicObject, java.lang.Object, java.lang.Object)
, but additionally assigns flags to the property. If the property already
exists, its flags will be updated before the value is set.key
- property identifiervalue
- value to be setflags
- flags to be setDynamicObjectLibrary.put(DynamicObject, Object, Object)
,
DynamicObjectLibrary.setPropertyFlags(DynamicObject, Object, int)
public abstract void putConstant(DynamicObject object, Object key, Object value, int flags)
Warning: this method will lead to a shape transition every time a new value is set and should be used sparingly (with at most one constant value per property) since it could cause an excessive amount of shapes to be created.
Note: the value will be strongly referenced from the shape and should be a value type or light-weight object without any references to guest language objects in order to prevent potential memory leaks.
// declare property objLib.putConstant(receiver, key, NULL_VALUE, 0); // initialize property objLib.put(receiver, key, value);
key
- property identifiervalue
- the constant value to be setflags
- property flags or 0DynamicObjectLibrary.put(DynamicObject, Object, Object)
public abstract boolean removeKey(DynamicObject object, Object key)
key
- the property keytrue
if the property was removed or false
if property was not foundpublic abstract boolean setDynamicType(DynamicObject object, Object type)
equals
.type
- a non-null type identifier defined by the guest language.true
if the type (and the object's shape) changedIllegalArgumentException
- if the type is not an instance of ObjectType
and the
object has been created with the legacy layout.DynamicObjectLibrary.getDynamicType(DynamicObject)
public abstract Object getDynamicType(DynamicObject object)
DynamicObjectLibrary.setDynamicType(DynamicObject, Object)
,
Shape.getDynamicType()
public abstract boolean containsKey(DynamicObject object, Object key)
true
if this object contains a property with the given key.
@ExportMessage boolean isMemberReadable(String name, @CachedLibrary("this") DynamicObjectLibrary objLib) { return objLib.containsKey(this, name); }
key
- the property keytrue
if the object contains a property with this key, else false
public abstract int getShapeFlags(DynamicObject object)
DynamicObjectLibrary.setShapeFlags(DynamicObject, int)
or
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.
@ExportMessage Object writeMember(String member, Object value, @CachedLibrary("this") DynamicObjectLibrary objLib) throws UnsupportedMessageException { if ((objLib.getShapeFlags(receiver) & FROZEN) != 0) { throw UnsupportedMessageException.create(); } objLib.put(this, member, value); }
DynamicObjectLibrary.setShapeFlags(DynamicObject, int)
,
Shape.Builder.shapeFlags(int)
,
Shape.getFlags()
public abstract boolean setShapeFlags(DynamicObject object, int flags)
@Specialization(limit = "3") static void preventExtensions(DynamicObject receiver, @CachedLibrary("receiver") DynamicObjectLibrary objLib) { objLib.setShapeFlags(receiver, objLib.getShapeFlags(receiver) | FROZEN); }
flags
- the flags to set; must be in the range from 0 to 255 (inclusive).true
if the object's shape changed, false
if no change was made.IllegalArgumentException
- if the flags are not in the allowed range.DynamicObjectLibrary.getShapeFlags(DynamicObject)
,
Shape.Builder.shapeFlags(int)
public abstract Property getProperty(DynamicObject object, Object key)
null
if the object contains no such property.Property
if the property exists, else null
public final int getPropertyFlagsOrDefault(DynamicObject object, Object key, int defaultValue)
defaultValue
if the object contains no such property. If the property exists but no
flags were explicitly set, returns the default of 0.
Convenience method equivalent to:
Property property = getProperty(object, key); return property != null ? property.getFlags() : defaultValue;
key
- the property keydefaultValue
- value to return if no such property existsdefaultValue
DynamicObjectLibrary.getProperty(DynamicObject, Object)
public abstract boolean setPropertyFlags(DynamicObject object, Object key, int propertyFlags)
key
- the property keytrue
if the property was found and its flags were changed, else false
public abstract void markShared(DynamicObject object)
Shape
, to allow safe usage of this
object between threads. Objects with a shared Shape
will not reuse storage locations
for other fields. In combination with careful synchronization on writes, this can prevent
reading out-of-thin-air values.UnsupportedOperationException
- if the object is already shared.DynamicObjectLibrary.isShared(DynamicObject)
public abstract boolean isShared(DynamicObject object)
true
if the object is sharedDynamicObjectLibrary.markShared(DynamicObject)
,
Shape.isShared()
public abstract boolean updateShape(DynamicObject object)
true
if the object's shape was changed, otherwise false
.public abstract boolean resetShape(DynamicObject object, Shape otherShape)
otherShape
- the desired shapetrue
if the object's shape was changedIllegalArgumentException
- if the shape contains instance propertiespublic abstract Object[] getKeyArray(DynamicObject object)
HiddenKey
are not included.
@ExportMessage Object getMembers( @CachedLibrary("this") DynamicObjectLibrary objLib) { return new Keys(objLib.getKeyArray(this)); } @ExportLibrary(InteropLibrary.class) static final class Keys implements TruffleObject { @CompilationFinal(dimensions = 1) final Object[] keys; Keys(Object[] keys) { this.keys = keys; } @ExportMessage boolean hasArrayElements() { return true; } @ExportMessage Object readArrayElement(long index) throws InvalidArrayIndexException { if (!isArrayElementReadable(index)) { throw InvalidArrayIndexException.create(index); } return keys[(int) index]; } @ExportMessage long getArraySize() { return keys.length; } @ExportMessage boolean isArrayElementReadable(long index) { return index >= 0 && index < keys.length; } }
public abstract Property[] getPropertyArray(DynamicObject object)
HiddenKey
are not included.
Similar to DynamicObjectLibrary.getKeyArray(com.oracle.truffle.api.object.DynamicObject)
but allows the properties' flags to be queried simultaneously
which may be relevant for quick filtering.DynamicObjectLibrary.getKeyArray(DynamicObject)