43
43
import java .util .Iterator ;
44
44
45
45
import org .graalvm .collections .EconomicMap ;
46
- import org .graalvm .collections .Equivalence ;
47
46
import org .graalvm .collections .MapCursor ;
48
47
49
48
import com .oracle .graal .python .builtins .objects .common .HashingStorageLibrary .InjectIntoNode ;
69
68
@ ExportLibrary (HashingStorageLibrary .class )
70
69
public class EconomicMapStorage extends HashingStorage {
71
70
72
- public static final Equivalence DEFAULT_EQIVALENCE = new Equivalence () {
73
-
74
- @ Override
75
- public int hashCode (Object o ) {
76
- return Long .hashCode (o .hashCode ());
77
- }
78
-
79
- @ Override
80
- public boolean equals (Object a , Object b ) {
81
- return (a == b ) || (a != null && objectEquals (a , b ));
82
- }
83
-
84
- private boolean objectEquals (Object a , Object b ) {
85
- return a .equals (b );
86
- }
87
- };
88
-
89
71
public static EconomicMapStorage create () {
90
72
return new EconomicMapStorage ();
91
73
}
@@ -107,26 +89,6 @@ static final class DictKey {
107
89
this .hash = hash ;
108
90
}
109
91
110
- @ Override
111
- public boolean equals (Object obj ) {
112
- // Comparison as per CPython's dictobject.c#lookdict function. First
113
- // check if the keys are identical, then check if the hashes are the
114
- // same, and only if they are, also call the comparison function.
115
- if (obj instanceof DictKey ) {
116
- DictKey other = (DictKey ) obj ;
117
- if (value == other .value ) {
118
- return true ;
119
- } else if (hash == other .hash ) {
120
- final PythonObjectLibrary lib = PythonObjectLibrary .getUncached ();
121
- return lib .equals (value , other .value , lib );
122
- } else {
123
- return false ;
124
- }
125
- } else {
126
- return false ;
127
- }
128
- }
129
-
130
92
@ Override
131
93
public int hashCode () {
132
94
return (int ) hash ;
@@ -136,7 +98,7 @@ public int hashCode() {
136
98
private final PEMap map ;
137
99
138
100
private EconomicMapStorage (int initialCapacity ) {
139
- this .map = PEMap .create (EconomicMapStorage . DEFAULT_EQIVALENCE , initialCapacity , false );
101
+ this .map = PEMap .create (initialCapacity , false );
140
102
}
141
103
142
104
private EconomicMapStorage () {
@@ -148,13 +110,15 @@ private EconomicMapStorage(EconomicMapStorage original) {
148
110
this .map .putAll (original .map );
149
111
}
150
112
113
+ @ TruffleBoundary
151
114
public EconomicMapStorage (EconomicMap <? extends Object , ? extends Object > map ) {
152
115
this (map .size ());
116
+ final PythonObjectLibrary lib = PythonObjectLibrary .getUncached ();
153
117
MapCursor <? extends Object , ? extends Object > c = map .getEntries ();
154
118
while (c .advance ()) {
155
119
Object key = c .getKey ();
156
120
assert key instanceof Integer || key instanceof String ;
157
- this .map .put (new DictKey (key , key .hashCode ()), c .getValue ());
121
+ this .map .put (new DictKey (key , key .hashCode ()), c .getValue (), lib , lib );
158
122
}
159
123
}
160
124
@@ -184,28 +148,31 @@ private static String generic(CharSequence profiled) {
184
148
static class GetItemWithState {
185
149
186
150
@ Specialization
187
- static Object getItemString (EconomicMapStorage self , String key , @ SuppressWarnings ("unused" ) ThreadState state ) {
151
+ static Object getItemString (EconomicMapStorage self , String key , @ SuppressWarnings ("unused" ) ThreadState state ,
152
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
188
153
DictKey newKey = new DictKey (key , key .hashCode ());
189
- return self .map .get (newKey );
154
+ return self .map .get (newKey , lib , lib );
190
155
}
191
156
192
157
@ SuppressWarnings ("unused" )
193
158
@ Specialization (guards = {"!isNativeString(key)" , "isBuiltinString(key, isBuiltinClassProfile, getClassNode)" })
194
159
static Object getItemPString (EconomicMapStorage self , PString key , @ SuppressWarnings ("unused" ) ThreadState state ,
195
160
@ Exclusive @ Cached ("createClassProfile()" ) ValueProfile profile ,
196
161
@ Exclusive @ Cached IsBuiltinClassProfile isBuiltinClassProfile ,
197
- @ Exclusive @ Cached GetLazyClassNode getClassNode ) {
162
+ @ Exclusive @ Cached GetLazyClassNode getClassNode ,
163
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
198
164
final String k = EconomicMapStorage .toString (key , profile );
199
- DictKey newKey = new DictKey (k , k .hashCode ());
200
- return self .map .get (newKey );
165
+ return getItemString (self , k , state , lib );
201
166
}
202
167
203
168
@ Specialization (replaces = "getItemString" , limit = "3" )
204
169
static Object getItemGeneric (EconomicMapStorage self , Object key , ThreadState state ,
205
170
@ CachedLibrary ("key" ) PythonObjectLibrary lib ,
171
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary otherlib ,
206
172
@ Exclusive @ Cached ("createBinaryProfile()" ) ConditionProfile gotState ) {
207
- DictKey newKey = new DictKey (key , self .getHashWithState (key , lib , state , gotState ));
208
- return self .map .get (newKey );
173
+ final long h = self .getHashWithState (key , lib , state , gotState );
174
+ DictKey newKey = new DictKey (key , h );
175
+ return self .map .get (newKey , lib , otherlib );
209
176
}
210
177
}
211
178
@@ -215,39 +182,41 @@ static Object getItemGeneric(EconomicMapStorage self, Object key, ThreadState st
215
182
static class SetItemWithState {
216
183
217
184
@ Specialization
218
- static HashingStorage setItemString (EconomicMapStorage self , String key , Object value , ThreadState state ) {
185
+ static HashingStorage setItemString (EconomicMapStorage self , String key , Object value , ThreadState state ,
186
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
219
187
DictKey newKey = new DictKey (key , key .hashCode ());
220
- self .map .put (newKey , value );
188
+ self .map .put (newKey , value , lib , lib );
221
189
return self ;
222
190
}
223
191
224
192
@ Specialization (guards = {"!isNativeString(key)" , "isBuiltinString(key, isBuiltinClassProfile, getClassNode)" })
225
193
static HashingStorage setItemPString (EconomicMapStorage self , PString key , Object value , ThreadState state ,
226
194
@ Exclusive @ Cached ("createClassProfile()" ) ValueProfile profile ,
227
195
@ Exclusive @ Cached IsBuiltinClassProfile isBuiltinClassProfile ,
228
- @ Exclusive @ Cached GetLazyClassNode getClassNode ) {
196
+ @ Exclusive @ Cached GetLazyClassNode getClassNode ,
197
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
229
198
final String k = EconomicMapStorage .toString (key , profile );
230
- DictKey newKey = new DictKey (k , k .hashCode ());
231
- self .map .put (newKey , value );
232
- return self ;
199
+ return setItemString (self , k , value , state , lib );
233
200
}
234
201
235
202
@ Specialization (replaces = "setItemString" , limit = "3" )
236
203
static HashingStorage setItemGeneric (EconomicMapStorage self , Object key , Object value , ThreadState state ,
237
204
@ CachedLibrary ("key" ) PythonObjectLibrary lib ,
205
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary otherlib ,
238
206
@ Exclusive @ Cached ("createBinaryProfile()" ) ConditionProfile gotState ) {
239
207
DictKey newKey = new DictKey (key , self .getHashWithState (key , lib , state , gotState ));
240
- self .map .put (newKey , value );
208
+ self .map .put (newKey , value , lib , otherlib );
241
209
return self ;
242
210
}
243
211
}
244
212
245
- @ ExportMessage (limit = "3 " )
213
+ @ ExportMessage (limit = "2 " )
246
214
public HashingStorage delItemWithState (Object key , ThreadState state ,
247
215
@ CachedLibrary ("key" ) PythonObjectLibrary lib ,
216
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary otherlib ,
248
217
@ Exclusive @ Cached ("createBinaryProfile()" ) ConditionProfile gotState ) {
249
218
DictKey newKey = new DictKey (key , getHashWithState (key , lib , state , gotState ));
250
- map .removeKey (newKey );
219
+ map .removeKey (newKey , lib , otherlib );
251
220
return this ;
252
221
}
253
222
@@ -264,15 +233,18 @@ public HashingStorage[] injectInto(HashingStorage[] firstValue, InjectIntoNode n
264
233
265
234
@ ExportMessage
266
235
public static class AddAllToOther {
236
+
237
+ @ TruffleBoundary
267
238
@ Specialization
268
239
static HashingStorage toSameType (EconomicMapStorage self , EconomicMapStorage other ) {
269
240
other .map .putAll (self .map );
270
241
return other ;
271
242
}
272
243
273
- @ Specialization
244
+ @ TruffleBoundary
245
+ @ Specialization (limit = "2" )
274
246
static HashingStorage generic (EconomicMapStorage self , HashingStorage other ,
275
- @ CachedLibrary (limit = "1 " ) HashingStorageLibrary lib ) {
247
+ @ CachedLibrary ("other " ) HashingStorageLibrary lib ) {
276
248
HashingStorage result = other ;
277
249
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
278
250
while (cursor .advance ()) {
@@ -297,34 +269,37 @@ public HashingStorage copy() {
297
269
298
270
@ ExportMessage
299
271
public static class EqualsWithState {
272
+ @ TruffleBoundary
300
273
@ Specialization
301
274
static boolean equalSameType (EconomicMapStorage self , EconomicMapStorage other , ThreadState state ,
302
- @ CachedLibrary (limit = "5 " ) PythonObjectLibrary compareLib1 ,
303
- @ CachedLibrary (limit = "5 " ) PythonObjectLibrary compareLib2 ) {
275
+ @ CachedLibrary (limit = "2 " ) PythonObjectLibrary compareLib1 ,
276
+ @ CachedLibrary (limit = "2 " ) PythonObjectLibrary compareLib2 ) {
304
277
if (self .map .size () != other .map .size ()) {
305
278
return false ;
306
279
}
307
280
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
308
281
while (cursor .advance ()) {
309
- Object otherValue = other .map .get (cursor .getKey ());
282
+ Object otherValue = other .map .get (cursor .getKey (), compareLib1 , compareLib2 );
310
283
if (otherValue != null && !compareLib1 .equalsWithState (otherValue , cursor .getValue (), compareLib2 , state )) {
311
284
return false ;
312
285
}
313
286
}
314
287
return true ;
315
288
}
316
289
290
+ @ TruffleBoundary
317
291
@ Specialization
318
292
static boolean equalGeneric (EconomicMapStorage self , HashingStorage other , ThreadState state ,
319
- @ CachedLibrary (limit = "5" ) HashingStorageLibrary lib ,
320
- @ CachedLibrary (limit = "5" ) PythonObjectLibrary compareLib1 ,
321
- @ CachedLibrary (limit = "5" ) PythonObjectLibrary compareLib2 ) {
322
- if (self .map .size () != lib .lengthWithState (other , state )) {
293
+ @ CachedLibrary (limit = "2" ) HashingStorageLibrary selflib ,
294
+ @ CachedLibrary (limit = "2" ) HashingStorageLibrary otherlib ,
295
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary compareLib1 ,
296
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary compareLib2 ) {
297
+ if (self .map .size () != otherlib .lengthWithState (other , state )) {
323
298
return false ;
324
299
}
325
300
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
326
301
while (cursor .advance ()) {
327
- Object otherValue = lib .getItemWithState (self , cursor .getKey ().value , state );
302
+ Object otherValue = selflib .getItemWithState (self , cursor .getKey ().value , state );
328
303
if (otherValue != null && !compareLib1 .equalsWithState (otherValue , cursor .getValue (), compareLib2 , state )) {
329
304
return false ;
330
305
}
@@ -335,16 +310,18 @@ static boolean equalGeneric(EconomicMapStorage self, HashingStorage other, Threa
335
310
336
311
@ ExportMessage
337
312
public static class CompareKeys {
313
+ @ TruffleBoundary
338
314
@ Specialization
339
- static int compareSameType (EconomicMapStorage self , EconomicMapStorage other ) {
315
+ static int compareSameType (EconomicMapStorage self , EconomicMapStorage other ,
316
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
340
317
int size = self .map .size ();
341
318
int size2 = other .map .size ();
342
319
if (size > size2 ) {
343
320
return 1 ;
344
321
}
345
322
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
346
323
while (cursor .advance ()) {
347
- if (!other .map .containsKey (cursor .getKey ())) {
324
+ if (!other .map .containsKey (cursor .getKey (), lib , lib )) {
348
325
return 1 ;
349
326
}
350
327
}
@@ -355,6 +332,7 @@ static int compareSameType(EconomicMapStorage self, EconomicMapStorage other) {
355
332
}
356
333
}
357
334
335
+ @ TruffleBoundary
358
336
@ Specialization (limit = "4" )
359
337
static int compareGeneric (EconomicMapStorage self , HashingStorage other ,
360
338
@ CachedLibrary ("other" ) HashingStorageLibrary lib ) {
@@ -379,26 +357,30 @@ static int compareGeneric(EconomicMapStorage self, HashingStorage other,
379
357
380
358
@ ExportMessage
381
359
public static class Intersect {
360
+ @ TruffleBoundary
382
361
@ Specialization
383
- static HashingStorage intersectSameType (EconomicMapStorage self , EconomicMapStorage other ) {
362
+ static HashingStorage intersectSameType (EconomicMapStorage self , EconomicMapStorage other ,
363
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
384
364
EconomicMapStorage result = EconomicMapStorage .create ();
385
365
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
386
366
while (cursor .advance ()) {
387
- if (other .map .containsKey (cursor .getKey ())) {
388
- result .map .put (cursor .getKey (), cursor .getValue ());
367
+ if (other .map .containsKey (cursor .getKey (), lib , lib )) {
368
+ result .map .put (cursor .getKey (), cursor .getValue (), lib , lib );
389
369
}
390
370
}
391
371
return result ;
392
372
}
393
373
374
+ @ TruffleBoundary
394
375
@ Specialization (limit = "4" )
395
376
static HashingStorage intersectGeneric (EconomicMapStorage self , HashingStorage other ,
396
- @ CachedLibrary ("other" ) HashingStorageLibrary lib ) {
377
+ @ CachedLibrary ("other" ) HashingStorageLibrary hlib ,
378
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
397
379
EconomicMapStorage result = EconomicMapStorage .create ();
398
380
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
399
381
while (cursor .advance ()) {
400
- if (lib .hasKey (other , cursor .getKey ().value )) {
401
- result .map .put (cursor .getKey (), cursor .getValue ());
382
+ if (hlib .hasKey (other , cursor .getKey ().value )) {
383
+ result .map .put (cursor .getKey (), cursor .getValue (), lib , lib );
402
384
}
403
385
}
404
386
return result ;
@@ -407,26 +389,30 @@ static HashingStorage intersectGeneric(EconomicMapStorage self, HashingStorage o
407
389
408
390
@ ExportMessage
409
391
public static class Diff {
392
+ @ TruffleBoundary
410
393
@ Specialization
411
- static HashingStorage diffSameType (EconomicMapStorage self , EconomicMapStorage other ) {
394
+ static HashingStorage diffSameType (EconomicMapStorage self , EconomicMapStorage other ,
395
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
412
396
EconomicMapStorage result = EconomicMapStorage .create ();
413
397
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
414
398
while (cursor .advance ()) {
415
- if (!other .map .containsKey (cursor .getKey ())) {
416
- result .map .put (cursor .getKey (), cursor .getValue ());
399
+ if (!other .map .containsKey (cursor .getKey (), lib , lib )) {
400
+ result .map .put (cursor .getKey (), cursor .getValue (), lib , lib );
417
401
}
418
402
}
419
403
return result ;
420
404
}
421
405
406
+ @ TruffleBoundary
422
407
@ Specialization (limit = "4" )
423
408
static HashingStorage diffGeneric (EconomicMapStorage self , HashingStorage other ,
424
- @ CachedLibrary ("other" ) HashingStorageLibrary lib ) {
409
+ @ CachedLibrary ("other" ) HashingStorageLibrary hlib ,
410
+ @ CachedLibrary (limit = "2" ) PythonObjectLibrary lib ) {
425
411
EconomicMapStorage result = EconomicMapStorage .create ();
426
412
MapCursor <DictKey , Object > cursor = self .map .getEntries ();
427
413
while (cursor .advance ()) {
428
- if (!lib .hasKey (other , cursor .getKey ().value )) {
429
- result .map .put (cursor .getKey (), cursor .getValue ());
414
+ if (!hlib .hasKey (other , cursor .getKey ().value )) {
415
+ result .map .put (cursor .getKey (), cursor .getValue (), lib , lib );
430
416
}
431
417
}
432
418
return result ;
0 commit comments