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 Thread initThread;
private final RootNode languageCheck;
private ForeignAccess(Factory faf) {
this(null, faf);
}
private ForeignAccess(RootNode languageCheck, Factory faf) {
this.factory = faf;
this.initThread = Thread.currentThread();
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
than the second interface also needs to implement
* {@link Factory})
* @param factory the factory that handles access requests to {@link Message}s known as of
* version 1.0
* @return new instance wrapping factory
* @since 0.8 or earlier
*/
public static ForeignAccess create(final Class extends TruffleObject> baseClass, final Factory10 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 factory the factory that handles access requests to {@link Message}s known as of
* version 1.0
* @param languageCheck a {@link RootNode} that performs the language check on receiver objects
* @return new instance wrapping factory
* @since 0.13
*/
public static ForeignAccess create(final Factory10 factory, final RootNode languageCheck) {
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 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) {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) foreignNode;
return fn.executeForeign(frame, 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 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 InteropException if any error occurred while accessing the receiver
* object
* @since 0.11
*/
public static Object send(Node foreignNode, VirtualFrame frame, TruffleObject receiver, Object... arguments) throws InteropException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) foreignNode;
try {
return fn.executeForeignImpl(frame, receiver, arguments);
} catch (InteropException e) {
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 frame the call frame
* @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.11
*/
public static Object sendRead(Node readNode, VirtualFrame frame, TruffleObject receiver, Object identifier) throws UnknownIdentifierException, UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) readNode;
try {
return fn.executeForeignImpl(frame, receiver, new Object[]{identifier});
} catch (UnsupportedMessageException e) {
throw e;
} catch (UnknownIdentifierException e) {
throw e;
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static Object sendWrite(Node writeNode, VirtualFrame frame, TruffleObject receiver, Object identifier, Object value)
throws UnknownIdentifierException, UnsupportedTypeException, UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) writeNode;
try {
return fn.executeForeignImpl(frame, receiver, new Object[]{identifier, value});
} catch (UnknownIdentifierException | UnsupportedTypeException | UnsupportedMessageException e) {
throw e;
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static Object sendUnbox(Node unboxNode, VirtualFrame frame, TruffleObject receiver) throws UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) unboxNode;
try {
return fn.executeForeignImpl(frame, receiver);
} catch (UnsupportedMessageException e) {
throw e;
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static Object sendExecute(Node executeNode, VirtualFrame frame, TruffleObject receiver, Object... arguments) throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) executeNode;
try {
return fn.executeForeignImpl(frame, receiver, arguments);
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw e;
} catch (InteropException e) {
CompilerDirectives.transferToInterpreter();
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static boolean sendIsExecutable(Node isExecutableNode, VirtualFrame frame, TruffleObject receiver) {
try {
return (boolean) send(isExecutableNode, frame, receiver);
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static Object sendInvoke(Node invokeNode, VirtualFrame frame, TruffleObject receiver, String identifier, Object... arguments)
throws UnsupportedTypeException, ArityException, UnknownIdentifierException, UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) invokeNode;
try {
Object[] args = new Object[arguments.length + 1];
System.arraycopy(arguments, 0, args, 1, arguments.length);
args[0] = identifier;
return fn.executeForeignImpl(frame, receiver, args);
} catch (UnsupportedTypeException | ArityException | UnknownIdentifierException | UnsupportedMessageException e) {
throw e;
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static Object sendNew(Node newNode, VirtualFrame frame, TruffleObject receiver, Object... arguments) throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) newNode;
try {
return fn.executeForeignImpl(frame, receiver, arguments);
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
throw e;
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static boolean sendIsNull(Node isNullNode, VirtualFrame frame, TruffleObject receiver) {
try {
return (boolean) send(isNullNode, frame, receiver);
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static boolean sendHasSize(Node hasSizeNode, VirtualFrame frame, TruffleObject receiver) {
try {
return (boolean) send(hasSizeNode, frame, receiver);
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static Object sendGetSize(Node getSizeNode, VirtualFrame frame, TruffleObject receiver) throws UnsupportedMessageException {
ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) getSizeNode;
try {
return fn.executeForeignImpl(frame, receiver);
} catch (UnsupportedMessageException e) {
throw e;
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", 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 frame the call frame
* @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.11
*/
public static boolean sendIsBoxed(Node isBoxedNode, VirtualFrame frame, TruffleObject receiver) {
try {
return (boolean) send(isBoxedNode, frame, receiver);
} catch (InteropException e) {
throw new AssertionError("Unexpected exception catched.", e);
}
}
/**
* Read only access to foreign call arguments inside of a frame.
*
* @param frame the frame that was called via
* {@link #execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, 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