Skip to content
Snippets Groups Projects
Commit c2e3b6ed authored by stepan's avatar stepan
Browse files

Adopt REmbedRFFI to new way of native functions invocation

parent 0f362648
No related branches found
No related tags found
No related merge requests found
Showing
with 150 additions and 260 deletions
......@@ -39,8 +39,11 @@ import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.r.launcher.ConsoleHandler;
import com.oracle.truffle.r.launcher.DelegatingConsoleHandler;
import com.oracle.truffle.r.runtime.RInterfaceCallbacks;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI.ReadConsoleNode;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI.WriteConsoleBaseNode;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI.WriteConsoleNode;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI.WriteErrConsoleNode;
import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
/**
......@@ -195,7 +198,7 @@ public final class EmbeddedConsoleHandler extends DelegatingConsoleHandler {
private CallTarget getReadLineCallTarget() {
if (readLineCallTarget == null) {
readLineCallTarget = Truffle.getRuntime().createCallTarget(new RootNode(null) {
@Child private ReadConsoleNode readConsoleNode = RFFIFactory.getREmbedRFFI().createReadConsoleNode();
@Child private ReadConsoleNode readConsoleNode = ReadConsoleNode.create();
@Override
public Object execute(VirtualFrame frame) {
......@@ -208,14 +211,14 @@ public final class EmbeddedConsoleHandler extends DelegatingConsoleHandler {
private CallTarget getWriteCallTarget() {
if (writeCallTarget == null) {
writeCallTarget = createWriteCallTarget(RFFIFactory.getREmbedRFFI().createWriteConsoleNode());
writeCallTarget = createWriteCallTarget(WriteConsoleNode.create());
}
return writeCallTarget;
}
private CallTarget getWriteErrCallTarget() {
if (writeErrCallTarget == null) {
writeErrCallTarget = createWriteCallTarget(RFFIFactory.getREmbedRFFI().createWriteErrConsoleNode());
writeErrCallTarget = createWriteCallTarget(WriteErrConsoleNode.create());
}
return writeErrCallTarget;
}
......
......@@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
import com.oracle.truffle.r.runtime.ffi.NativeFunction;
import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
import com.oracle.truffle.r.runtime.ffi.RFFIContext;
import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
......@@ -50,7 +51,7 @@ final class TruffleLLVM_Context extends RFFIContext {
super(new TruffleLLVM_C(), new BaseRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE), new TruffleLLVM_Call(), new TruffleLLVM_DLL(), new TruffleLLVM_UserRng(),
new ZipRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE), new PCRERFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE),
new LapackRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE), new StatsRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE),
new ToolsRFFI(), new TruffleLLVM_REmbed(), new MiscRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE));
new ToolsRFFI(), new REmbedRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE), new MiscRFFI(TruffleLLVM_DownCallNodeFactory.INSTANCE));
}
static TruffleLLVM_Context getContextState() {
......
/*
* Copyright (c) 2014, 2018, 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.
*
* 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.r.ffi.impl.llvm;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
public class TruffleLLVM_REmbed implements REmbedRFFI {
@Override
public ReadConsoleNode createReadConsoleNode() {
throw RInternalError.unimplemented("TODO");
}
@Override
public WriteConsoleNode createWriteConsoleNode() {
throw RInternalError.unimplemented("TODO");
}
@Override
public WriteErrConsoleNode createWriteErrConsoleNode() {
throw RInternalError.unimplemented("TODO");
}
}
/*
* Copyright (c) 2017, 2018, 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.
*
* 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.r.ffi.impl.managed;
import static com.oracle.truffle.r.ffi.impl.managed.Managed_RFFIFactory.unsupported;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
public class Managed_REmbedRFFI implements REmbedRFFI {
@Override
public ReadConsoleNode createReadConsoleNode() {
throw unsupported("REmbed");
}
@Override
public WriteConsoleNode createWriteConsoleNode() {
throw unsupported("REmbed");
}
@Override
public WriteErrConsoleNode createWriteErrConsoleNode() {
throw unsupported("REmbed");
}
}
......@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
import com.oracle.truffle.r.runtime.ffi.NativeFunction;
import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
import com.oracle.truffle.r.runtime.ffi.RFFIContext;
import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
......@@ -108,7 +109,8 @@ public final class Managed_RFFIFactory extends RFFIFactory {
throw unsupported("user defined RNG");
}
}, new ZipRFFI(Managed_DownCallNodeFactory.INSTANCE), new PCRERFFI(Managed_DownCallNodeFactory.INSTANCE), new LapackRFFI(Managed_DownCallNodeFactory.INSTANCE),
new StatsRFFI(Managed_DownCallNodeFactory.INSTANCE), new ToolsRFFI(), new Managed_REmbedRFFI(), new MiscRFFI(Managed_DownCallNodeFactory.INSTANCE));
new StatsRFFI(Managed_DownCallNodeFactory.INSTANCE), new ToolsRFFI(), new REmbedRFFI(Managed_DownCallNodeFactory.INSTANCE),
new MiscRFFI(Managed_DownCallNodeFactory.INSTANCE));
}
private static class IgnoreUpCallExceptionNode extends Node implements HandleUpCallExceptionNode {
......
......@@ -185,13 +185,6 @@ public class TruffleNFI_Call implements CallRFFI {
if (traceEnabled()) {
traceDownCallReturn(name, result);
}
TruffleNFI_Context nfiCtx = (TruffleNFI_Context) RContext.getInstance().getStateRFFI();
RuntimeException lastUpCallEx = nfiCtx.getLastUpCallException();
if (lastUpCallEx != null) {
CompilerDirectives.transferToInterpreter();
nfiCtx.setLastUpCallException(null);
throw lastUpCallEx;
}
}
@Override
......
......@@ -59,6 +59,7 @@ import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
import com.oracle.truffle.r.runtime.ffi.NativeFunction;
import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
import com.oracle.truffle.r.runtime.ffi.RFFIContext;
import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
......@@ -93,7 +94,8 @@ final class TruffleNFI_Context extends RFFIContext {
TruffleNFI_Context() {
super(new TruffleNFI_C(), new BaseRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE), new TruffleNFI_Call(), new TruffleNFI_DLL(), new TruffleNFI_UserRng(),
new ZipRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE), new PCRERFFI(TruffleNFI_DownCallNodeFactory.INSTANCE), new LapackRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE),
new StatsRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE), new ToolsRFFI(), new TruffleNFI_REmbed(), new MiscRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE));
new StatsRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE), new ToolsRFFI(), new REmbedRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE),
new MiscRFFI(TruffleNFI_DownCallNodeFactory.INSTANCE));
// forward constructor
}
......@@ -345,6 +347,7 @@ final class TruffleNFI_Context extends RFFIContext {
@Override
public long beforeDowncall() {
assert transientAllocations.size() == 0 : "transientAllocations should have been cleared in afterDowncall";
super.beforeDowncall();
if (hasAccessLock) {
acquireLock();
......@@ -354,6 +357,7 @@ final class TruffleNFI_Context extends RFFIContext {
@Override
public void afterDowncall(long beforeValue) {
super.afterDowncall(beforeValue);
popCallbacks(beforeValue);
for (Long ptr : transientAllocations) {
UnsafeAdapter.UNSAFE.freeMemory(ptr);
......@@ -362,7 +366,12 @@ final class TruffleNFI_Context extends RFFIContext {
if (hasAccessLock) {
releaseLock();
}
super.afterDowncall(beforeValue);
RuntimeException lastUpCallEx = getLastUpCallException();
if (lastUpCallEx != null) {
CompilerDirectives.transferToInterpreter();
setLastUpCallException(null);
throw lastUpCallEx;
}
}
public static TruffleNFI_Context getInstance() {
......
......@@ -91,7 +91,7 @@ public final class TruffleNFI_DownCallNodeFactory extends DownCallNodeFactory {
@ExplodeLoop
protected void afterCall(long before, NativeFunction function, TruffleObject target, Object[] args) {
if (function.hasComplexInteraction()) {
RContext.getInstance().getRFFI().afterDowncall(before);
((TruffleNFI_Context) RContext.getInstance().getRFFI()).afterDowncall(before);
}
for (Object obj : args) {
......
/*
* Copyright (c) 2017, 2018, 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.
*
* 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.r.ffi.impl.nfi;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.ffi.NativeFunction;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
public class TruffleNFI_REmbed implements REmbedRFFI {
private static class TruffleNFI_ReadConsoleNode extends TruffleNFI_DownCallNode implements ReadConsoleNode {
@Child private Node unboxNode;
@Override
protected NativeFunction getFunction() {
return NativeFunction.rembedded_read_console;
}
@Override
public String execute(String prompt) {
Object result = call(prompt);
if (result instanceof String) {
return (String) result;
}
assert result instanceof TruffleObject : "NFI is expected to send us TruffleObject or String";
if (unboxNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
unboxNode = insert(Message.UNBOX.createNode());
}
try {
return (String) ForeignAccess.sendUnbox(unboxNode, (TruffleObject) result);
} catch (ClassCastException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw RInternalError.shouldNotReachHere("Unboxing TruffleObject from NFI, which should be String wrapper, failed. " + e.getMessage());
}
}
}
private static class TruffleNFI_WriteConsoleNode extends TruffleNFI_DownCallNode implements WriteConsoleNode {
@Override
protected NativeFunction getFunction() {
return NativeFunction.rembedded_write_console;
}
@Override
public void execute(String x) {
call(x, x.length());
}
}
private static class TruffleNFI_WriteErrConsoleNode extends TruffleNFI_DownCallNode implements WriteErrConsoleNode {
@Override
protected NativeFunction getFunction() {
return NativeFunction.rembedded_write_err_console;
}
@Override
public void execute(String x) {
call(x, x.length());
}
}
@Override
public ReadConsoleNode createReadConsoleNode() {
return new TruffleNFI_ReadConsoleNode();
}
@Override
public WriteConsoleNode createWriteConsoleNode() {
return new TruffleNFI_WriteConsoleNode();
}
@Override
public WriteErrConsoleNode createWriteErrConsoleNode() {
return new TruffleNFI_WriteErrConsoleNode();
}
}
......@@ -420,7 +420,7 @@ void uR_ProcessEvents(void) {
}
void uR_CleanUp(SA_TYPE x, int y, int z) {
return ((call_R_CleanUp) callbacks[R_CleanUp_x])(x, y, z);
((call_R_CleanUp) callbacks[R_CleanUp_x])(x, y, z);
}
void (*ptr_R_Suicide)(const char *) = uR_Suicide;
......@@ -505,11 +505,11 @@ void R_runHandlers(InputHandler *handlers, fd_set *mask) {
// -----------------------------------------------------------------------------------------------
// Downcalls from Java. We invoke these functions via REmbedRFFI
void invokeCleanUp(int x, int y, int z) {
void rembedded_cleanup(int x, int y, int z) {
ptr_R_CleanUp(x, y, z);
}
void invokeSuicide(char* msg) {
void rembedded_suicide(char* msg) {
ptr_R_Suicide(msg);
}
......@@ -522,7 +522,7 @@ void rembedded_write_err_console(char *cbuf, int len) {
}
char* rembedded_read_console(const char* prompt) {
char* cbuf = malloc(sizeof(char) * 1024);
unsigned char* cbuf = malloc(sizeof(char) * 1024);
int n = (*ptr_R_ReadConsole)(prompt, cbuf, 1024, 0);
return cbuf;
}
......
......@@ -27,6 +27,8 @@ import com.oracle.truffle.r.runtime.ffi.CallRFFI.InvokeCallNode;
import com.oracle.truffle.r.runtime.ffi.DLL.RFindSymbolNode;
import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI.EmbeddedCleanUpNode;
import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
import com.oracle.truffle.r.runtime.instrument.InstrumentationState;
......@@ -44,8 +46,7 @@ public abstract class RCleanUp {
public static void cleanUp(RContext ctx, SA_TYPE saveType, int status, boolean runLast) {
if (RInterfaceCallbacks.R_CleanUp.isOverridden()) {
RootCallTarget invokeUserCleanup = ctx.getOrCreateCachedCallTarget(UserDefinedCleanUpRootNode.class, () -> new UserDefinedCleanUpRootNode(ctx).getCallTarget());
Object[] args = new Object[]{asVector(saveType.ordinal()), asVector(status), asVector(runLast ? 1 : 0)};
invokeUserCleanup.call(args);
invokeUserCleanup.call(saveType.ordinal(), status, runLast ? 1 : 0);
} else {
stdCleanUp(saveType, status, runLast);
}
......@@ -134,29 +135,18 @@ public abstract class RCleanUp {
RContext.getEngine().checkAndRunStartupShutdownFunction(".Last.sys");
}
private static RIntVector asVector(int value) {
return RDataFactory.createIntVectorFromScalar(value);
}
private static final class UserDefinedCleanUpRootNode extends RootNode {
protected UserDefinedCleanUpRootNode(RContext ctx) {
super(null);
invokeCallNode = ctx.getRFFI().callRFFI.createInvokeCallNode();
cleanUpNode = ctx.getRFFI().embedRFFI.createEmbeddedCleanUpNode();
Truffle.getRuntime().createCallTarget(this);
}
private static final String SYMBOL_NAME = "invokeCleanUp";
@Child InvokeCallNode invokeCallNode;
@Child RFindSymbolNode findSymbolNode = RFindSymbolNode.create();
@Child private EmbeddedCleanUpNode cleanUpNode;
@Override
public Object execute(VirtualFrame frame) {
SymbolHandle invokeCleanUp = findSymbolNode.execute(SYMBOL_NAME, null, null);
if (invokeCleanUp == null) {
CompilerDirectives.transferToInterpreter();
throw RInternalError.shouldNotReachHere("Cannot find " + SYMBOL_NAME + " symbol which should be declared in Rembedded.c");
}
invokeCallNode.dispatch(new NativeCallInfo(SYMBOL_NAME, invokeCleanUp, null), frame.getArguments());
cleanUpNode.execute((int) frame.getArguments()[0], (int) frame.getArguments()[1], (int) frame.getArguments()[2]);
return null;
}
}
......
......@@ -34,6 +34,7 @@ import com.oracle.truffle.r.runtime.ffi.CallRFFI.InvokeCallNode;
import com.oracle.truffle.r.runtime.ffi.DLL.RFindSymbolNode;
import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
import com.oracle.truffle.r.runtime.ffi.REmbedRFFI.EmbeddedSuicideNode;
import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
public abstract class RSuicide {
......@@ -73,36 +74,25 @@ public abstract class RSuicide {
throw new ExitException(2, false);
}
private static RStringVector asVector(String value) {
return RDataFactory.createStringVector(value);
}
private static void invokeUserDefinedSuicide(RContext ctx, String msg) {
if (ctx != null && RInterfaceCallbacks.R_Suicide.isOverridden()) {
RootCallTarget invokeUserCleanup = ctx.getOrCreateCachedCallTarget(UserDefinedSuicideRootNode.class, () -> new UserDefinedSuicideRootNode(ctx).getCallTarget());
invokeUserCleanup.call(new Object[]{asVector(msg)});
invokeUserCleanup.call(msg);
}
}
private static final class UserDefinedSuicideRootNode extends RootNode {
protected UserDefinedSuicideRootNode(RContext ctx) {
super(null);
invokeCallNode = ctx.getRFFI().callRFFI.createInvokeCallNode();
suicideNode = ctx.getRFFI().embedRFFI.createEmbeddedSuicideNode();
Truffle.getRuntime().createCallTarget(this);
}
private static final String SYMBOL_NAME = "invokeSuicide";
@Child InvokeCallNode invokeCallNode;
@Child RFindSymbolNode findSymbolNode = RFindSymbolNode.create();
@Child private EmbeddedSuicideNode suicideNode;
@Override
public Object execute(VirtualFrame frame) {
SymbolHandle invokeSuicide = findSymbolNode.execute(SYMBOL_NAME, null, null);
if (invokeSuicide == null) {
CompilerDirectives.transferToInterpreter();
throw RInternalError.shouldNotReachHere("Cannot find " + SYMBOL_NAME + " symbol which should be declared in Rembedded.c");
}
invokeCallNode.dispatch(new NativeCallInfo(SYMBOL_NAME, invokeSuicide, null), frame.getArguments());
suicideNode.execute((String) frame.getArguments()[0]);
return null;
}
}
......
......@@ -82,11 +82,13 @@ public enum NativeFunction {
// FastR helpers
set_exception_flag("(): void"),
// FastR internal helper for R embedded mode
rembedded_write_console("(string, sint32):void", "", anyLibrary(), true),
rembedded_write_err_console("(string, sint32):void", "", anyLibrary(), true),
rembedded_read_console("(string):string", "", anyLibrary(), true),
rembedded_native_clean_up("(sint32, sint32, sint32):void", "", anyLibrary(), true),
rembedded_native_suicide("(string):void", "", anyLibrary(), true),
rembedded_cleanup("(sint32, sint32, sint32):void", "", baseLibrary(), true),
rembedded_suicide("(string):void", "", baseLibrary(), true),
rembedded_write_console("(string, sint32):void", "", baseLibrary(), true),
rembedded_write_err_console("(string, sint32):void", "", baseLibrary(), true),
rembedded_read_console("(string):string", "", baseLibrary(), true),
rembedded_native_clean_up("(sint32, sint32, sint32):void", "", baseLibrary(), true),
rembedded_native_suicide("(string):void", "", baseLibrary(), true),
// user-defined RNG
unif_init("(sint32): void", "user_", anyLibrary()),
norm_rand("(): pointer", "user_", anyLibrary()),
......
......@@ -22,40 +22,131 @@
*/
package com.oracle.truffle.r.runtime.ffi;
import com.oracle.truffle.api.nodes.NodeInterface;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.ffi.DownCallNodeFactory.DownCallNode;
/**
* Function down-calls related to the embedded API. TODO: these all should be invoked as proper
* down-calls because the user code may want to use R API.
*/
public interface REmbedRFFI {
interface ReadConsoleNode extends NodeInterface {
String execute(String prompt);
public final class REmbedRFFI {
private final DownCallNodeFactory downCallNodeFactory;
static REmbedRFFI.ReadConsoleNode create() {
public REmbedRFFI(DownCallNodeFactory downCallNodeFactory) {
this.downCallNodeFactory = downCallNodeFactory;
}
public static final class ReadConsoleNode extends NativeCallNode {
@Child private Node unboxNode;
private ReadConsoleNode(DownCallNodeFactory factory) {
super(factory.createDownCallNode(NativeFunction.rembedded_read_console));
}
public String execute(String prompt) {
Object result = call(prompt);
if (result instanceof String) {
return (String) result;
}
assert result instanceof TruffleObject : "NFI is expected to send us TruffleObject or String";
if (unboxNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
unboxNode = insert(Message.UNBOX.createNode());
}
try {
return (String) ForeignAccess.sendUnbox(unboxNode, (TruffleObject) result);
} catch (ClassCastException | UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreter();
throw RInternalError.shouldNotReachHere("Unboxing TruffleObject from NFI, which should be String wrapper, failed. " + e.getMessage());
}
}
public static REmbedRFFI.ReadConsoleNode create() {
return RFFIFactory.getREmbedRFFI().createReadConsoleNode();
}
}
interface WriteConsoleBaseNode extends NodeInterface {
void execute(String x);
public abstract static class WriteConsoleBaseNode extends NativeCallNode {
private WriteConsoleBaseNode(DownCallNode downCallNode) {
super(downCallNode);
}
public final void execute(String x) {
call(x, x.length());
}
}
interface WriteConsoleNode extends WriteConsoleBaseNode {
static REmbedRFFI.WriteConsoleNode create() {
public static final class WriteConsoleNode extends WriteConsoleBaseNode {
public static REmbedRFFI.WriteConsoleNode create() {
return RFFIFactory.getREmbedRFFI().createWriteConsoleNode();
}
public WriteConsoleNode(DownCallNodeFactory factory) {
super(factory.createDownCallNode(NativeFunction.rembedded_write_console));
}
}
interface WriteErrConsoleNode extends WriteConsoleBaseNode {
static REmbedRFFI.WriteErrConsoleNode create() {
public static final class WriteErrConsoleNode extends WriteConsoleBaseNode {
public static REmbedRFFI.WriteErrConsoleNode create() {
return RFFIFactory.getREmbedRFFI().createWriteErrConsoleNode();
}
public WriteErrConsoleNode(DownCallNodeFactory factory) {
super(factory.createDownCallNode(NativeFunction.rembedded_write_err_console));
}
}
ReadConsoleNode createReadConsoleNode();
public static final class EmbeddedSuicideNode extends NativeCallNode {
private EmbeddedSuicideNode(DownCallNodeFactory factory) {
super(factory.createDownCallNode(NativeFunction.rembedded_suicide));
}
WriteConsoleNode createWriteConsoleNode();
public void execute(String message) {
call(message);
}
WriteErrConsoleNode createWriteErrConsoleNode();
public static EmbeddedSuicideNode create() {
return RFFIFactory.getREmbedRFFI().createEmbeddedSuicideNode();
}
}
public static final class EmbeddedCleanUpNode extends NativeCallNode {
private EmbeddedCleanUpNode(DownCallNodeFactory factory) {
super(factory.createDownCallNode(NativeFunction.rembedded_cleanup));
}
public void execute(int x, int y, int z) {
call(x, y, z);
}
public static EmbeddedCleanUpNode create() {
return RFFIFactory.getREmbedRFFI().createEmbeddedCleanUpNode();
}
}
ReadConsoleNode createReadConsoleNode() {
return new ReadConsoleNode(downCallNodeFactory);
}
WriteConsoleNode createWriteConsoleNode() {
return new WriteConsoleNode(downCallNodeFactory);
}
WriteErrConsoleNode createWriteErrConsoleNode() {
return new WriteErrConsoleNode(downCallNodeFactory);
}
public EmbeddedSuicideNode createEmbeddedSuicideNode() {
return new EmbeddedSuicideNode(downCallNodeFactory);
}
public EmbeddedCleanUpNode createEmbeddedCleanUpNode() {
return new EmbeddedCleanUpNode(downCallNodeFactory);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment