com.oracle.truffle.api.interop.ForeignAccess Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of truffle-api Show documentation
Show all versions of truffle-api Show documentation
Truffle is a multi-language framework for executing dynamic languages
that achieves high performance when combined with Graal.
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.interop;
import java.util.List;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.impl.ReadOnlyArrayList;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
/**
* Encapsulates types of access to {@link TruffleObject}. If you want to expose your own objects to
* foreign language implementations, you need to implement {@link TruffleObject} and its
* {@link TruffleObject#getForeignAccess()} method. To create instance of ForeignAccess
* , use one of the factory methods available in this class.
*
* @since 0.8 or earlier
*/
public final class ForeignAccess {
private final Factory factory;
private final RootNode languageCheck;
// still here for GraalVM intrinsics.
@SuppressWarnings("unused") private final Thread initThread;
private ForeignAccess(Factory faf) {
this(null, faf);
}
private ForeignAccess(RootNode languageCheck, Factory faf) {
this.factory = faf;
this.initThread = null;
this.languageCheck = languageCheck;
CompilerAsserts.neverPartOfCompilation("do not create a ForeignAccess object from compiled code");
}
/**
* Creates new instance of {@link ForeignAccess} that delegates to provided factory.
*
* @param baseClass the super class of all {@link TruffleObject}s handled by this factory (if
* null
then the second interface must also implement {@link Factory})
* @param factory the factory that handles access requests to {@link Message}s
* @return new instance wrapping factory
* @since 0.30
*/
public static ForeignAccess create(final Class extends TruffleObject> baseClass, final StandardFactory factory) {
if (baseClass == null) {
Factory f = (Factory) factory;
assert f != null;
}
return new ForeignAccess(new DelegatingFactory(baseClass, factory));
}
/**
* Creates new instance of {@link ForeignAccess} that delegates to provided factory.
*
* @param baseClass the super class of all {@link TruffleObject}s handled by this factory (if
* null
then the second interface must also implement {@link Factory})
* @param factory the factory that handles access requests to {@link Message}s known as of
* version 0.26
* @return new instance wrapping factory
* @since 0.26
* @deprecated Use {@link StandardFactory} and
* {@link #create(java.lang.Class, com.oracle.truffle.api.interop.ForeignAccess.StandardFactory)}
*/
@Deprecated
public static ForeignAccess create(final Class extends TruffleObject> baseClass, final Factory26 factory) {
if (baseClass == null) {
Factory f = (Factory) factory;
assert f != null;
}
return new ForeignAccess(new DelegatingFactory26(baseClass, factory));
}
/**
* Creates new instance of {@link ForeignAccess} that delegates to provided factory.
*
* @param factory the factory that handles access requests to {@link Message}s
* @param languageCheck a {@link RootNode} that performs the language check on receiver objects,
* can be null
, but then the factory must also implement {@link Factory}
* interface
* @return new instance wrapping factory
* @since 0.30
*/
public static ForeignAccess create(final StandardFactory factory, final RootNode languageCheck) {
if (languageCheck == null) {
Factory f = (Factory) factory;
assert f != null;
}
return new ForeignAccess(languageCheck, new DelegatingFactory(null, factory));
}
/**
* Creates new instance of {@link ForeignAccess} that delegates to provided factory.
*
* @param factory the factory that handles access requests to {@link Message}s known as of
* version 0.26
* @param languageCheck a {@link RootNode} that performs the language check on receiver objects,
* can be null
, but then the factory must also implement {@link Factory}
* interface
* @return new instance wrapping factory
* @since 0.26
* @deprecated Use {@link StandardFactory} and
* {@link #create(com.oracle.truffle.api.interop.ForeignAccess.StandardFactory, com.oracle.truffle.api.nodes.RootNode)
* its associated factory} method
*/
@Deprecated
public static ForeignAccess create(final Factory26 factory, final RootNode languageCheck) {
if (languageCheck == null) {
Factory f = (Factory) factory;
assert f != null;
}
return new ForeignAccess(languageCheck, new DelegatingFactory26(null, factory));
}
/**
* Creates new instance of {@link ForeignAccess} that delegates to provided factory.
*
* @param factory the factory that handles various access requests {@link Message}s.
* @return new instance wrapping factory
* @since 0.8 or earlier
*/
public static ForeignAccess create(Factory factory) {
return new ForeignAccess(factory);
}
/**
* Executes {@link Message#createNode() foreign node}.
*
* @deprecated replaced by specialized methods for sending individual messages (e.g.
* {@link #sendRead(Node, VirtualFrame, TruffleObject, Object)}). For sending any
* message use the rare {@link #send(Node, VirtualFrame, TruffleObject, Object...)}
* method.
*
* @param foreignNode the createNode created by {@link Message#createNode()}
* @param frame the call frame
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param arguments parameters for the receiver
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws IllegalStateException if any error occurred while accessing the receiver
* object
* @since 0.8 or earlier
*/
@SuppressWarnings("deprecation")
@Deprecated
public static Object execute(Node foreignNode, VirtualFrame frame, TruffleObject receiver, Object... arguments) {
return ((InteropAccessNode) foreignNode).executeOld(receiver, arguments);
}
/**
* Sends a {@link Message} to the foreign receiver object by executing the
* {@link Message#createNode() foreign node}.
*
* @param foreignNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param arguments parameters for the receiver
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws InteropException if any error occurred while accessing the receiver
* object
* @since 0.24
*/
public static Object send(Node foreignNode, TruffleObject receiver, Object... arguments) throws InteropException {
try {
return ((InteropAccessNode) foreignNode).execute(receiver, arguments);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw e;
}
}
/**
* Sends a {@link Message#READ READ message} to the foreign receiver object by executing the
* readNode
.
*
* @param readNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param identifier name of the property to be read
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by readNode
* @throws UnknownIdentifierException if the receiver
does not allow reading a
* property for the given identifier
* @since 0.24
*/
public static Object sendRead(Node readNode, TruffleObject receiver, Object identifier) throws UnknownIdentifierException, UnsupportedMessageException {
try {
return ((InteropAccessNode) readNode).execute(receiver, identifier);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (UnknownIdentifierException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends a {@link Message#WRITE WRITE message} to the foreign receiver object by executing the
* writeNode
.
*
* @param writeNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param identifier name of the property to be written
* @param value value to be written
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by writeNode
* @throws UnknownIdentifierException if the receiver
does not allow writing a
* property for the given identifier
* @throws UnsupportedTypeException if value
has an unsupported type
* @since 0.24
*/
public static Object sendWrite(Node writeNode, TruffleObject receiver, Object identifier, Object value)
throws UnknownIdentifierException, UnsupportedTypeException, UnsupportedMessageException {
try {
return ((InteropAccessNode) writeNode).execute(receiver, identifier, value);
} catch (UnknownIdentifierException | UnsupportedTypeException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends a {@link Message#REMOVE REMOVE message} to the foreign receiver object by executing the
* removeNode
.
*
* @param removeNode the node created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param identifier name of the property to be removed
* @return true
if the property was successfully removed, false
* otherwise
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by readNode
* @throws UnknownIdentifierException if the receiver
does not allow removing a
* property for the given identifier
* @since 0.32
*/
public static boolean sendRemove(Node removeNode, TruffleObject receiver, Object identifier)
throws UnknownIdentifierException, UnsupportedMessageException {
try {
return (boolean) ((InteropAccessNode) removeNode).execute(receiver, identifier);
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#UNBOX UNBOX message} to the foreign receiver object by executing the
* unboxNode
.
*
* @param unboxNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by unboxNode
* @since 0.24
*/
public static Object sendUnbox(Node unboxNode, TruffleObject receiver) throws UnsupportedMessageException {
try {
return ((InteropAccessNode) unboxNode).execute(receiver);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#IS_POINTER IS_POINTER message} to the foreign receiver object by
* executing the isPointerNode
.
*
* @param isPointerNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.26
*/
public static boolean sendIsPointer(Node isPointerNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) isPointerNode).executeOrFalse(receiver);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#AS_POINTER AS_POINTER message} to the foreign receiver object by
* executing the asPointerNode
.
*
* @param asPointerNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return a raw 64bit pointer value
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by asPointerNode
* @since 0.26
*/
public static long sendAsPointer(Node asPointerNode, TruffleObject receiver) throws UnsupportedMessageException {
try {
return (long) ((InteropAccessNode) asPointerNode).execute(receiver);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#TO_NATIVE TO_NATIVE message} to the foreign receiver object by
* executing the toNativeNode
.
*
* @param toNativeNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by toNativeNode
* @since 0.26
*/
public static Object sendToNative(Node toNativeNode, TruffleObject receiver) throws UnsupportedMessageException {
try {
return ((InteropAccessNode) toNativeNode).execute(receiver);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an EXECUTE {@link Message} to the foreign receiver object by executing the
* executeNode
.
*
* @param executeNode the createNode created by {@link Message#createNode()}
* @param receiver foreign function object to receive the message passed to
* {@link Message#createNode()} method
* @param arguments arguments passed to the foreign function
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedTypeException if one of element of the arguments
has an
* unsupported type
* @throws ArityException if the arguments
array does not contain the right number
* of arguments for the foreign function
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by executeNode
* @since 0.24
*/
public static Object sendExecute(Node executeNode, TruffleObject receiver, Object... arguments) throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
try {
return ((InteropAccessNode) executeNode).execute(receiver, arguments);
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#IS_EXECUTABLE IS_EXECUTABLE message} to the foreign receiver object
* by executing the isExecutableNode
.
*
* @param isExecutableNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.24
*/
public static boolean sendIsExecutable(Node isExecutableNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) isExecutableNode).executeOrFalse(receiver);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#IS_INSTANTIABLE IS_INSTANTIABLE message} to the foreign receiver
* object by executing the isInstantiableNode
.
*
* @param isInstantiableNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.30
*/
public static boolean sendIsInstantiable(Node isInstantiableNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) isInstantiableNode).executeOrFalse(receiver);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an INVOKE {@link Message} to the foreign receiver object by executing the
* invokeNode
.
*
* @param invokeNode the createNode created by {@link Message#createNode()}
* @param receiver foreign function object to receive the message passed to
* {@link Message#createNode()} method
* @param arguments arguments passed to the foreign function
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedTypeException if one of element of the arguments
has an
* unsupported type
* @throws UnknownIdentifierException if the receiver
does not have a property for
* the given identifier
that can be invoked
* @throws ArityException if the arguments
array does not contain the right number
* of arguments for the foreign function
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by invokeNode
* @since 0.24
*/
public static Object sendInvoke(Node invokeNode, TruffleObject receiver, String identifier, Object... arguments)
throws UnsupportedTypeException, ArityException, UnknownIdentifierException, UnsupportedMessageException {
try {
return ((InteropAccessNode) invokeNode).execute(receiver, identifier, arguments);
} catch (UnsupportedTypeException | ArityException | UnknownIdentifierException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an NEW {@link Message} to the foreign receiver object by executing the
* newNode
.
*
* @param newNode the createNode created by {@link Message#createNode()}
* @param receiver foreign function object to receive the message passed to
* {@link Message#createNode()} method
* @param arguments arguments passed to the foreign function
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedTypeException if one of element of the arguments
has an
* unsupported type
* @throws ArityException if the arguments
array does not contain the right number
* of arguments for the foreign function
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by newNode
* @since 0.24
*/
public static Object sendNew(Node newNode, TruffleObject receiver, Object... arguments) throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
try {
return ((InteropAccessNode) newNode).execute(receiver, arguments);
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#IS_NULL IS_NULL message} to the foreign receiver object by executing
* the isNullNode
.
*
* @param isNullNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.24
*/
public static boolean sendIsNull(Node isNullNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) isNullNode).executeOrFalse(receiver);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#HAS_SIZE HAS_SIZE message} to the foreign receiver object by
* executing the hasSizeNode
.
*
* @param hasSizeNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.24
*/
public static boolean sendHasSize(Node hasSizeNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) hasSizeNode).executeOrFalse(receiver);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends a {@link Message#GET_SIZE GET_SIZE message} to the foreign receiver object by executing
* the getSizeNode
.
*
* @param getSizeNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @throws UnsupportedMessageException if the receiver
does not support the
* {@link Message#createNode() message represented} by getSizeNode
* @since 0.24
*/
public static Object sendGetSize(Node getSizeNode, TruffleObject receiver) throws UnsupportedMessageException {
try {
return ((InteropAccessNode) getSizeNode).execute(receiver);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#IS_BOXED IS_BOXED message} to the foreign receiver object by
* executing the isNullNode
.
*
* @param isBoxedNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.24
*/
public static boolean sendIsBoxed(Node isBoxedNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) isBoxedNode).executeOrFalse(receiver);
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends a {@link Message#KEY_INFO KEY_INFO message} to the foreign receiver object by executing
* the keyInfoNode
. If the object does not support the message, the presence of the
* key is found by iteration over it's keys on a slow path and a default info is returned.
*
* @param keyInfoNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param identifier name of the property to get the info of.
* @return an integer value with bit flags described at {@link KeyInfo}.
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.26
*/
public static int sendKeyInfo(Node keyInfoNode, TruffleObject receiver, Object identifier) {
try {
return (Integer) send(keyInfoNode, receiver, identifier);
} catch (UnsupportedMessageException ex) {
CompilerDirectives.transferToInterpreter();
try {
TruffleObject keys = sendKeys(Message.KEYS.createNode(), receiver, true);
Number sizeNumber = (Number) sendGetSize(Message.GET_SIZE.createNode(), keys);
int size = sizeNumber.intValue();
Node readNode = Message.READ.createNode();
for (int i = 0; i < size; i++) {
Object key = sendRead(readNode, keys, i);
// identifier must not be null
if (identifier.equals(key)) {
return 0b111;
}
}
} catch (UnsupportedMessageException | UnknownIdentifierException uex) {
}
try {
boolean hasSize = sendHasSize(Message.HAS_SIZE.createNode(), receiver);
if (hasSize && identifier instanceof Number) {
int id = ((Number) identifier).intValue();
if (id < 0 || id != ((Number) identifier).doubleValue()) {
// identifier is some wild double number
return 0;
}
Number sizeNumber = (Number) sendGetSize(Message.GET_SIZE.createNode(), receiver);
int size = sizeNumber.intValue();
if (id < size) {
return 0b111;
}
}
} catch (UnsupportedMessageException uex) {
}
return 0;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends an {@link Message#HAS_KEYS HAS_KEYS message} to the foreign receiver object by
* executing the hasKeysNode
. If the object does not support the message, a
* {@link Message#KEYS} message is sent to test the presence of keys.
*
* @param hasKeysNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return value, if any
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.30
*/
public static boolean sendHasKeys(Node hasKeysNode, TruffleObject receiver) {
try {
return (boolean) ((InteropAccessNode) hasKeysNode).execute(receiver);
} catch (UnsupportedMessageException ex) {
CompilerDirectives.transferToInterpreter();
try {
sendKeys(Message.KEYS.createNode(), receiver, true);
return true;
} catch (UnsupportedMessageException uex) {
return false;
}
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends a {@link Message#KEYS} message to the foreign receiver object.
*
* @param keysNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @return return an instance of {@link TruffleObject} that responds to {@link Message#HAS_SIZE}
* and {@link Message#GET_SIZE} and its 0 to {@link Message#GET_SIZE size - 1} indexes
* contain {@link String} names of the properties of the receiver
object
* @throws UnsupportedMessageException if the message isn't handled
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.24
*/
public static TruffleObject sendKeys(Node keysNode, TruffleObject receiver) throws UnsupportedMessageException {
try {
return (TruffleObject) send(keysNode, receiver);
} catch (UnsupportedMessageException ex) {
CompilerDirectives.transferToInterpreter();
throw ex;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Sends a {@link Message#KEYS} message to the foreign receiver object, with a specification of
* whether internal keys should be included in the result, or not.
*
* @param keysNode the createNode created by {@link Message#createNode()}
* @param receiver foreign object to receive the message passed to {@link Message#createNode()}
* method
* @param includeInternal true
to include internal keys in the result,
* false
to abandon them.
* @return return an instance of {@link TruffleObject} that responds to {@link Message#HAS_SIZE}
* and {@link Message#GET_SIZE} and its 0 to {@link Message#GET_SIZE size - 1} indexes
* contain {@link String} names of the properties of the receiver
object
* @throws UnsupportedMessageException if the message isn't handled
* @throws ClassCastException if the createNode has not been created by
* {@link Message#createNode()} method.
* @since 0.26
*/
public static TruffleObject sendKeys(Node keysNode, TruffleObject receiver, boolean includeInternal) throws UnsupportedMessageException {
try {
return (TruffleObject) send(keysNode, receiver, includeInternal);
} catch (UnsupportedMessageException ex) {
CompilerDirectives.transferToInterpreter();
throw ex;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception caught.", e);
}
}
/**
* Read only access to foreign call arguments inside of a frame.
*
* @param frame the frame that was called via
* {@link #send(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) }
* @return read-only list of parameters passed to the frame
* @since 0.11
*/
public static List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy