Skip to content

Commit 5a28177

Browse files
committed
Convert HashStringNode to DSL inlinable
1 parent 4c0e900 commit 5a28177

File tree

7 files changed

+88
-53
lines changed

7 files changed

+88
-53
lines changed

src/main/java/org/truffleruby/core/hash/HashingNodes.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,15 @@ protected static int hashBignum(Node node, RubyBignum value) {
9999
}
100100

101101
@Specialization
102-
protected static int hashString(RubyString value,
102+
protected static int hashString(Node node, RubyString value,
103103
@Shared @Cached StringHelperNodes.HashStringNode stringHashNode) {
104-
return (int) stringHashNode.execute(value);
104+
return (int) stringHashNode.execute(node, value);
105105
}
106106

107107
@Specialization
108-
protected static int hashImmutableString(ImmutableRubyString value,
108+
protected static int hashImmutableString(Node node, ImmutableRubyString value,
109109
@Shared @Cached StringHelperNodes.HashStringNode stringHashNode) {
110-
return (int) stringHashNode.execute(value);
110+
return (int) stringHashNode.execute(node, value);
111111
}
112112

113113
@Specialization

src/main/java/org/truffleruby/core/kernel/KernelNodes.java

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
import org.truffleruby.language.objects.IsCopyableObjectNode;
135135
import org.truffleruby.language.objects.IsCopyableObjectNodeGen;
136136
import org.truffleruby.language.objects.IsFrozenNode;
137+
import org.truffleruby.language.objects.LazySingletonClassNode;
137138
import org.truffleruby.language.objects.LogicalClassNode;
138139
import org.truffleruby.language.objects.MetaClassNode;
139140
import org.truffleruby.language.objects.ShapeCachingGuards;
@@ -554,24 +555,24 @@ protected RubyDynamicObject copy(RubyIntOrLongRange range,
554555
public abstract static class CloneNode extends PrimitiveArrayArgumentsNode {
555556

556557
@Child IsCopyableObjectNode isCopyableObjectNode = IsCopyableObjectNodeGen.create();
557-
@Child SingletonClassNode singletonClassNode;
558-
private final BranchProfile cantUnfreezeErrorProfile = BranchProfile.create();
559558

560559
@Specialization(guards = "isCopyableObjectNode.execute(object)")
561-
protected RubyDynamicObject copyable(Object object, Object freeze,
560+
protected static RubyDynamicObject copyable(Object object, Object freeze,
562561
@Cached MetaClassNode metaClassNode,
563562
@Cached CopyNode copyNode,
564563
@Cached DispatchNode initializeCloneNode,
565564
@Cached InlinedConditionProfile isSingletonProfile,
566565
@Cached HashingNodes.ToHashByHashCode hashNode,
567566
@Cached IsFrozenNode isFrozenNode,
568-
@Cached FreezeNode freezeNode) {
567+
@Cached FreezeNode freezeNode,
568+
@Cached LazySingletonClassNode lazySingletonClassNode,
569+
@Bind("this") Node node) {
569570
final RubyDynamicObject newObject = copyNode.executeCopy(object);
570571

571572
// Copy the singleton class if any.
572-
final RubyClass selfMetaClass = metaClassNode.execute(this, object);
573-
if (isSingletonProfile.profile(this, selfMetaClass.isSingleton)) {
574-
final RubyClass newObjectMetaClass = executeSingletonClass(newObject);
573+
final RubyClass selfMetaClass = metaClassNode.execute(node, object);
574+
if (isSingletonProfile.profile(node, selfMetaClass.isSingleton)) {
575+
final RubyClass newObjectMetaClass = lazySingletonClassNode.get(node).executeSingletonClass(newObject);
575576
newObjectMetaClass.fields.initCopy(selfMetaClass);
576577
}
577578

@@ -581,7 +582,7 @@ protected RubyDynamicObject copyable(Object object, Object freeze,
581582
initializeCloneNode.call(newObject, "initialize_clone", object);
582583
} else {
583584
// pass :freeze keyword argument to #initialize_clone
584-
final RubyHash keywordArguments = createFreezeBooleanHash((boolean) freeze, hashNode);
585+
final RubyHash keywordArguments = createFreezeBooleanHash(node, (boolean) freeze, hashNode);
585586
initializeCloneNode.callWithKeywords(newObject, "initialize_clone", object, keywordArguments);
586587
}
587588

@@ -594,24 +595,27 @@ protected RubyDynamicObject copyable(Object object, Object freeze,
594595
}
595596

596597
@Specialization(guards = "!isCopyableObjectNode.execute(object)")
597-
protected Object notCopyable(Object object, Object freeze) {
598+
protected Object notCopyable(Object object, Object freeze,
599+
@Cached InlinedBranchProfile cantUnfreezeErrorProfile) {
598600
if (forceNotFrozen(freeze)) {
599-
raiseCantUnfreezeError(object);
601+
raiseCantUnfreezeError(cantUnfreezeErrorProfile, object);
600602
}
601603
return object;
602604
}
603605

604-
private RubyHash createFreezeBooleanHash(boolean freeze, HashingNodes.ToHashByHashCode hashNode) {
605-
final RubySymbol key = coreSymbols().FREEZE;
606+
private static RubyHash createFreezeBooleanHash(Node node, boolean freeze,
607+
HashingNodes.ToHashByHashCode hashNode) {
608+
final RubySymbol key = coreSymbols(node).FREEZE;
606609

607610
final Object[] newStore = PackedHashStoreLibrary.createStore();
608-
final int hashed = hashNode.execute(this, key);
611+
final int hashed = hashNode.execute(node, key);
609612
PackedHashStoreLibrary.setHashedKeyValue(newStore, 0, hashed, key, freeze);
610613

611-
return new RubyHash(coreLibrary().hashClass, getLanguage().hashShape, getContext(), newStore, 1, false);
614+
return new RubyHash(coreLibrary(node).hashClass, getLanguage(node).hashShape, getContext(node), newStore, 1,
615+
false);
612616
}
613617

614-
private boolean forceFrozen(Object freeze) {
618+
private static boolean forceFrozen(Object freeze) {
615619
return freeze instanceof Boolean && (boolean) freeze;
616620

617621
}
@@ -620,20 +624,10 @@ private boolean forceNotFrozen(Object freeze) {
620624
return freeze instanceof Boolean && !(boolean) freeze;
621625
}
622626

623-
private void raiseCantUnfreezeError(Object object) {
624-
cantUnfreezeErrorProfile.enter();
627+
private void raiseCantUnfreezeError(InlinedBranchProfile cantUnfreezeErrorProfile, Object object) {
628+
cantUnfreezeErrorProfile.enter(this);
625629
throw new RaiseException(getContext(), coreExceptions().argumentErrorCantUnfreeze(object, this));
626630
}
627-
628-
private RubyClass executeSingletonClass(RubyDynamicObject newObject) {
629-
if (singletonClassNode == null) {
630-
CompilerDirectives.transferToInterpreterAndInvalidate();
631-
singletonClassNode = insert(SingletonClassNode.create());
632-
}
633-
634-
return singletonClassNode.executeSingletonClass(newObject);
635-
}
636-
637631
}
638632

639633
// Worth always splitting to have monomorphic #__allocate__, Shape, #initialize_dup and #initialize_copy.
@@ -886,15 +880,17 @@ protected long hashBignum(RubyBignum value) {
886880
}
887881

888882
@Specialization
889-
protected long hashString(RubyString value,
890-
@Cached @Exclusive StringHelperNodes.HashStringNode stringHashNode) {
891-
return stringHashNode.execute(value);
883+
protected static long hashString(RubyString value,
884+
@Cached @Exclusive StringHelperNodes.HashStringNode stringHashNode,
885+
@Bind("this") Node node) {
886+
return stringHashNode.execute(node, value);
892887
}
893888

894889
@Specialization
895-
protected long hashImmutableString(ImmutableRubyString value,
896-
@Cached @Exclusive StringHelperNodes.HashStringNode stringHashNode) {
897-
return stringHashNode.execute(value);
890+
protected static long hashImmutableString(ImmutableRubyString value,
891+
@Cached @Exclusive StringHelperNodes.HashStringNode stringHashNode,
892+
@Bind("this") Node node) {
893+
return stringHashNode.execute(node, value);
898894
}
899895

900896
@Specialization

src/main/java/org/truffleruby/core/string/StringHelperNodes.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import com.oracle.truffle.api.dsl.Cached;
1515
import com.oracle.truffle.api.dsl.Cached.Shared;
1616
import com.oracle.truffle.api.dsl.Cached.Exclusive;
17+
import com.oracle.truffle.api.dsl.GenerateCached;
18+
import com.oracle.truffle.api.dsl.GenerateInline;
1719
import com.oracle.truffle.api.dsl.GenerateUncached;
1820
import com.oracle.truffle.api.dsl.ImportStatic;
1921
import com.oracle.truffle.api.dsl.NeverDefault;
@@ -373,23 +375,20 @@ private static TruffleString processStr(Node node, RubyString string, boolean[]
373375
}
374376

375377
@GenerateUncached
378+
@GenerateCached(false)
379+
@GenerateInline
376380
public abstract static class HashStringNode extends RubyBaseNode {
377381

378382
protected static final int CLASS_SALT = 54008340; // random number, stops hashes for similar values but different classes being the same, static because we want deterministic hashes
379383

380-
@NeverDefault
381-
public static HashStringNode create() {
382-
return StringHelperNodesFactory.HashStringNodeGen.create();
383-
}
384-
385-
public abstract long execute(Object string);
384+
public abstract long execute(Node node, Object string);
386385

387386
@Specialization
388-
protected long hash(Object string,
387+
protected static long hash(Node node, Object string,
389388
@Cached RubyStringLibrary strings,
390-
@Cached TruffleString.HashCodeNode hashCodeNode) {
389+
@Cached(inline = false) TruffleString.HashCodeNode hashCodeNode) {
391390
int hashCode = hashCodeNode.execute(strings.getTString(string), strings.getTEncoding(string));
392-
return getContext().getHashing(this).hash(CLASS_SALT, hashCode);
391+
return getContext(node).getHashing(node).hash(CLASS_SALT, hashCode);
393392
}
394393
}
395394

src/main/java/org/truffleruby/core/string/StringNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,7 @@ public static HashNode create() {
14701470
@Specialization
14711471
protected long hash(Object string,
14721472
@Cached StringHelperNodes.HashStringNode hash) {
1473-
return hash.execute(string);
1473+
return hash.execute(this, string);
14741474
}
14751475
}
14761476

src/main/java/org/truffleruby/extra/ConcurrentMapNodes.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
package org.truffleruby.extra;
1111

1212
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
13+
import com.oracle.truffle.api.dsl.Bind;
1314
import com.oracle.truffle.api.dsl.Cached;
1415
import com.oracle.truffle.api.dsl.Cached.Exclusive;
1516
import com.oracle.truffle.api.dsl.Specialization;
17+
import com.oracle.truffle.api.nodes.Node;
1618
import com.oracle.truffle.api.object.Shape;
1719
import org.truffleruby.annotations.CoreMethod;
1820
import org.truffleruby.annotations.CoreModule;
@@ -214,9 +216,10 @@ protected boolean replacePairPrimitive(
214216
}
215217

216218
@Specialization(guards = "!isPrimitive(expectedValue)")
217-
protected boolean replacePair(RubyConcurrentMap self, Object key, Object expectedValue, Object newValue,
218-
@Exclusive @Cached ToHashByHashCode hashNode) {
219-
final int hashCode = hashNode.execute(this, key);
219+
protected static boolean replacePair(RubyConcurrentMap self, Object key, Object expectedValue, Object newValue,
220+
@Exclusive @Cached ToHashByHashCode hashNode,
221+
@Bind("this") Node node) {
222+
final int hashCode = hashNode.execute(node, key);
220223
return replace(self.getMap(), new Key(key, hashCode), expectedValue, newValue);
221224
}
222225

@@ -251,9 +254,10 @@ protected boolean deletePairPrimitive(RubyConcurrentMap self, Object key, Object
251254
}
252255

253256
@Specialization(guards = "!isPrimitive(expectedValue)")
254-
protected boolean deletePair(RubyConcurrentMap self, Object key, Object expectedValue,
255-
@Exclusive @Cached ToHashByHashCode hashNode) {
256-
final int hashCode = hashNode.execute(this, key);
257+
protected static boolean deletePair(RubyConcurrentMap self, Object key, Object expectedValue,
258+
@Exclusive @Cached ToHashByHashCode hashNode,
259+
@Bind("this") Node node) {
260+
final int hashCode = hashNode.execute(node, key);
257261
return remove(self.getMap(), new Key(key, hashCode), expectedValue);
258262
}
259263

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.language.objects;
11+
12+
import com.oracle.truffle.api.dsl.Cached;
13+
import com.oracle.truffle.api.dsl.GenerateCached;
14+
import com.oracle.truffle.api.dsl.GenerateInline;
15+
import com.oracle.truffle.api.dsl.Specialization;
16+
import com.oracle.truffle.api.nodes.Node;
17+
import org.truffleruby.language.RubyBaseNode;
18+
19+
@GenerateInline
20+
@GenerateCached(false)
21+
public abstract class LazySingletonClassNode extends RubyBaseNode {
22+
23+
public final SingletonClassNode get(Node node) {
24+
return execute(node);
25+
}
26+
27+
protected abstract SingletonClassNode execute(Node node);
28+
29+
@Specialization
30+
protected static SingletonClassNode doLazy(
31+
@Cached(inline = false) SingletonClassNode singletonClassNode) {
32+
return singletonClassNode;
33+
}
34+
}

src/main/java/org/truffleruby/language/objects/SingletonClassNode.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.truffleruby.language.objects;
1111

1212
import com.oracle.truffle.api.dsl.GenerateUncached;
13+
import com.oracle.truffle.api.dsl.NeverDefault;
1314
import org.truffleruby.RubyContext;
1415
import org.truffleruby.core.klass.ClassNodes;
1516
import org.truffleruby.core.klass.RubyClass;
@@ -35,6 +36,7 @@ public static SingletonClassNode getUncached() {
3536
return SingletonClassNodeGen.getUncached();
3637
}
3738

39+
@NeverDefault
3840
public static SingletonClassNode create() {
3941
return SingletonClassNodeGen.create(null);
4042
}

0 commit comments

Comments
 (0)