Skip to content

Commit 6c6155f

Browse files
committed
Reduce lock overhead when calling markers.
1 parent 6f50749 commit 6c6155f

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

lib/truffle/truffle/cext.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,7 @@ def run_marker(obj)
15011501
data_holder = Primitive.object_hidden_var_get obj, DATA_HOLDER
15021502
data = Primitive.data_holder_get_data(data_holder)
15031503
# This call is done without pushing a new frame as the marking service manages frames itself.
1504-
Primitive.call_with_c_mutex(mark, [data]) unless Truffle::Interop.null?(data)
1504+
mark.call(data) unless Truffle::Interop.null?(data)
15051505
set_mark_list_on_object(obj)
15061506
end
15071507
end

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

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.truffleruby.builtins.Primitive;
3131
import org.truffleruby.builtins.PrimitiveArrayArgumentsNode;
3232
import org.truffleruby.builtins.YieldingCoreMethodNode;
33-
import org.truffleruby.cext.CExtNodesFactory.CallWithCExtLockNodeFactory;
3433
import org.truffleruby.cext.CExtNodesFactory.StringToNativeNodeGen;
3534
import org.truffleruby.cext.UnwrapNode.UnwrapCArrayNode;
3635
import org.truffleruby.core.MarkingService.ExtensionCallStack;
@@ -165,26 +164,56 @@ private static long getNativeStringCapacity(Pointer pointer) {
165164
@Primitive(name = "call_with_c_mutex_and_frame")
166165
public abstract static class CallWithCExtLockAndFrameNode extends PrimitiveArrayArgumentsNode {
167166

168-
@Child protected CallWithCExtLockNode callCextNode = CallWithCExtLockNodeFactory.create(RubyNode.EMPTY_ARRAY);
169167
@Child protected MarkingServiceNodes.RunMarkOnExitNode runMarksNode = MarkingServiceNodes.RunMarkOnExitNode
170168
.create();
171169

172-
@Specialization
170+
@Specialization(limit = "getCacheLimit()")
173171
protected Object callWithCExtLockAndFrame(
174-
VirtualFrame frame, Object receiver, RubyArray argsArray, Object specialVariables, Object block) {
175-
final ExtensionCallStack extensionStack = getLanguage().getCurrentFiber().extensionCallStack;
172+
VirtualFrame frame, Object receiver, RubyArray argsArray, Object specialVariables, Object block,
173+
@CachedLibrary("receiver") InteropLibrary receivers,
174+
@Cached ArrayToObjectArrayNode arrayToObjectArrayNode,
175+
@Cached TranslateInteropExceptionNode translateInteropExceptionNode,
176+
@Cached ConditionProfile ownedProfile,
177+
@Cached MarkingServiceNodes.RunMarkOnExitNode runMarksNode) {
178+
final ExtensionCallStack extensionStack = getLanguage()
179+
.getCurrentThread()
180+
.getCurrentFiber().extensionCallStack;
176181
final boolean keywordsGiven = RubyArguments.getDescriptor(frame) instanceof KeywordArgumentsDescriptor;
177182
extensionStack.push(keywordsGiven, specialVariables, block);
178183
try {
179-
try {
180-
return callCextNode.execute(receiver, argsArray);
181-
} finally {
182-
runMarksNode.execute(extensionStack);
184+
final Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray);
185+
186+
if (getContext().getOptions().CEXT_LOCK) {
187+
final ReentrantLock lock = getContext().getCExtensionsLock();
188+
boolean owned = ownedProfile.profile(lock.isHeldByCurrentThread());
189+
190+
if (!owned) {
191+
MutexOperations.lockInternal(getContext(), lock, this);
192+
}
193+
try {
194+
return InteropNodes.execute(receiver, args, receivers, translateInteropExceptionNode);
195+
} finally {
196+
runMarksNode.execute(extensionStack);
197+
if (!owned) {
198+
MutexOperations.unlockInternal(lock);
199+
}
200+
}
201+
} else {
202+
try {
203+
return InteropNodes.execute(receiver, args, receivers, translateInteropExceptionNode);
204+
} finally {
205+
runMarksNode.execute(extensionStack);
206+
}
183207
}
208+
184209
} finally {
185210
extensionStack.pop();
186211
}
187212
}
213+
214+
protected int getCacheLimit() {
215+
return getLanguage().options.DISPATCH_CACHE;
216+
}
188217
}
189218

190219
@Primitive(name = "call_with_c_mutex_and_frame_and_unwrap")

src/main/java/org/truffleruby/core/array/ArrayToObjectArrayNode.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
import org.truffleruby.language.RubyBaseNode;
1414

1515
import com.oracle.truffle.api.dsl.Bind;
16+
import com.oracle.truffle.api.dsl.Cached;
1617
import com.oracle.truffle.api.dsl.ImportStatic;
1718
import com.oracle.truffle.api.dsl.Specialization;
1819
import com.oracle.truffle.api.library.CachedLibrary;
20+
import com.oracle.truffle.api.profiles.IntValueProfile;
1921

2022
@ImportStatic(ArrayGuards.class)
2123
public abstract class ArrayToObjectArrayNode extends RubyBaseNode {
@@ -34,8 +36,9 @@ public Object[] unsplat(Object[] arguments) {
3436
@Specialization(limit = "storageStrategyLimit()")
3537
protected Object[] toObjectArrayOther(RubyArray array,
3638
@Bind("array.getStore()") Object store,
39+
@Cached("createIdentityProfile()") IntValueProfile sizeProfile,
3740
@CachedLibrary("store") ArrayStoreLibrary stores) {
38-
final int size = array.size;
41+
final int size = sizeProfile.profile(array.size);
3942
return stores.boxedCopyOfRange(store, 0, size);
4043
}
4144

0 commit comments

Comments
 (0)