34
34
import org .truffleruby .core .hash .HashNodesFactory .HashLookupOrExecuteDefaultNodeGen ;
35
35
import org .truffleruby .core .hash .HashNodesFactory .InitializeCopyNodeFactory ;
36
36
import org .truffleruby .core .hash .HashNodesFactory .InternalRehashNodeGen ;
37
- import org .truffleruby .language .NotOptimizedWarningNode ;
38
37
import org .truffleruby .language .NotProvided ;
39
38
import org .truffleruby .language .RubyBaseNode ;
40
39
import org .truffleruby .language .RubyGuards ;
@@ -683,8 +682,8 @@ private Object yieldPair(DynamicObject block, Object key, Object value) {
683
682
}
684
683
685
684
@ ImportStatic (HashGuards .class )
686
- @ CoreMethod ( names = "merge " , required = 1 , needsBlock = true )
687
- public abstract static class MergeNode extends YieldingCoreMethodNode {
685
+ @ Primitive ( name = "hash_merge " , needsSelf = false )
686
+ public abstract static class MergeNode extends PrimitiveArrayArgumentsNode {
688
687
689
688
@ Child private LookupEntryNode lookupEntryNode ;
690
689
@ Child private SetNode setNode = SetNode .create ();
@@ -694,38 +693,38 @@ public abstract static class MergeNode extends YieldingCoreMethodNode {
694
693
// Merge with an empty hash, without a block
695
694
696
695
@ Specialization (guards = {"isNullHash(hash)" , "isRubyHash(other)" , "isNullHash(other)" })
697
- public DynamicObject mergeEmptyEmpty (DynamicObject hash , DynamicObject other , NotProvided block ) {
696
+ public DynamicObject mergeEmptyEmpty (DynamicObject hash , DynamicObject other ) {
698
697
return newHash (hash , null , 0 , Layouts .HASH .getCompareByIdentity (hash ));
699
698
}
700
699
701
700
@ Specialization (guards = {"isEmptyHash(hash)" , "isRubyHash(other)" , "isPackedHash(other)" })
702
- public DynamicObject mergeEmptyPacked (DynamicObject hash , DynamicObject other , NotProvided block ) {
701
+ public DynamicObject mergeEmptyPacked (DynamicObject hash , DynamicObject other ) {
703
702
final Object [] store = (Object []) Layouts .HASH .getStore (other );
704
703
final Object [] copy = PackedArrayStrategy .copyStore (getContext (), store );
705
704
return newHash (hash , copy , Layouts .HASH .getSize (other ), Layouts .HASH .getCompareByIdentity (hash ));
706
705
}
707
706
708
707
@ Specialization (guards = {"isPackedHash(hash)" , "isRubyHash(other)" , "isEmptyHash(other)" })
709
- public DynamicObject mergePackedEmpty (DynamicObject hash , DynamicObject other , NotProvided block ) {
710
- return mergeEmptyPacked (other , hash , block );
708
+ public DynamicObject mergePackedEmpty (DynamicObject hash , DynamicObject other ) {
709
+ return mergeEmptyPacked (other , hash );
711
710
}
712
711
713
712
@ Specialization (guards = {"isEmptyHash(hash)" , "isRubyHash(other)" , "isBucketHash(other)" })
714
- public DynamicObject mergeEmptyBuckets (DynamicObject hash , DynamicObject other , NotProvided block ) {
713
+ public DynamicObject mergeEmptyBuckets (DynamicObject hash , DynamicObject other ) {
715
714
final DynamicObject merged = newHash (hash , null , 0 , Layouts .HASH .getCompareByIdentity (hash ));
716
715
BucketsStrategy .copyInto (getContext (), other , merged );
717
716
return merged ;
718
717
}
719
718
720
719
@ Specialization (guards = {"isBucketHash(hash)" , "isRubyHash(other)" , "isEmptyHash(other)" })
721
- public DynamicObject mergeBucketsEmpty (DynamicObject hash , DynamicObject other , NotProvided block ) {
722
- return mergeEmptyBuckets (other , hash , block );
720
+ public DynamicObject mergeBucketsEmpty (DynamicObject hash , DynamicObject other ) {
721
+ return mergeEmptyBuckets (other , hash );
723
722
}
724
723
725
724
// Merge non-empty packed with non-empty packed, without a block
726
725
727
726
@ Specialization (guards = {"isPackedHash(hash)" , "!isEmptyHash(hash)" , "isRubyHash(other)" , "isPackedHash(other)" , "!isEmptyHash(other)" })
728
- public DynamicObject mergePackedPacked (DynamicObject hash , DynamicObject other , NotProvided block ,
727
+ public DynamicObject mergePackedPacked (DynamicObject hash , DynamicObject other ,
729
728
@ Cached ("createBinaryProfile()" ) ConditionProfile byIdentityProfile ,
730
729
@ Cached ("createBinaryProfile()" ) ConditionProfile nothingFromFirstProfile ,
731
730
@ Cached ("createBinaryProfile()" ) ConditionProfile resultIsSmallProfile ) {
@@ -834,7 +833,7 @@ private int mergedPackedHashes(boolean compareByIdentity, Object[] storeA, int s
834
833
// Merge non-empty buckets with non-empty buckets, without a block
835
834
836
835
@ Specialization (guards = {"isBucketHash(hash)" , "!isEmptyHash(hash)" , "isRubyHash(other)" , "isBucketHash(other)" , "!isEmptyHash(other)" })
837
- public DynamicObject mergeBucketsBuckets (DynamicObject hash , DynamicObject other , NotProvided block ) {
836
+ public DynamicObject mergeBucketsBuckets (DynamicObject hash , DynamicObject other ) {
838
837
final boolean compareByIdentity = Layouts .HASH .getCompareByIdentity (hash );
839
838
final Entry [] newStore = new Entry [BucketsStrategy .capacityGreaterThan (Layouts .HASH .getSize (hash ) + Layouts .HASH .getSize (other ))];
840
839
final DynamicObject merged = newHash (hash , newStore , 0 , compareByIdentity );
@@ -854,7 +853,7 @@ public DynamicObject mergeBucketsBuckets(DynamicObject hash, DynamicObject other
854
853
// Merge combinations of packed and buckets, without a block
855
854
856
855
@ Specialization (guards = {"isPackedHash(hash)" , "!isEmptyHash(hash)" , "isRubyHash(other)" , "isBucketHash(other)" , "!isEmptyHash(other)" })
857
- public DynamicObject mergePackedBuckets (DynamicObject hash , DynamicObject other , NotProvided block ) {
856
+ public DynamicObject mergePackedBuckets (DynamicObject hash , DynamicObject other ) {
858
857
final boolean compareByIdentity = Layouts .HASH .getCompareByIdentity (hash );
859
858
final Entry [] newStore = new Entry [BucketsStrategy .capacityGreaterThan (Layouts .HASH .getSize (hash ) + Layouts .HASH .getSize (other ))];
860
859
final DynamicObject merged = newHash (hash , newStore , 0 , compareByIdentity );
@@ -877,7 +876,7 @@ public DynamicObject mergePackedBuckets(DynamicObject hash, DynamicObject other,
877
876
}
878
877
879
878
@ Specialization (guards = {"isBucketHash(hash)" , "!isEmptyHash(hash)" , "isRubyHash(other)" , "isPackedHash(other)" , "!isEmptyHash(other)" })
880
- public DynamicObject mergeBucketsPacked (DynamicObject hash , DynamicObject other , NotProvided block ) {
879
+ public DynamicObject mergeBucketsPacked (DynamicObject hash , DynamicObject other ) {
881
880
final boolean compareByIdentity = Layouts .HASH .getCompareByIdentity (hash );
882
881
final Entry [] newStore = new Entry [BucketsStrategy .capacityGreaterThan (Layouts .HASH .getSize (hash ) + Layouts .HASH .getSize (other ))];
883
882
final DynamicObject merged = newHash (hash , newStore , 0 , compareByIdentity );
@@ -899,66 +898,6 @@ public DynamicObject mergeBucketsPacked(DynamicObject hash, DynamicObject other,
899
898
return merged ;
900
899
}
901
900
902
- // Merge using a block
903
-
904
- @ Specialization (guards = "isRubyHash(other)" )
905
- public DynamicObject merge (DynamicObject hash , DynamicObject other , DynamicObject block ,
906
- @ Cached ("new()" ) NotOptimizedWarningNode notOptimizedWarningNode ) {
907
- notOptimizedWarningNode .warn ("Hash#merge with a block is not yet optimized" );
908
-
909
- final boolean compareByIdentity = Layouts .HASH .getCompareByIdentity (hash );
910
-
911
- final int capacity = BucketsStrategy .capacityGreaterThan (Layouts .HASH .getSize (hash ) + Layouts .HASH .getSize (other ));
912
- final DynamicObject merged = newHash (hash , new Entry [capacity ], 0 , compareByIdentity );
913
-
914
- int size = 0 ;
915
-
916
- for (KeyValue keyValue : HashOperations .iterableKeyValues (hash )) {
917
- setNode .executeSet (merged , keyValue .getKey (), keyValue .getValue (), false );
918
- size ++;
919
- }
920
-
921
- if (lookupEntryNode == null ) {
922
- CompilerDirectives .transferToInterpreterAndInvalidate ();
923
- lookupEntryNode = insert (new LookupEntryNode ());
924
- }
925
-
926
- for (KeyValue keyValue : HashOperations .iterableKeyValues (other )) {
927
- final HashLookupResult searchResult = lookupEntryNode .lookup (merged , keyValue .getKey ());
928
-
929
- if (searchResult .getEntry () == null ) {
930
- setNode .executeSet (merged , keyValue .getKey (), keyValue .getValue (), false );
931
- size ++;
932
- } else {
933
- final Object oldValue = searchResult .getEntry ().getValue ();
934
- final Object newValue = keyValue .getValue ();
935
- final Object mergedValue = yield (block , keyValue .getKey (), oldValue , newValue );
936
-
937
- setNode .executeSet (merged , keyValue .getKey (), mergedValue , false );
938
- }
939
- }
940
-
941
- Layouts .HASH .setSize (merged , size );
942
-
943
- assert HashOperations .verifyStore (getContext (), hash );
944
- return merged ;
945
- }
946
-
947
- // Merge with something that wasn't a hash
948
-
949
- @ Specialization (guards = "!isRubyHash(other)" )
950
- public Object merge (DynamicObject hash , Object other , Object maybeBlock ,
951
- @ Cached ("createPrivate()" ) CallDispatchHeadNode fallbackCallNode ) {
952
- final DynamicObject block ;
953
- if (maybeBlock == NotProvided .INSTANCE ) {
954
- block = null ;
955
- } else {
956
- block = (DynamicObject ) maybeBlock ;
957
- }
958
-
959
- return fallbackCallNode .callWithBlock (hash , "merge_fallback" , block , other );
960
- }
961
-
962
901
private DynamicObject newHash (DynamicObject hash , Object [] store , int size , boolean compareByIdentity ) {
963
902
return allocateObjectNode .allocate (Layouts .BASIC_OBJECT .getLogicalClass (hash ),
964
903
Layouts .HASH .build (store , size , null , null , Layouts .HASH .getDefaultBlock (hash ), Layouts .HASH .getDefaultValue (hash ), compareByIdentity ));
0 commit comments