Skip to content

Commit afcc8dc

Browse files
[GR-19494] Fix: protect Rf_unprotect'ed until next GNU-R compatible GC cycle.
PullRequest: fastr/2225
2 parents dd6db7f + 167cb79 commit afcc8dc

File tree

5 files changed

+49
-7
lines changed

5 files changed

+49
-7
lines changed

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ReleaseObjectNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Object protect(RBaseObject x,
5959
int decrementAndGet = atomicInteger.decrementAndGet();
6060
if (decrementAndGet == 0) {
6161
// remove from "list"
62+
// Note: developers expect the "unprotected" references to be still alive until next
63+
// GNU-R compatible GC cycle
64+
ctx.registerReferenceUsedInNative(x);
6265
preserveList.removeKey(x);
6366
}
6467
} else {

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/UnprotectNode.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
import com.oracle.truffle.api.dsl.Specialization;
3131
import com.oracle.truffle.api.library.CachedLibrary;
3232
import com.oracle.truffle.api.nodes.ExplodeLoop;
33+
import com.oracle.truffle.api.profiles.BranchProfile;
3334
import com.oracle.truffle.r.runtime.Collections.StackLibrary;
3435
import com.oracle.truffle.r.runtime.RError;
3536
import com.oracle.truffle.r.runtime.context.RContext;
3637
import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
3738
import com.oracle.truffle.r.runtime.data.RNull;
39+
import com.oracle.truffle.r.runtime.ffi.RFFIContext;
40+
import com.oracle.truffle.r.runtime.ffi.RFFILog;
3841

3942
@GenerateUncached
4043
public abstract class UnprotectNode extends FFIUpCallNode.Arg1 {
@@ -54,11 +57,13 @@ Object unprotectNothing(@SuppressWarnings("unused") int n) {
5457

5558
@Specialization(guards = "n == 1")
5659
Object unprotectSingle(@SuppressWarnings("unused") int n,
60+
@Cached BranchProfile registerNativeRefProfile,
5761
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef,
5862
@CachedLibrary(limit = "1") StackLibrary stacks) {
5963
RContext ctx = ctxRef.get();
64+
RFFIContext rffiCtx = ctx.getRFFI();
6065
try {
61-
stacks.pop(ctx.getStateRFFI().rffiContextState.protectStack);
66+
popProtectedObject(ctx, rffiCtx, stacks, registerNativeRefProfile);
6267
} catch (IndexOutOfBoundsException e) {
6368
debugWarning("mismatched protect/unprotect (unprotect with empty protect stack)");
6469
}
@@ -69,12 +74,14 @@ Object unprotectSingle(@SuppressWarnings("unused") int n,
6974
@ExplodeLoop
7075
Object unprotectMultipleCached(@SuppressWarnings("unused") int n,
7176
@Cached("n") int nCached,
77+
@Cached BranchProfile registerNativeRefProfile,
7278
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef,
7379
@CachedLibrary(limit = "1") StackLibrary stacks) {
7480
RContext ctx = ctxRef.get();
81+
RFFIContext rffiCtx = ctx.getRFFI();
7582
try {
7683
for (int i = 0; i < nCached; i++) {
77-
stacks.pop(ctx.getStateRFFI().rffiContextState.protectStack);
84+
popProtectedObject(ctx, rffiCtx, stacks, registerNativeRefProfile);
7885
}
7986
} catch (IndexOutOfBoundsException e) {
8087
debugWarning("mismatched protect/unprotect (unprotect with empty protect stack)");
@@ -84,19 +91,31 @@ Object unprotectMultipleCached(@SuppressWarnings("unused") int n,
8491

8592
@Specialization(guards = "n > 1", replaces = "unprotectMultipleCached")
8693
Object unprotectMultipleUnchached(int n,
94+
@Cached BranchProfile registerNativeRefProfile,
8795
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef,
8896
@CachedLibrary(limit = "1") StackLibrary stacks) {
8997
RContext ctx = ctxRef.get();
98+
RFFIContext rffiCtx = ctx.getRFFI();
9099
try {
91100
for (int i = 0; i < n; i++) {
92-
stacks.pop(ctx.getStateRFFI().rffiContextState.protectStack);
101+
popProtectedObject(ctx, rffiCtx, stacks, registerNativeRefProfile);
93102
}
94103
} catch (IndexOutOfBoundsException e) {
95104
debugWarning("mismatched protect/unprotect (unprotect with empty protect stack)");
96105
}
97106
return RNull.instance;
98107
}
99108

109+
private static void popProtectedObject(RContext ctx, RFFIContext rffiCtx, StackLibrary stacks, BranchProfile registerNativeRefProfile) {
110+
Object removed = stacks.pop(ctx.getStateRFFI().rffiContextState.protectStack);
111+
// Developers expect the "unprotected" references to be still alive until next GNU-R
112+
// compatible GC cycle
113+
rffiCtx.registerReferenceUsedInNative(removed, registerNativeRefProfile);
114+
if (RFFILog.logEnabled()) {
115+
RFFILog.logRObject("Unprotected: ", removed);
116+
}
117+
}
118+
100119
private static boolean debugWarning(String message) {
101120
CompilerDirectives.transferToInterpreter();
102121
RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, message);

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/UnprotectPtrNode.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@
2323
package com.oracle.truffle.r.ffi.impl.nodes;
2424

2525
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
26+
import com.oracle.truffle.api.dsl.Cached;
2627
import com.oracle.truffle.api.dsl.CachedContext;
2728
import com.oracle.truffle.api.dsl.GenerateUncached;
2829
import com.oracle.truffle.api.dsl.Specialization;
30+
import com.oracle.truffle.api.profiles.BranchProfile;
2931
import com.oracle.truffle.r.runtime.Collections;
3032
import com.oracle.truffle.r.runtime.context.RContext;
3133
import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
3234
import com.oracle.truffle.r.runtime.data.RBaseObject;
3335
import com.oracle.truffle.r.runtime.ffi.RFFIContext;
36+
import com.oracle.truffle.r.runtime.ffi.RFFILog;
3437

3538
@GenerateUncached
3639
public abstract class UnprotectPtrNode extends FFIUpCallNode.Arg1 {
@@ -45,11 +48,18 @@ public static UnprotectPtrNode getUncached() {
4548

4649
@Specialization
4750
Object unprotect(RBaseObject x,
51+
@Cached BranchProfile registerNativeRefProfile,
4852
@CachedContext(TruffleRLanguage.class) ContextReference<RContext> ctxRef) {
4953
RFFIContext ctx = ctxRef.get().getStateRFFI();
5054
Collections.ArrayListObj<RBaseObject> stack = ctx.rffiContextState.protectStack;
5155
for (int i = stack.size() - 1; i >= 0; i--) {
52-
if (stack.get(i) == x) {
56+
RBaseObject current = stack.get(i);
57+
if (current == x) {
58+
if (RFFILog.logEnabled()) {
59+
RFFILog.logRObject("Unprotected: ", current);
60+
}
61+
ctx.registerReferenceUsedInNative(current, registerNativeRefProfile);
62+
stack.remove(i);
5363
return null;
5464
}
5565
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,15 +479,19 @@ public static Object lookup(long address) {
479479
}
480480

481481
private static RuntimeException reportDataAccessError(long address) {
482-
RuntimeException location = TRACE_MIRROR_ALLOCATION_SITES ? nativeMirrorInfo.get(address) : null;
483-
printDataAccessErrorLocation(location);
482+
if (TRACE_MIRROR_ALLOCATION_SITES) {
483+
printDataAccessErrorLocation(address);
484+
}
484485
throw RInternalError.shouldNotReachHere("unknown native reference " + address + "L / 0x" + Long.toHexString(address) + " (current id count: " + Long.toHexString(counter.get()) + ")");
485486
}
486487

487-
private static void printDataAccessErrorLocation(RuntimeException location) {
488+
private static void printDataAccessErrorLocation(long address) {
489+
RuntimeException location = nativeMirrorInfo.get(address);
488490
if (location != null) {
489491
System.out.println("Location at which the native mirror was allocated:");
490492
location.printStackTrace();
493+
} else {
494+
System.out.println("Location at which the native mirror was allocated was not recorded.");
491495
}
492496
}
493497

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFILog.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ private enum CallMode {
7474
}
7575
}
7676

77+
@TruffleBoundary
78+
public static void logRObject(String message, Object obj) {
79+
Object mirror = obj instanceof RBaseObject ? mirror = ((RBaseObject) obj).getNativeMirror() : null;
80+
log(String.format("%s [%s, native mirror: %s]", message, Utils.getDebugInfo(obj), mirror));
81+
}
82+
7783
public static void logUpCall(String name, List<Object> args) {
7884
logCall(CallMode.UP, name, getContext().getCallDepth(), args.toArray());
7985
}

0 commit comments

Comments
 (0)