diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java index 3cd51bce2da13484f1b3973c5b8283f452c89da4..22f48ef2cc55bcd9cc9a9124b82ad350ec416282 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java @@ -223,6 +223,19 @@ public class TruffleLLVM_Base implements BaseRFFI { } } + private static class TruffleLLVM_SetShutdownFlagNode extends TruffleLLVM_DownCallNode implements SetShutdownFlagNode { + + @Override + protected NativeFunction getFunction() { + return NativeFunction.set_shutdown_phase; + } + + @Override + public void execute(boolean value) { + call(value ? 1 : 0); + } + } + @Override public GetpidNode createGetpidNode() { return new TruffleLLVM_GetpidNode(); @@ -272,4 +285,9 @@ public class TruffleLLVM_Base implements BaseRFFI { public GlobNode createGlobNode() { return new TruffleLLVM_GlobNode(); } + + @Override + public SetShutdownFlagNode createSetShutdownFlagNode() { + return new TruffleLLVM_SetShutdownFlagNode(); + } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java index 20c7d3f17d6845b66cbf9054c9c4bfa42a78c3a4..7054d39681aadfd43ce7c3c824a95474c4865ba1 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java @@ -200,4 +200,17 @@ public class Managed_Base implements BaseRFFI { public GlobNode createGlobNode() { return null; } + + private static final class ManagedSetShutdownFlagNode extends Node implements SetShutdownFlagNode { + + @Override + public void execute(boolean value) { + // do nothing + } + } + + @Override + public SetShutdownFlagNode createSetShutdownFlagNode() { + return new ManagedSetShutdownFlagNode(); + } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIContext.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIContext.java index 712210240126b220fb57a17b1525ed9151093a8b..47f28cbce9c159adb4bf9e0af9349fe3e04a19b8 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIContext.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIContext.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import com.oracle.truffle.r.ffi.impl.common.LibPaths; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextState; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLLRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIContext; @@ -49,9 +50,20 @@ class NFIContext extends RFFIContext { // force initialization of NFI DLLRFFI.DLOpenRootNode.create(context).call(librffiPath, false, false); } + if (RContext.getContextCnt() == 0) { + BaseRFFI.SetShutdownFlagRootNode.create().getCallTarget().call(false); + } return this; } + @Override + public void beforeDispose(RContext context) { + if (RContext.getContextCnt() == 1) { + BaseRFFI.SetShutdownFlagRootNode.create().getCallTarget().call(true); + } + super.beforeDispose(context); + } + @Override public void afterDowncall() { for (Long ptr : transientAllocations) { diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NativeFunction.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NativeFunction.java index cf1c2d76c38e1b39042c2fe93a716eab11f01def..1e8dd4776e2a52586222f95968803c1600086c3c 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NativeFunction.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NativeFunction.java @@ -78,7 +78,8 @@ public enum NativeFunction { dqrls("([double], sint32, sint32, [double], sint32, double, [double], [double], [double], [sint32], [sint32], [double], [double]): void", "call_misc_"), // stats fft_factor("(sint32, [sint32], [sint32]): void", TruffleNFI_Utils::lookupAndBindStats), - fft_work("([double], sint32, sint32, sint32, sint32, [double], [sint32]): sint32", TruffleNFI_Utils::lookupAndBindStats); + fft_work("([double], sint32, sint32, sint32, sint32, [double], [sint32]): sint32", TruffleNFI_Utils::lookupAndBindStats), + set_shutdown_phase("(uint8): void", TruffleNFI_Utils::lookupAndBind); private final int argumentCount; private final String signature; diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java index c38173bfd4b8ecddc57ac170309aa2126fd95970..69b7d456b22989af06b22c0ad4708eea1167cbe4 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java @@ -213,6 +213,19 @@ public class TruffleNFI_Base implements BaseRFFI { } } + private static class TruffleNFI_SetShutdownFlagNode extends TruffleNFI_DownCallNode implements SetShutdownFlagNode { + + @Override + protected NativeFunction getFunction() { + return NativeFunction.set_shutdown_phase; + } + + @Override + public void execute(boolean value) { + call(value ? 1 : 0); + } + } + @Override public GetpidNode createGetpidNode() { return new TruffleNFI_GetpidNode(); @@ -262,4 +275,9 @@ public class TruffleNFI_Base implements BaseRFFI { public GlobNode createGlobNode() { return new TruffleNFI_GlobNode(); } + + @Override + public SetShutdownFlagNode createSetShutdownFlagNode() { + return new TruffleNFI_SetShutdownFlagNode(); + } } diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h index 9ec235c0bf90a484764528a552c801065e3fae51..583fee9348251042d78bd2bcb00ff56c65674652 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h @@ -828,8 +828,8 @@ void SET_PRCODE(SEXP x, SEXP v) { } int TRUELENGTH(SEXP x) { - TRACE0(); - unimplemented("unimplemented"); + TRACE(TARGp, x); + // TODO do not throw an error for now return 0; } @@ -1342,7 +1342,9 @@ void R_PreserveObject(SEXP x) { void R_ReleaseObject(SEXP x) { TRACE0(); - ((call_R_ReleaseObject) callbacks[R_ReleaseObject_x])(x); + if(!is_shutdown_phase()) { + ((call_R_ReleaseObject) callbacks[R_ReleaseObject_x])(x); + } } void R_dot_Last(void) { diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c index 12c143c3461d9367be0347fca288aa1b3e94b0d2..be3bf7cf24c906e88dd543e50492b2e380e69345 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c @@ -41,6 +41,8 @@ void init_utils(TruffleEnv *env) { } } +static unsigned char shutdown_phase = 0; + #define ERROR_JMP_BUF_STACK_SIZE 32 static jmp_buf *callErrorJmpBufStack[ERROR_JMP_BUF_STACK_SIZE]; static int callErrorJmpBufStackIndex = 0; @@ -79,6 +81,14 @@ static void popJmpBuf() { popJmpBuf(); \ return result; +void set_shutdown_phase(unsigned char value) { + shutdown_phase = value; +} + +int is_shutdown_phase() { + return shutdown_phase; +} + void dot_call_void0(callvoid0func fun) { DO_CALL_VOID(fun()); } diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h index 8de8be4ec35234407051080baee058e64ac83210..fc9621f2dc2f4e571282d920d5de29cd1205b9db 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h @@ -53,6 +53,10 @@ typedef void (*callvoid0func)(void); typedef void (*callvoid1func)(SEXP arg1); +void set_shutdown_phase(unsigned char value); + +int is_shutdown_phase(); + void dot_call_void0(callvoid0func); void dot_call_void1(callvoid1func, SEXP); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java index 265f759518f8b13c32f0b4dd8fcd8aab203e9f49..2232e1e75853eac5b55d828b1426021b137b9b57 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java @@ -48,6 +48,7 @@ import java.util.TimeZone; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; import com.oracle.truffle.api.Assumption; @@ -292,6 +293,8 @@ public final class RContext implements RTruffleObject { */ private static boolean embedded; + private static final AtomicInteger CONTEXT_CNT = new AtomicInteger(0); + /* * Workarounds to finesse project circularities between runtime/nodes. */ @@ -372,6 +375,10 @@ public final class RContext implements RTruffleObject { return embedded; } + public static int getContextCnt() { + return CONTEXT_CNT.get(); + } + /** * Sets the fields that do not depend on complex initialization. * @@ -523,6 +530,7 @@ public final class RContext implements RTruffleObject { if (initial && !embedded) { initialContextInitialized = true; } + CONTEXT_CNT.incrementAndGet(); return this; } @@ -574,6 +582,7 @@ public final class RContext implements RTruffleObject { if (contextKind == ContextKind.SHARE_PARENT_RW) { parentContext.sharedChild = null; } + CONTEXT_CNT.decrementAndGet(); state = EnumSet.of(State.DISPOSED); this.allocationReporter.removePropertyChangeListener(ALLOCATION_ACTIVATION_LISTENER); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java index 2a6ad6919008ef22802b97f96c276d9377bab21f..6ae84cd4766ac2767a066db82a03561c75321728 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeInterface; +import com.oracle.truffle.r.runtime.data.RNull; /** * A statically typed interface to exactly those native functions required by the R {@code base} @@ -163,6 +164,14 @@ public interface BaseRFFI { } } + interface SetShutdownFlagNode extends NodeInterface { + void execute(boolean value); + + static SetShutdownFlagNode create() { + return RFFIFactory.getBaseRFFI().createSetShutdownFlagNode(); + } + } + /* * The RFFI implementation influences exactly what subclass of the above nodes is created. Each * implementation must therefore, implement these methods that are called by the associated @@ -189,6 +198,8 @@ public interface BaseRFFI { GlobNode createGlobNode(); + SetShutdownFlagNode createSetShutdownFlagNode(); + /* * Some functions are called from non-Truffle contexts, which requires a RootNode */ @@ -273,4 +284,27 @@ public interface BaseRFFI { return unameRootNode; } } + + final class SetShutdownFlagRootNode extends RFFIRootNode<SetShutdownFlagNode> { + protected SetShutdownFlagRootNode() { + super(RFFIFactory.getBaseRFFI().createSetShutdownFlagNode()); + } + + private static SetShutdownFlagRootNode setShutdownFlagRootNode; + + @Override + public Object execute(VirtualFrame frame) { + Object[] args = frame.getArguments(); + rffiNode.execute((boolean) args[0]); + return RNull.instance; + } + + public static SetShutdownFlagRootNode create() { + if (setShutdownFlagRootNode == null) { + setShutdownFlagRootNode = new SetShutdownFlagRootNode(); + } + return setShutdownFlagRootNode; + } + } + }