Skip to content

Commit 4425379

Browse files
committed
Customize PEMap to accept equal libraries
1 parent ab329db commit 4425379

File tree

2 files changed

+160
-224
lines changed

2 files changed

+160
-224
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/EconomicMapStorage.java

Lines changed: 66 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import java.util.Iterator;
4444

4545
import org.graalvm.collections.EconomicMap;
46-
import org.graalvm.collections.Equivalence;
4746
import org.graalvm.collections.MapCursor;
4847

4948
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary.InjectIntoNode;
@@ -69,23 +68,6 @@
6968
@ExportLibrary(HashingStorageLibrary.class)
7069
public class EconomicMapStorage extends HashingStorage {
7170

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-
8971
public static EconomicMapStorage create() {
9072
return new EconomicMapStorage();
9173
}
@@ -107,26 +89,6 @@ static final class DictKey {
10789
this.hash = hash;
10890
}
10991

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-
13092
@Override
13193
public int hashCode() {
13294
return (int) hash;
@@ -136,7 +98,7 @@ public int hashCode() {
13698
private final PEMap map;
13799

138100
private EconomicMapStorage(int initialCapacity) {
139-
this.map = PEMap.create(EconomicMapStorage.DEFAULT_EQIVALENCE, initialCapacity, false);
101+
this.map = PEMap.create(initialCapacity, false);
140102
}
141103

142104
private EconomicMapStorage() {
@@ -148,13 +110,15 @@ private EconomicMapStorage(EconomicMapStorage original) {
148110
this.map.putAll(original.map);
149111
}
150112

113+
@TruffleBoundary
151114
public EconomicMapStorage(EconomicMap<? extends Object, ? extends Object> map) {
152115
this(map.size());
116+
final PythonObjectLibrary lib = PythonObjectLibrary.getUncached();
153117
MapCursor<? extends Object, ? extends Object> c = map.getEntries();
154118
while (c.advance()) {
155119
Object key = c.getKey();
156120
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);
158122
}
159123
}
160124

@@ -184,28 +148,31 @@ private static String generic(CharSequence profiled) {
184148
static class GetItemWithState {
185149

186150
@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) {
188153
DictKey newKey = new DictKey(key, key.hashCode());
189-
return self.map.get(newKey);
154+
return self.map.get(newKey, lib, lib);
190155
}
191156

192157
@SuppressWarnings("unused")
193158
@Specialization(guards = {"!isNativeString(key)", "isBuiltinString(key, isBuiltinClassProfile, getClassNode)"})
194159
static Object getItemPString(EconomicMapStorage self, PString key, @SuppressWarnings("unused") ThreadState state,
195160
@Exclusive @Cached("createClassProfile()") ValueProfile profile,
196161
@Exclusive @Cached IsBuiltinClassProfile isBuiltinClassProfile,
197-
@Exclusive @Cached GetLazyClassNode getClassNode) {
162+
@Exclusive @Cached GetLazyClassNode getClassNode,
163+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
198164
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);
201166
}
202167

203168
@Specialization(replaces = "getItemString", limit = "3")
204169
static Object getItemGeneric(EconomicMapStorage self, Object key, ThreadState state,
205170
@CachedLibrary("key") PythonObjectLibrary lib,
171+
@CachedLibrary(limit = "2") PythonObjectLibrary otherlib,
206172
@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);
209176
}
210177
}
211178

@@ -215,39 +182,41 @@ static Object getItemGeneric(EconomicMapStorage self, Object key, ThreadState st
215182
static class SetItemWithState {
216183

217184
@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) {
219187
DictKey newKey = new DictKey(key, key.hashCode());
220-
self.map.put(newKey, value);
188+
self.map.put(newKey, value, lib, lib);
221189
return self;
222190
}
223191

224192
@Specialization(guards = {"!isNativeString(key)", "isBuiltinString(key, isBuiltinClassProfile, getClassNode)"})
225193
static HashingStorage setItemPString(EconomicMapStorage self, PString key, Object value, ThreadState state,
226194
@Exclusive @Cached("createClassProfile()") ValueProfile profile,
227195
@Exclusive @Cached IsBuiltinClassProfile isBuiltinClassProfile,
228-
@Exclusive @Cached GetLazyClassNode getClassNode) {
196+
@Exclusive @Cached GetLazyClassNode getClassNode,
197+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
229198
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);
233200
}
234201

235202
@Specialization(replaces = "setItemString", limit = "3")
236203
static HashingStorage setItemGeneric(EconomicMapStorage self, Object key, Object value, ThreadState state,
237204
@CachedLibrary("key") PythonObjectLibrary lib,
205+
@CachedLibrary(limit = "2") PythonObjectLibrary otherlib,
238206
@Exclusive @Cached("createBinaryProfile()") ConditionProfile gotState) {
239207
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);
241209
return self;
242210
}
243211
}
244212

245-
@ExportMessage(limit = "3")
213+
@ExportMessage(limit = "2")
246214
public HashingStorage delItemWithState(Object key, ThreadState state,
247215
@CachedLibrary("key") PythonObjectLibrary lib,
216+
@CachedLibrary(limit = "2") PythonObjectLibrary otherlib,
248217
@Exclusive @Cached("createBinaryProfile()") ConditionProfile gotState) {
249218
DictKey newKey = new DictKey(key, getHashWithState(key, lib, state, gotState));
250-
map.removeKey(newKey);
219+
map.removeKey(newKey, lib, otherlib);
251220
return this;
252221
}
253222

@@ -264,15 +233,18 @@ public HashingStorage[] injectInto(HashingStorage[] firstValue, InjectIntoNode n
264233

265234
@ExportMessage
266235
public static class AddAllToOther {
236+
237+
@TruffleBoundary
267238
@Specialization
268239
static HashingStorage toSameType(EconomicMapStorage self, EconomicMapStorage other) {
269240
other.map.putAll(self.map);
270241
return other;
271242
}
272243

273-
@Specialization
244+
@TruffleBoundary
245+
@Specialization(limit = "2")
274246
static HashingStorage generic(EconomicMapStorage self, HashingStorage other,
275-
@CachedLibrary(limit = "1") HashingStorageLibrary lib) {
247+
@CachedLibrary("other") HashingStorageLibrary lib) {
276248
HashingStorage result = other;
277249
MapCursor<DictKey, Object> cursor = self.map.getEntries();
278250
while (cursor.advance()) {
@@ -297,34 +269,37 @@ public HashingStorage copy() {
297269

298270
@ExportMessage
299271
public static class EqualsWithState {
272+
@TruffleBoundary
300273
@Specialization
301274
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) {
304277
if (self.map.size() != other.map.size()) {
305278
return false;
306279
}
307280
MapCursor<DictKey, Object> cursor = self.map.getEntries();
308281
while (cursor.advance()) {
309-
Object otherValue = other.map.get(cursor.getKey());
282+
Object otherValue = other.map.get(cursor.getKey(), compareLib1, compareLib2);
310283
if (otherValue != null && !compareLib1.equalsWithState(otherValue, cursor.getValue(), compareLib2, state)) {
311284
return false;
312285
}
313286
}
314287
return true;
315288
}
316289

290+
@TruffleBoundary
317291
@Specialization
318292
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)) {
323298
return false;
324299
}
325300
MapCursor<DictKey, Object> cursor = self.map.getEntries();
326301
while (cursor.advance()) {
327-
Object otherValue = lib.getItemWithState(self, cursor.getKey().value, state);
302+
Object otherValue = selflib.getItemWithState(self, cursor.getKey().value, state);
328303
if (otherValue != null && !compareLib1.equalsWithState(otherValue, cursor.getValue(), compareLib2, state)) {
329304
return false;
330305
}
@@ -335,16 +310,18 @@ static boolean equalGeneric(EconomicMapStorage self, HashingStorage other, Threa
335310

336311
@ExportMessage
337312
public static class CompareKeys {
313+
@TruffleBoundary
338314
@Specialization
339-
static int compareSameType(EconomicMapStorage self, EconomicMapStorage other) {
315+
static int compareSameType(EconomicMapStorage self, EconomicMapStorage other,
316+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
340317
int size = self.map.size();
341318
int size2 = other.map.size();
342319
if (size > size2) {
343320
return 1;
344321
}
345322
MapCursor<DictKey, Object> cursor = self.map.getEntries();
346323
while (cursor.advance()) {
347-
if (!other.map.containsKey(cursor.getKey())) {
324+
if (!other.map.containsKey(cursor.getKey(), lib, lib)) {
348325
return 1;
349326
}
350327
}
@@ -355,6 +332,7 @@ static int compareSameType(EconomicMapStorage self, EconomicMapStorage other) {
355332
}
356333
}
357334

335+
@TruffleBoundary
358336
@Specialization(limit = "4")
359337
static int compareGeneric(EconomicMapStorage self, HashingStorage other,
360338
@CachedLibrary("other") HashingStorageLibrary lib) {
@@ -379,26 +357,30 @@ static int compareGeneric(EconomicMapStorage self, HashingStorage other,
379357

380358
@ExportMessage
381359
public static class Intersect {
360+
@TruffleBoundary
382361
@Specialization
383-
static HashingStorage intersectSameType(EconomicMapStorage self, EconomicMapStorage other) {
362+
static HashingStorage intersectSameType(EconomicMapStorage self, EconomicMapStorage other,
363+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
384364
EconomicMapStorage result = EconomicMapStorage.create();
385365
MapCursor<DictKey, Object> cursor = self.map.getEntries();
386366
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);
389369
}
390370
}
391371
return result;
392372
}
393373

374+
@TruffleBoundary
394375
@Specialization(limit = "4")
395376
static HashingStorage intersectGeneric(EconomicMapStorage self, HashingStorage other,
396-
@CachedLibrary("other") HashingStorageLibrary lib) {
377+
@CachedLibrary("other") HashingStorageLibrary hlib,
378+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
397379
EconomicMapStorage result = EconomicMapStorage.create();
398380
MapCursor<DictKey, Object> cursor = self.map.getEntries();
399381
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);
402384
}
403385
}
404386
return result;
@@ -407,26 +389,30 @@ static HashingStorage intersectGeneric(EconomicMapStorage self, HashingStorage o
407389

408390
@ExportMessage
409391
public static class Diff {
392+
@TruffleBoundary
410393
@Specialization
411-
static HashingStorage diffSameType(EconomicMapStorage self, EconomicMapStorage other) {
394+
static HashingStorage diffSameType(EconomicMapStorage self, EconomicMapStorage other,
395+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
412396
EconomicMapStorage result = EconomicMapStorage.create();
413397
MapCursor<DictKey, Object> cursor = self.map.getEntries();
414398
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);
417401
}
418402
}
419403
return result;
420404
}
421405

406+
@TruffleBoundary
422407
@Specialization(limit = "4")
423408
static HashingStorage diffGeneric(EconomicMapStorage self, HashingStorage other,
424-
@CachedLibrary("other") HashingStorageLibrary lib) {
409+
@CachedLibrary("other") HashingStorageLibrary hlib,
410+
@CachedLibrary(limit = "2") PythonObjectLibrary lib) {
425411
EconomicMapStorage result = EconomicMapStorage.create();
426412
MapCursor<DictKey, Object> cursor = self.map.getEntries();
427413
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);
430416
}
431417
}
432418
return result;

0 commit comments

Comments
 (0)