/*
* 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 <code>ForeignAccess</code>
* , 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
* <code>null</code> 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.10
* @return new instance wrapping <code>factory</code>
* @since 0.8 or earlier
* @deprecated Use {@link Factory18} and
* {@link #create(java.lang.Class, com.oracle.truffle.api.interop.ForeignAccess.Factory18)}
*/
@Deprecated
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 DelegatingFactory10(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
* <code>null</code> 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.18
* @return new instance wrapping <code>factory</code>
* @since 0.18
* @deprecated Use {@link Factory26} and
* {@link #create(java.lang.Class, com.oracle.truffle.api.interop.ForeignAccess.Factory26)}
*/
@Deprecated
public static ForeignAccess create(final Class<? extends TruffleObject> baseClass, final Factory18 factory) {
if (baseClass == null) {
Factory f = (Factory) factory;
assert f != null;
}
return new ForeignAccess(new DelegatingFactory18(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
* <code>null</code> 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 <code>factory</code>
* @since 0.26
*/
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 known as of
* version 0.10
* @param languageCheck a {@link RootNode} that performs the language check on receiver objects
* @return new instance wrapping <code>factory</code>
* @since 0.13
* @deprecated Use {@link Factory18} and
* {@link #create(com.oracle.truffle.api.interop.ForeignAccess.Factory18, com.oracle.truffle.api.nodes.RootNode)
* its associated factory} method
*/
@Deprecated
public static ForeignAccess create(final Factory10 factory, final RootNode languageCheck) {
return new ForeignAccess(languageCheck, new DelegatingFactory10(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.18
* @param languageCheck a {@link RootNode} that performs the language check on receiver objects,
* can be <code>null</code>, but then the factory must also implement {@link Factory}
* interface
* @return new instance wrapping <code>factory</code>
* @since 0.18
* @deprecated Use {@link Factory26} and
* {@link #create(com.oracle.truffle.api.interop.ForeignAccess.Factory26, com.oracle.truffle.api.nodes.RootNode)
* its associated factory} method
*/
@Deprecated
public static ForeignAccess create(final Factory18 factory, final RootNode languageCheck) {
if (languageCheck == null) {
Factory f = (Factory) factory;
assert f != null;
}
return new ForeignAccess(languageCheck, new DelegatingFactory18(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 <code>null</code>, but then the factory must also implement {@link Factory}
* interface
* @return new instance wrapping <code>factory</code>
* @since 0.26
*/
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 <code>factory</code>
* @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 <code>receiver</code>
* 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);
}
/**
* @since 0.11
* @deprecated use {@link #send(Node, TruffleObject, Object...)} instead
*/
@Deprecated
public static Object send(Node foreignNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver, Object... arguments) throws InteropException {
return send(foreignNode, receiver, arguments);
}
/**
* @since 0.11
* @deprecated use {@link #sendRead(Node, TruffleObject, Object)} instead
*/
@Deprecated
public static Object sendRead(Node readNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver, Object identifier)
throws UnknownIdentifierException, UnsupportedMessageException {
return sendRead(readNode, receiver, identifier);
}
/**
* @since 0.11
* @deprecated use {@link #sendWrite(Node, TruffleObject, Object, Object)} instead
*/
@Deprecated
public static Object sendWrite(Node writeNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver, Object identifier, Object value)
throws UnknownIdentifierException, UnsupportedTypeException, UnsupportedMessageException {
return sendWrite(writeNode, receiver, identifier, value);
}
/**
* @since 0.11
* @deprecated use {@link #sendUnbox(Node, TruffleObject)} instead
*/
@Deprecated
public static Object sendUnbox(Node unboxNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) throws UnsupportedMessageException {
return sendUnbox(unboxNode, receiver);
}
/**
* @since 0.11
* @deprecated use {@link #sendExecute(Node, TruffleObject, Object...)} instead
*/
@Deprecated
public static Object sendExecute(Node executeNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver, Object... arguments)
throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
return sendExecute(executeNode, receiver, arguments);
}
/**
* @since 0.11
* @deprecated use {@link #sendIsExecutable(Node, TruffleObject)} instead
*/
@Deprecated
public static boolean sendIsExecutable(Node isExecutableNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) {
return sendIsExecutable(isExecutableNode, receiver);
}
/**
* @since 0.11
* @deprecated use {@link #sendInvoke(Node, TruffleObject, String, Object...)} instead
*/
@Deprecated
public static Object sendInvoke(Node invokeNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver, String identifier, Object... arguments)
throws UnsupportedTypeException, ArityException, UnknownIdentifierException, UnsupportedMessageException {
return sendInvoke(invokeNode, receiver, identifier, arguments);
}
/**
* @since 0.11
* @deprecated use {@link #sendNew(Node, TruffleObject, Object...)} instead
*/
@Deprecated
public static Object sendNew(Node newNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver, Object... arguments)
throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
return sendNew(newNode, receiver, arguments);
}
/**
* @since 0.11
* @deprecated use {@link #sendIsNull(Node, TruffleObject)} instead
*/
@Deprecated
public static boolean sendIsNull(Node isNullNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) {
return sendIsNull(isNullNode, receiver);
}
/**
* @since 0.11
* @deprecated use {@link #sendHasSize(Node, TruffleObject)} instead
*/
@Deprecated
public static boolean sendHasSize(Node hasSizeNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) {
return sendHasSize(hasSizeNode, receiver);
}
/**
* @since 0.11
* @deprecated use {@link #sendGetSize(Node, TruffleObject)} instead
*/
@Deprecated
public static Object sendGetSize(Node getSizeNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) throws UnsupportedMessageException {
return sendGetSize(getSizeNode, receiver);
}
/**
* @since 0.11
* @deprecated use {@link #sendIsBoxed(Node, TruffleObject)} instead
*/
@Deprecated
public static boolean sendIsBoxed(Node isBoxedNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) {
return sendIsBoxed(isBoxedNode, receiver);
}
/**
* @since 0.18
* @deprecated use {@link #sendKeys(Node, TruffleObject)} instead
*/
@Deprecated
public static TruffleObject sendKeys(Node keysNode, @SuppressWarnings("unused") VirtualFrame frame, TruffleObject receiver) throws UnsupportedMessageException {
return sendKeys(keysNode, receiver);
}
/**
* 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 <code>receiver</code>
* 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
* <code> readNode </code>.
*
* @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 <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>readNode</code>
* @throws UnknownIdentifierException if the <code>receiver</code> does not allow reading a
* property for the given <code>identifier</code>
* @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
* <code> writeNode </code>.
*
* @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 <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>writeNode</code>
* @throws UnknownIdentifierException if the <code>receiver</code> does not allow writing a
* property for the given <code>identifier</code>
* @throws UnsupportedTypeException if <code>value</code> 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 an {@link Message#UNBOX UNBOX message} to the foreign receiver object by executing the
* <code> unboxNode </code>.
*
* @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 <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>unboxNode</code>
* @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 <code> isPointerNode </code>.
*
* @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) send(isPointerNode, receiver);
} catch (UnsupportedMessageException ex) {
return false;
} 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 <code> asPointerNode </code>.
*
* @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 <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>asPointerNode</code>
* @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 <code> toNativeNode </code>.
*
* @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 <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>toNativeNode</code>
* @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
* <code> executeNode </code>.
*
* @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 <code>arguments</code> has an
* unsupported type
* @throws ArityException if the <code>arguments</code> array does not contain the right number
* of arguments for the foreign function
* @throws UnsupportedMessageException if the <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>executeNode</code>
* @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 <code> isExecutableNode </code>.
*
* @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) send(isExecutableNode, 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
* <code> invokeNode </code>.
*
* @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 <code>arguments</code> has an
* unsupported type
* @throws UnknownIdentifierException if the <code>receiver</code> does not have a property for
* the given <code>identifier</code> that can be invoked
* @throws ArityException if the <code>arguments</code> array does not contain the right number
* of arguments for the foreign function
* @throws UnsupportedMessageException if the <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>invokeNode</code>
* @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
* <code> newNode </code>.
*
* @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 <code>arguments</code> has an
* unsupported type
* @throws ArityException if the <code>arguments</code> array does not contain the right number
* of arguments for the foreign function
* @throws UnsupportedMessageException if the <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>newNode</code>
* @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 <code> isNullNode </code>.
*
* @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) send(isNullNode, receiver);
} catch (UnsupportedMessageException ex) {
return false;
} 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 <code> hasSizeNode </code>.
*
* @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) send(hasSizeNode, receiver);
} catch (UnsupportedMessageException ex) {
return false;
} 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 <code> getSizeNode </code>.
*
* @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 <code>receiver</code> does not support the
* {@link Message#createNode() message represented} by <code>getSizeNode</code>
* @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 <code> isNullNode </code>.
*
* @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) send(isBoxedNode, receiver);
} catch (UnsupportedMessageException ex) {
return false;
} 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 <code>keyInfoNode</code>. 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 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 <code>receiver</code> 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 <code>true</code> to include internal keys in the result,
* <code>false</code> 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 <code>receiver</code> 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<Object> getArguments(Frame frame) {
final Object[] arr = frame.getArguments();
return ReadOnlyArrayList.asList(arr, 1, arr.length);
}
/**
* The foreign receiver in the 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 the receiver used when invoking the frame
* @since 0.8 or earlier
*/
public static TruffleObject getReceiver(Frame frame) {
return (TruffleObject) frame.getArguments()[InteropAccessNode.ARG0_RECEIVER];
}
/** @since 0.8 or earlier */
@Override
public String toString() {
Object f;
if (factory instanceof DelegatingFactory26) {
f = ((DelegatingFactory26) factory).factory;
} else if (factory instanceof DelegatingFactory18) {
f = ((DelegatingFactory18) factory).factory;
} else if (factory instanceof DelegatingFactory10) {
f = ((DelegatingFactory10) factory).factory;
} else {
f = factory;
}
return "ForeignAccess[" + f.getClass().getName() + "]";
}
CallTarget access(Message message) {
return factory.accessMessage(message);
}
CallTarget checkLanguage() {
if (languageCheck != null) {
return Truffle.getRuntime().createCallTarget((RootNode) languageCheck.deepCopy());
} else {
return null;
}
}
// currently intrinsified by Graal
@SuppressWarnings("unused")
private void checkThread() {
}
boolean canHandle(TruffleObject receiver) {
return factory.canHandle(receiver);
}
/**
* Interface of a factory that produces AST snippets that can access a foreign
* {@code TruffleObject}. A Truffle language implementation accesses a {@code TruffleObject} via
* a {@code Message}. The {@code TruffleObject} instance provides a {@link ForeignAccess}
* instance (built via {@link #create(com.oracle.truffle.api.interop.ForeignAccess.Factory)})
* that provides an AST snippet for a given {@link Message}. Rather than using this generic
* {@code Factory}, consider implementing {@link Factory18} interface that captures the set of
* messages each language should implement as of Truffle version 0.18.
*
* @since 0.8 or earlier
*/
public interface Factory {
/**
* * Checks whether provided {@link TruffleObject} can be accessed using AST snippets
* produced by this {@link Factory}.
*
* @param obj the object to check
* @return true, if the object can be processed
* @since 0.8 or earlier
*/
boolean canHandle(TruffleObject obj);
/**
* Provides an AST snippet to access a {@code TruffleObject}.
*
* @param tree the {@code Message} that represents the access to a {@code TruffleObject}.
* @return the AST snippet for accessing the {@code TruffleObject}, wrapped as a
* {@code CallTarget}.
* @since 0.8 or earlier
*/
CallTarget accessMessage(Message tree);
}
/**
* Specialized {@link Factory factory} that handles {@link Message messages} known as of release
* 0.26 of the Truffle API.
*
* @since 0.26
*/
public interface Factory26 {
/**
* Handles {@link Message#IS_NULL} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessIsNull();
/**
* Handles {@link Message#IS_EXECUTABLE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessIsExecutable();
/**
* Handles {@link Message#IS_BOXED} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessIsBoxed();
/**
* Handles {@link Message#HAS_SIZE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessHasSize();
/**
* Handles {@link Message#GET_SIZE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessGetSize();
/**
* Handles {@link Message#UNBOX} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessUnbox();
/**
* Handles {@link Message#READ} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessRead();
/**
* Handles {@link Message#WRITE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessWrite();
/**
* Handles {@link Message#createExecute(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessExecute(int argumentsLength);
/**
* Handles {@link Message#createInvoke(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessInvoke(int argumentsLength);
/**
* Handles {@link Message#createNew(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessNew(int argumentsLength);
/**
* Handles request for access to a message not known in version 0.10. The parameter to the
* returned {@link CallTarget} is going to be the object/receiver. The return value is
* supposed to be a {@link TruffleObject} that represents an array (responds to
* {@link Message#HAS_SIZE} and {@link Message#GET_SIZE} and its element represent
* {@link String} names of properties of the receiver.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessKeys();
/**
* Handles {@link Message#KEY_INFO} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessKeyInfo();
/**
* Handles {@link Message#IS_POINTER} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
default CallTarget accessIsPointer() {
return null;
}
/**
* Handles {@link Message#AS_POINTER} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
default CallTarget accessAsPointer() {
return null;
}
/**
* Handles {@link Message#TO_NATIVE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
default CallTarget accessToNative() {
return null;
}
/**
* Handles request for access to a message not known in version 0.18.
*
* @param unknown the message
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.26
*/
CallTarget accessMessage(Message unknown);
}
/**
* Specialized {@link Factory factory} that handles {@link Message messages} known as of release
* 0.18 of the Truffle API.
*
* @since 0.18
* @deprecated extended set of messages is now supported, consider implementing
* {@link Factory26}
*/
@Deprecated
public interface Factory18 {
/**
* Handles {@link Message#IS_NULL} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessIsNull();
/**
* Handles {@link Message#IS_EXECUTABLE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessIsExecutable();
/**
* Handles {@link Message#IS_BOXED} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessIsBoxed();
/**
* Handles {@link Message#HAS_SIZE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessHasSize();
/**
* Handles {@link Message#GET_SIZE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessGetSize();
/**
* Handles {@link Message#UNBOX} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessUnbox();
/**
* Handles {@link Message#READ} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessRead();
/**
* Handles {@link Message#WRITE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessWrite();
/**
* Handles {@link Message#createExecute(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessExecute(int argumentsLength);
/**
* Handles {@link Message#createInvoke(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessInvoke(int argumentsLength);
/**
* Handles {@link Message#createNew(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessNew(int argumentsLength);
/**
* Handles request for access to a message not known in version 0.10. The parameter to the
* returned {@link CallTarget} is going to be the object/receiver. The return value is
* supposed to be a {@link TruffleObject} that represents an array (responds to
* {@link Message#HAS_SIZE} and {@link Message#GET_SIZE} and its element represent
* {@link String} names of properties of the receiver.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessKeys();
/**
* Handles request for access to a message not known in version 0.18.
*
* @param unknown the message
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.18
*/
CallTarget accessMessage(Message unknown);
}
/**
* Specialized {@link Factory factory} that handles {@link Message messages} known as of release
* 0.10 of the Truffle API.
*
* @since 0.8 or earlier
* @deprecated extended set of messages is now supported, consider implementing
* {@link Factory18}
*/
@Deprecated
public interface Factory10 {
/**
* Handles {@link Message#IS_NULL} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessIsNull();
/**
* Handles {@link Message#IS_EXECUTABLE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessIsExecutable();
/**
* Handles {@link Message#IS_BOXED} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessIsBoxed();
/**
* Handles {@link Message#HAS_SIZE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessHasSize();
/**
* Handles {@link Message#GET_SIZE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessGetSize();
/**
* Handles {@link Message#UNBOX} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessUnbox();
/**
* Handles {@link Message#READ} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessRead();
/**
* Handles {@link Message#WRITE} message.
*
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessWrite();
/**
* Handles {@link Message#createExecute(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessExecute(int argumentsLength);
/**
* Handles {@link Message#createInvoke(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessInvoke(int argumentsLength);
/**
* Handles {@link Message#createNew(int)} messages.
*
* @param argumentsLength number of parameters the messages has been created for
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.9
*/
CallTarget accessNew(int argumentsLength);
/**
* Handles request for access to a message not known in version 1.0.
*
* @param unknown the message
* @return call target to handle the message or <code>null</code> if this message is not
* supported
* @since 0.8 or earlier
*/
CallTarget accessMessage(Message unknown);
}
private static class DelegatingFactory10 implements Factory {
private final Class<?> baseClass;
private final Factory10 factory;
DelegatingFactory10(Class<?> baseClass, Factory10 factory) {
this.baseClass = baseClass;
this.factory = factory;
}
@Override
public boolean canHandle(TruffleObject obj) {
if (baseClass == null) {
return ((Factory) factory).canHandle(obj);
}
return baseClass.isInstance(obj);
}
@Override
public CallTarget accessMessage(Message msg) {
return accessMessage(factory, msg);
}
private static CallTarget accessMessage(Factory10 factory, Message msg) {
if (msg instanceof KnownMessage) {
switch (msg.hashCode()) {
case Execute.EXECUTE:
return factory.accessExecute(((Execute) msg).getArity());
case Execute.INVOKE:
return factory.accessInvoke(((Execute) msg).getArity());
case Execute.NEW:
return factory.accessNew(((Execute) msg).getArity());
case GetSize.HASH:
return factory.accessGetSize();
case HasSize.HASH:
return factory.accessHasSize();
case IsBoxed.HASH:
return factory.accessIsBoxed();
case IsExecutable.HASH:
return factory.accessIsExecutable();
case IsNull.HASH:
return factory.accessIsNull();
case Read.HASH:
return factory.accessRead();
case Unbox.HASH:
return factory.accessUnbox();
case Write.HASH:
return factory.accessWrite();
}
}
return factory.accessMessage(msg);
}
}
private static class DelegatingFactory18 implements Factory {
private final Class<?> baseClass;
private final Factory18 factory;
DelegatingFactory18(Class<?> baseClass, Factory18 factory) {
this.baseClass = baseClass;
this.factory = factory;
}
@Override
public boolean canHandle(TruffleObject obj) {
if (baseClass == null) {
return ((Factory) factory).canHandle(obj);
}
return baseClass.isInstance(obj);
}
@Override
public CallTarget accessMessage(Message msg) {
return accessMessage(factory, msg);
}
private static CallTarget accessMessage(Factory18 factory, Message msg) {
if (msg instanceof KnownMessage) {
switch (msg.hashCode()) {
case Execute.EXECUTE:
return factory.accessExecute(((Execute) msg).getArity());
case Execute.INVOKE:
return factory.accessInvoke(((Execute) msg).getArity());
case Execute.NEW:
return factory.accessNew(((Execute) msg).getArity());
case GetSize.HASH:
return factory.accessGetSize();
case HasSize.HASH:
return factory.accessHasSize();
case IsBoxed.HASH:
return factory.accessIsBoxed();
case IsExecutable.HASH:
return factory.accessIsExecutable();
case IsNull.HASH:
return factory.accessIsNull();
case Read.HASH:
return factory.accessRead();
case Unbox.HASH:
return factory.accessUnbox();
case Write.HASH:
return factory.accessWrite();
case Keys.HASH:
return factory.accessKeys();
}
}
return factory.accessMessage(msg);
}
}
private static class DelegatingFactory26 implements Factory {
private final Class<?> baseClass;
private final Factory26 factory;
DelegatingFactory26(Class<?> baseClass, Factory26 factory) {
this.baseClass = baseClass;
this.factory = factory;
}
@Override
public boolean canHandle(TruffleObject obj) {
if (baseClass == null) {
return ((Factory) factory).canHandle(obj);
}
return baseClass.isInstance(obj);
}
@Override
public CallTarget accessMessage(Message msg) {
return accessMessage(factory, msg);
}
private static CallTarget accessMessage(Factory26 factory, Message msg) {
if (msg instanceof KnownMessage) {
switch (msg.hashCode()) {
case Execute.EXECUTE:
return factory.accessExecute(((Execute) msg).getArity());
case Execute.INVOKE:
return factory.accessInvoke(((Execute) msg).getArity());
case Execute.NEW:
return factory.accessNew(((Execute) msg).getArity());
case GetSize.HASH:
return factory.accessGetSize();
case HasSize.HASH:
return factory.accessHasSize();
case IsBoxed.HASH:
return factory.accessIsBoxed();
case IsExecutable.HASH:
return factory.accessIsExecutable();
case IsNull.HASH:
return factory.accessIsNull();
case Read.HASH:
return factory.accessRead();
case Unbox.HASH:
return factory.accessUnbox();
case Write.HASH:
return factory.accessWrite();
case Keys.HASH:
return factory.accessKeys();
case KeyInfoMsg.HASH:
return factory.accessKeyInfo();
case IsPointer.HASH:
return factory.accessIsPointer();
case AsPointer.HASH:
return factory.accessAsPointer();
case ToNative.HASH:
return factory.accessToNative();
}
}
return factory.accessMessage(msg);
}
}
@SuppressWarnings("unused") private static final InteropAccessor ACCESSOR = new InteropAccessor();
}