Skip to content

Commit e03d4fd

Browse files
committed
Manage the thread-local IO buffer manually rather than using a finalizer
* Avoids creating the finalizer thread very early when not really needed. * Fixes sharing being triggered by operations using the thread IO buffer such as File.read.
1 parent e8beb21 commit e03d4fd

File tree

4 files changed

+17
-5
lines changed

4 files changed

+17
-5
lines changed

spec/truffle/thread_safe_objects_spec.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,4 +281,8 @@ def wb; @wb; end
281281
ruby_exe("p Truffle::Debug.shared?(Object)").should == "false\n"
282282
end
283283

284+
it "thread-local IO buffers which should not trigger sharing" do
285+
ruby_exe("File.read(#{__FILE__.inspect}); p Truffle::Debug.shared?(Object)").should == "false\n"
286+
end
287+
284288
end

src/main/java/org/truffleruby/core/support/IONodes.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,6 @@ public int write(int fd, DynamicObject string) {
477477
@Primitive(name = "io_get_thread_buffer", needsSelf = false)
478478
public static abstract class GetThreadBufferNode extends PrimitiveArrayArgumentsNode {
479479

480-
private static final ThreadLocal<Pointer> THREAD_BUFFER_THREAD_LOCAL = ThreadLocal.withInitial(() -> Pointer.NULL);
481-
482480
@Specialization
483481
public DynamicObject getThreadBuffer(long size,
484482
@Cached("create()") AllocateObjectNode allocateObjectNode) {
@@ -487,13 +485,15 @@ public DynamicObject getThreadBuffer(long size,
487485

488486
@TruffleBoundary
489487
public static Pointer getBuffer(RubyContext context, long size) {
490-
final Pointer buffer = THREAD_BUFFER_THREAD_LOCAL.get();
488+
final DynamicObject rubyThread = context.getThreadManager().getCurrentThread();
489+
final Pointer buffer = Layouts.THREAD.getIoBuffer(rubyThread);
490+
491491
if (buffer.getSize() >= size) {
492492
return buffer;
493493
} else {
494+
buffer.freeNoAutorelease();
494495
final Pointer newBuffer = Pointer.malloc(Math.max(size * 2, 1024));
495-
newBuffer.enableAutorelease(context.getFinalizationService());
496-
THREAD_BUFFER_THREAD_LOCAL.set(newBuffer);
496+
Layouts.THREAD.setIoBuffer(rubyThread, newBuffer);
497497
return newBuffer;
498498
}
499499
}

src/main/java/org/truffleruby/core/thread/ThreadLayout.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.truffleruby.core.InterruptMode;
1919
import org.truffleruby.core.basicobject.BasicObjectLayout;
2020
import org.truffleruby.core.fiber.FiberManager;
21+
import org.truffleruby.extra.ffi.Pointer;
2122
import org.truffleruby.language.threadlocal.ThreadLocalGlobals;
2223

2324
import java.util.List;
@@ -45,6 +46,7 @@ Object[] build(
4546
@Nullable @Volatile Object value,
4647
AtomicBoolean wakeUp,
4748
@Volatile int priority,
49+
Pointer ioBuffer,
4850
DynamicObject threadGroup,
4951
String sourceLocation,
5052
DynamicObject name);
@@ -85,6 +87,9 @@ Object[] build(
8587
int getPriority(DynamicObject object);
8688
void setPriority(DynamicObject object, int value);
8789

90+
Pointer getIoBuffer(DynamicObject object);
91+
void setIoBuffer(DynamicObject object, Pointer value);
92+
8893
DynamicObject getThreadGroup(DynamicObject object);
8994
void setThreadGroup(DynamicObject object, DynamicObject value);
9095

src/main/java/org/truffleruby/core/thread/ThreadManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ private Object[] packThreadFields(DynamicObject currentGroup, String info) {
183183
null,
184184
new AtomicBoolean(false),
185185
Thread.NORM_PRIORITY,
186+
Pointer.NULL,
186187
currentGroup,
187188
info,
188189
nil());
@@ -336,6 +337,8 @@ public void cleanup(DynamicObject thread, Thread javaThread) {
336337
final FiberManager fiberManager = Layouts.THREAD.getFiberManager(thread);
337338
fiberManager.shutdown(javaThread);
338339

340+
Layouts.THREAD.getIoBuffer(thread).freeNoAutorelease();
341+
339342
unregisterThread(thread);
340343
Layouts.THREAD.setThread(thread, null);
341344

0 commit comments

Comments
 (0)