Skip to content

Commit fb6e9d9

Browse files
committed
[GR-33075] Move marking and handle thread local data to RubyFiber.
PullRequest: truffleruby/2872
2 parents e66e124 + 6039aec commit fb6e9d9

File tree

15 files changed

+92
-248
lines changed

15 files changed

+92
-248
lines changed

src/main/java/org/truffleruby/RubyContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ public RubyContext(RubyLanguage language, TruffleLanguage.Env env) {
210210
coreLibrary = new CoreLibrary(this, language);
211211
nativeConfiguration = NativeConfiguration.loadNativeConfiguration(this);
212212
coreLibrary.initialize();
213-
valueWrapperManager = new ValueWrapperManager(this);
213+
valueWrapperManager = new ValueWrapperManager();
214214
Metrics.printTime("after-create-core-library");
215215

216216
rootLexicalScope = new LexicalScope(null, coreLibrary.objectClass);

src/main/java/org/truffleruby/cext/CExtNodes.java

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,10 @@ public abstract static class CallWithCExtLockAndFrameNode extends PrimitiveArray
125125

126126
@Specialization
127127
protected Object callWithCExtLockAndFrame(
128-
Object receiver, RubyArray argsArray, Object specialVariables, Object block,
129-
@Cached MarkingServiceNodes.GetMarkerThreadLocalDataNode getDataNode) {
130-
final ExtensionCallStack extensionStack = getDataNode.execute().getExtensionCallStack();
128+
Object receiver, RubyArray argsArray, Object specialVariables, Object block) {
129+
final ExtensionCallStack extensionStack = getLanguage()
130+
.getCurrentThread()
131+
.getCurrentFiber().extensionCallStack;
131132
extensionStack.push(specialVariables, block);
132133
try {
133134
return callCextNode.execute(receiver, argsArray);
@@ -693,19 +694,17 @@ protected RubyString trStrCapaResize(RubyString string, int newCapacity,
693694
public abstract static class BlockProcNode extends CoreMethodArrayArgumentsNode {
694695

695696
@Specialization
696-
protected Object block(
697-
@Cached MarkingServiceNodes.GetMarkerThreadLocalDataNode getDataNode) {
698-
return getDataNode.execute().getExtensionCallStack().getBlock();
697+
protected Object block() {
698+
return getLanguage().getCurrentThread().getCurrentFiber().extensionCallStack.getBlock();
699699
}
700700
}
701701

702702
@Primitive(name = "cext_special_variables_from_stack")
703703
public abstract static class VarsFromStackNode extends PrimitiveArrayArgumentsNode {
704704

705705
@Specialization
706-
protected Object variables(
707-
@Cached MarkingServiceNodes.GetMarkerThreadLocalDataNode getDataNode) {
708-
return getDataNode.execute().getExtensionCallStack().getVariables();
706+
protected Object variables() {
707+
return getLanguage().getCurrentThread().getCurrentFiber().extensionCallStack.getVariables();
709708
}
710709
}
711710

@@ -1568,9 +1567,8 @@ protected Object createMarker(RubyDynamicObject object, RubyProc marker) {
15681567
public abstract static class PushPreservingFrame extends CoreMethodArrayArgumentsNode {
15691568

15701569
@Specialization
1571-
protected Object pushFrame(Object variables, RubyProc block,
1572-
@Cached MarkingServiceNodes.GetMarkerThreadLocalDataNode getDataNode) {
1573-
getDataNode.execute().getExtensionCallStack().push(variables, block);
1570+
protected Object pushFrame(Object variables, RubyProc block) {
1571+
getLanguage().getCurrentThread().getCurrentFiber().extensionCallStack.push(variables, block);
15741572
return nil;
15751573
}
15761574
}
@@ -1579,9 +1577,8 @@ protected Object pushFrame(Object variables, RubyProc block,
15791577
public abstract static class PopPreservingFrame extends CoreMethodArrayArgumentsNode {
15801578

15811579
@Specialization
1582-
protected Object popFrame(
1583-
@Cached MarkingServiceNodes.GetMarkerThreadLocalDataNode getDataNode) {
1584-
getDataNode.execute().getExtensionCallStack().pop();
1580+
protected Object popFrame() {
1581+
getLanguage().getCurrentThread().getCurrentFiber().extensionCallStack.pop();
15851582
return nil;
15861583
}
15871584
}

src/main/java/org/truffleruby/cext/ValueWrapperManager.java

Lines changed: 31 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import org.truffleruby.RubyLanguage;
1919
import org.truffleruby.SuppressFBWarnings;
2020
import org.truffleruby.cext.ValueWrapperManagerFactory.AllocateHandleNodeGen;
21-
import org.truffleruby.cext.ValueWrapperManagerFactory.GetHandleBlockHolderNodeGen;
2221
import org.truffleruby.extra.ffi.Pointer;
2322
import org.truffleruby.language.ImmutableRubyObject;
2423
import org.truffleruby.language.NotProvided;
@@ -60,35 +59,8 @@ public class ValueWrapperManager {
6059

6160
private volatile HandleBlockWeakReference[] blockMap = new HandleBlockWeakReference[0];
6261

63-
private final ThreadLocal<HandleThreadData> threadBlocks;
64-
65-
private final RubyContext context;
66-
67-
public ValueWrapperManager(RubyContext context) {
68-
this.context = context;
69-
this.threadBlocks = ThreadLocal.withInitial(this::makeThreadData);
70-
}
71-
72-
public HandleThreadData makeThreadData() {
73-
HandleThreadData threadData = new HandleThreadData();
74-
HandleBlockHolder holder = threadData.holder;
75-
context.getFinalizationService().addFinalizer(
76-
context,
77-
threadData,
78-
ValueWrapperManager.class,
79-
() -> context.getMarkingService().queueForMarking(holder.handleBlock),
80-
null);
81-
return threadData;
82-
}
83-
84-
@TruffleBoundary
85-
public HandleThreadData getBlockHolder() {
86-
return threadBlocks.get();
87-
}
88-
89-
@TruffleBoundary
90-
public void cleanupBlockHolder() {
91-
threadBlocks.remove();
62+
public static HandleBlockHolder getBlockHolder(RubyContext context, RubyLanguage language) {
63+
return language.getCurrentThread().getCurrentFiber().handleData;
9264
}
9365

9466
/* We keep a map of long wrappers that have been generated because various C extensions assume that any given fixnum
@@ -102,7 +74,7 @@ public ValueWrapper doubleWrapper(double value) {
10274
}
10375

10476
@TruffleBoundary
105-
public synchronized void addToBlockMap(HandleBlock block, RubyLanguage language) {
77+
public synchronized void addToBlockMap(HandleBlock block, RubyContext context, RubyLanguage language) {
10678
int blockIndex = block.getIndex();
10779
long blockBase = block.getBase();
10880
HandleBlockAllocator allocator = language.handleBlockAllocator;
@@ -117,7 +89,7 @@ public synchronized void addToBlockMap(HandleBlock block, RubyLanguage language)
11789
}
11890

11991
@TruffleBoundary
120-
public void addToSharedBlockMap(HandleBlock block, RubyLanguage language) {
92+
public void addToSharedBlockMap(HandleBlock block, RubyContext context, RubyLanguage language) {
12193
synchronized (language) {
12294
int blockIndex = block.getIndex();
12395
long blockBase = block.getBase();
@@ -186,6 +158,11 @@ public void freeAllBlocksInMap(RubyLanguage language) {
186158
}
187159
}
188160

161+
public void cleanup(RubyContext context, HandleBlockHolder holder) {
162+
context.getMarkingService().queueForMarking(holder.handleBlock);
163+
holder.handleBlock = null;
164+
}
165+
189166
protected static class FreeHandleBlock {
190167
public final long start;
191168
public final FreeHandleBlock next;
@@ -299,86 +276,43 @@ public static final class HandleBlockWeakReference extends WeakReference<HandleB
299276
}
300277
}
301278

302-
protected static class HandleBlockHolder {
279+
public static class HandleBlockHolder {
303280
protected HandleBlock handleBlock = null;
304281
protected HandleBlock sharedHandleBlock = null;
305282
}
306283

307-
protected static class HandleThreadData {
308-
309-
private final HandleBlockHolder holder = new HandleBlockHolder();
310-
311-
public HandleBlock currentBlock() {
312-
return holder.handleBlock;
313-
}
314-
315-
public HandleBlock currentSharedBlock() {
316-
return holder.sharedHandleBlock;
317-
}
318-
319-
public HandleBlock makeNewBlock(RubyContext context, HandleBlockAllocator allocator) {
320-
return (holder.handleBlock = new HandleBlock(context, allocator));
321-
}
322-
323-
public HandleBlock makeNewSharedBlock(RubyContext context, HandleBlockAllocator allocator) {
324-
return (holder.sharedHandleBlock = new HandleBlock(context, allocator));
325-
}
326-
}
327-
328-
@GenerateUncached
329-
public abstract static class GetHandleBlockHolderNode extends RubyBaseNode {
330-
331-
public abstract HandleThreadData execute(ValueWrapper wrapper);
332-
333-
@Specialization(guards = "cachedThread == currentJavaThread(wrapper)", limit = "getCacheLimit()")
334-
protected HandleThreadData getHolderOnKnownThread(ValueWrapper wrapper,
335-
@Cached("currentJavaThread(wrapper)") Thread cachedThread,
336-
@Cached("getBlockHolder(wrapper)") HandleThreadData threadData) {
337-
return threadData;
338-
}
339-
340-
@Specialization(replaces = "getHolderOnKnownThread")
341-
protected HandleThreadData getBlockHolder(ValueWrapper wrapper) {
342-
return getContext().getValueWrapperManager().getBlockHolder();
343-
}
344-
345-
protected static Thread currentJavaThread(ValueWrapper wrapper) {
346-
return Thread.currentThread();
347-
}
348-
349-
public int getCacheLimit() {
350-
return getLanguage().options.THREAD_CACHE;
351-
}
352-
353-
public static GetHandleBlockHolderNode create() {
354-
return GetHandleBlockHolderNodeGen.create();
355-
}
356-
}
357-
358284
@GenerateUncached
359285
public abstract static class AllocateHandleNode extends RubyBaseNode {
360286

361287
public abstract long execute(ValueWrapper wrapper);
362288

363289
@Specialization(guards = "!isSharedObject(wrapper)")
364-
protected long allocateHandleOnKnownThread(ValueWrapper wrapper,
365-
@Cached GetHandleBlockHolderNode getBlockHolderNode) {
366-
return allocateHandle(wrapper, getContext(), getLanguage(), getBlockHolderNode.execute(wrapper), false);
290+
protected long allocateHandleOnKnownThread(ValueWrapper wrapper) {
291+
return allocateHandle(
292+
wrapper,
293+
getContext(),
294+
getLanguage(),
295+
getBlockHolder(getContext(), getLanguage()),
296+
false);
367297
}
368298

369299
@Specialization(guards = "isSharedObject(wrapper)")
370-
protected long allocateSharedHandleOnKnownThread(ValueWrapper wrapper,
371-
@Cached GetHandleBlockHolderNode getBlockHolderNode) {
372-
return allocateHandle(wrapper, getContext(), getLanguage(), getBlockHolderNode.execute(wrapper), true);
300+
protected long allocateSharedHandleOnKnownThread(ValueWrapper wrapper) {
301+
return allocateHandle(
302+
wrapper,
303+
getContext(),
304+
getLanguage(),
305+
getBlockHolder(getContext(), getLanguage()),
306+
true);
373307
}
374308

375309
protected static long allocateHandle(ValueWrapper wrapper, RubyContext context, RubyLanguage language,
376-
HandleThreadData threadData, boolean shared) {
310+
HandleBlockHolder holder, boolean shared) {
377311
HandleBlock block;
378312
if (shared) {
379-
block = threadData.holder.sharedHandleBlock;
313+
block = holder.sharedHandleBlock;
380314
} else {
381-
block = threadData.holder.handleBlock;
315+
block = holder.handleBlock;
382316
}
383317

384318
if (context.getOptions().CEXTS_TO_NATIVE_STATS) {
@@ -390,13 +324,11 @@ protected static long allocateHandle(ValueWrapper wrapper, RubyContext context,
390324
context.getMarkingService().queueForMarking(block);
391325
}
392326
if (shared) {
393-
block = threadData
394-
.makeNewSharedBlock(context, language.handleBlockAllocator);
395-
context.getValueWrapperManager().addToSharedBlockMap(block, language);
327+
block = (holder.sharedHandleBlock = new HandleBlock(context, language.handleBlockAllocator));
328+
context.getValueWrapperManager().addToSharedBlockMap(block, context, language);
396329
} else {
397-
block = threadData
398-
.makeNewBlock(context, language.handleBlockAllocator);
399-
context.getValueWrapperManager().addToBlockMap(block, language);
330+
block = (holder.handleBlock = new HandleBlock(context, language.handleBlockAllocator));
331+
context.getValueWrapperManager().addToBlockMap(block, context, language);
400332
}
401333

402334
}

src/main/java/org/truffleruby/core/FinalizationService.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.Objects;
1515

1616
import org.truffleruby.RubyContext;
17+
import org.truffleruby.RubyLanguage;
1718
import org.truffleruby.core.MarkingService.ExtensionCallStack;
1819
import org.truffleruby.language.RubyDynamicObject;
1920

@@ -85,14 +86,16 @@ public final void drainFinalizationQueue(RubyContext context) {
8586
}
8687

8788
@Override
88-
protected void processReference(RubyContext context, ProcessingReference<?> finalizerReference) {
89-
super.processReference(context, finalizerReference);
89+
protected void processReference(RubyContext context, RubyLanguage language,
90+
ProcessingReference<?> finalizerReference) {
91+
super.processReference(context, language, finalizerReference);
9092

91-
runCatchingErrors(context, this::processReferenceInternal, (FinalizerReference) finalizerReference);
93+
runCatchingErrors(context, language, this::processReferenceInternal, (FinalizerReference) finalizerReference);
9294
}
9395

94-
protected void processReferenceInternal(RubyContext context, FinalizerReference finalizerReference) {
95-
ExtensionCallStack stack = context.getMarkingService().getThreadLocalData().getExtensionCallStack();
96+
protected void processReferenceInternal(RubyContext context, RubyLanguage language,
97+
FinalizerReference finalizerReference) {
98+
final ExtensionCallStack stack = language.getCurrentThread().getCurrentFiber().extensionCallStack;
9699
stack.push(stack.getVariables(), stack.getBlock());
97100
try {
98101
while (!context.isFinalizing()) {

0 commit comments

Comments
 (0)