@@ -81,36 +81,53 @@ public RubyHash executeRubyHash(VirtualFrame frame) {
81
81
82
82
public static class SmallHashLiteralNode extends HashLiteralNode {
83
83
84
+ @ Child protected DispatchHeadNode equalNode ;
85
+
84
86
public SmallHashLiteralNode (RubyContext context , SourceSection sourceSection , RubyNode [] keyValues ) {
85
87
super (context , sourceSection , keyValues );
88
+ equalNode = new DispatchHeadNode (context );
86
89
}
87
90
88
91
@ ExplodeLoop
89
92
@ Override
90
93
public RubyHash executeRubyHash (VirtualFrame frame ) {
91
94
final Object [] storage = new Object [RubyContext .HASHES_SMALL * 2 ];
92
95
93
- for (int n = 0 ; n < keyValues .length ; n += 2 ) {
96
+ int position = 0 ;
97
+
98
+ initializers : for (int n = 0 ; n < keyValues .length ; n += 2 ) {
94
99
Object key = keyValues [n ].execute (frame );
95
- final Object value = keyValues [n + 1 ].execute (frame );
96
100
97
101
if (key instanceof RubyString ) {
98
102
key = freezeNode .call (frame , dupNode .call (frame , key , "dup" , null ), "freeze" , null );
99
103
}
100
104
101
- storage [n ] = key ;
102
- storage [n + 1 ] = value ;
105
+ final Object value = keyValues [n + 1 ].execute (frame );
106
+
107
+ for (int i = 0 ; i < n ; i += 2 ) {
108
+ if ((boolean ) equalNode .call (frame , key , "==" , null , storage [i ])) {
109
+ storage [i + 1 ] = value ;
110
+ continue initializers ;
111
+ }
112
+ }
113
+
114
+ storage [position ] = key ;
115
+ storage [position + 1 ] = value ;
116
+ position += 2 ;
103
117
}
104
118
105
- return new RubyHash (getContext ().getCoreLibrary ().getHashClass (), null , storage , keyValues . length / 2 );
119
+ return new RubyHash (getContext ().getCoreLibrary ().getHashClass (), null , storage , position / 2 );
106
120
}
107
121
108
122
}
109
123
110
124
public static class GenericHashLiteralNode extends HashLiteralNode {
111
125
126
+ @ Child protected DispatchHeadNode equalNode ;
127
+
112
128
public GenericHashLiteralNode (RubyContext context , SourceSection sourceSection , RubyNode [] keyValues ) {
113
129
super (context , sourceSection , keyValues );
130
+ equalNode = new DispatchHeadNode (context );
114
131
}
115
132
116
133
@ ExplodeLoop
@@ -122,12 +139,13 @@ public RubyHash executeRubyHash(VirtualFrame frame) {
122
139
123
140
for (int n = 0 ; n < keyValues .length ; n += 2 ) {
124
141
Object key = keyValues [n ].execute (frame );
125
- final Object value = keyValues [n + 1 ].execute (frame );
126
142
127
143
if (key instanceof RubyString ) {
128
144
key = freezeNode .call (frame , dupNode .call (frame , key , "dup" , null ), "freeze" , null );
129
145
}
130
146
147
+ final Object value = keyValues [n + 1 ].execute (frame );
148
+
131
149
storage .put (key , value );
132
150
}
133
151
0 commit comments