Skip to content

Commit 648c5f5

Browse files
committed
honor iterator order when initializing dict from another dict
1 parent efd700c commit 648c5f5

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@
5858
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.LenNode;
5959
import com.oracle.graal.python.builtins.objects.dict.PDict;
6060
import com.oracle.graal.python.builtins.objects.function.PArguments.ThreadState;
61+
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
6162
import com.oracle.graal.python.builtins.objects.function.PKeyword;
63+
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
6264
import com.oracle.graal.python.builtins.objects.object.PythonObject;
6365
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
6466
import com.oracle.graal.python.nodes.ErrorMessages;
@@ -163,16 +165,18 @@ protected boolean hasKeysAttribute(Object o) {
163165
return lookupKeysAttributeNode.execute(o) != PNone.NO_VALUE;
164166
}
165167

166-
@Specialization(guards = "isEmpty(kwargs)")
168+
@Specialization(guards = {"isEmpty(kwargs)", "!hasIterAttrButNotBuiltin(dictLike, dictLib)"}, limit = "1")
167169
HashingStorage doPDict(PHashingCollection dictLike, @SuppressWarnings("unused") PKeyword[] kwargs,
170+
@SuppressWarnings("unused") @CachedLibrary("dictLike") PythonObjectLibrary dictLib,
168171
@CachedLibrary(limit = "3") HashingStorageLibrary lib,
169172
@Cached HashingCollectionNodes.GetDictStorageNode getDictStorageNode) {
170173
return lib.copy(getDictStorageNode.execute(dictLike));
171174
}
172175

173-
@Specialization(guards = "!isEmpty(kwargs)")
176+
@Specialization(guards = {"!isEmpty(kwargs)", "!hasIterAttrButNotBuiltin(iterable, iterLib)"}, limit = "1")
174177
HashingStorage doPDictKwargs(VirtualFrame frame, PHashingCollection iterable, PKeyword[] kwargs,
175178
@CachedContext(PythonLanguage.class) PythonContext context,
179+
@SuppressWarnings("unused") @CachedLibrary("iterable") PythonObjectLibrary iterLib,
176180
@CachedLibrary(limit = "2") HashingStorageLibrary lib,
177181
@Cached("create()") HashingCollectionNodes.GetDictStorageNode getDictStorageNode) {
178182
Object state = IndirectCallContext.enter(frame, context, this);
@@ -185,6 +189,26 @@ HashingStorage doPDictKwargs(VirtualFrame frame, PHashingCollection iterable, PK
185189
}
186190
}
187191

192+
@Specialization(guards = "hasIterAttrButNotBuiltin(col, colLib)", limit = "1")
193+
HashingStorage doNoBuiltinKeysAttr(VirtualFrame frame, PHashingCollection col,
194+
@SuppressWarnings("unused") PKeyword[] kwargs,
195+
@SuppressWarnings("unused") @CachedLibrary("col") PythonObjectLibrary colLib,
196+
@CachedLibrary(limit = "3") HashingStorageLibrary lib,
197+
@Cached("create(KEYS)") LookupAndCallUnaryNode callKeysNode,
198+
@Cached("create(__GETITEM__)") LookupAndCallBinaryNode callGetItemNode,
199+
@Cached GetIteratorNode getIteratorNode,
200+
@Cached GetNextNode nextNode,
201+
@Cached IsBuiltinClassProfile errorProfile) {
202+
HashingStorage curStorage = PDict.createNewStorage(false, 0);
203+
return copyToStorage(frame, col, kwargs, curStorage, callKeysNode, callGetItemNode,
204+
getIteratorNode, nextNode, errorProfile, lib);
205+
}
206+
207+
protected boolean hasIterAttrButNotBuiltin(PHashingCollection col, PythonObjectLibrary lib) {
208+
Object attr = lib.lookupAttribute(col, SpecialMethodNames.__ITER__);
209+
return attr != PNone.NO_VALUE && !(attr instanceof PBuiltinMethod || attr instanceof PBuiltinFunction);
210+
}
211+
188212
@Specialization(guards = {"!isPDict(mapping)", "hasKeysAttribute(mapping)"})
189213
HashingStorage doMapping(VirtualFrame frame, Object mapping, PKeyword[] kwargs,
190214
@CachedLibrary(limit = "3") HashingStorageLibrary lib,
@@ -194,7 +218,7 @@ HashingStorage doMapping(VirtualFrame frame, Object mapping, PKeyword[] kwargs,
194218
@Cached GetNextNode nextNode,
195219
@Cached IsBuiltinClassProfile errorProfile) {
196220
HashingStorage curStorage = PDict.createNewStorage(false, 0);
197-
return addMappingToStorage(frame, mapping, kwargs, curStorage, callKeysNode, callGetItemNode, getIteratorNode, nextNode, errorProfile, lib);
221+
return copyToStorage(frame, mapping, kwargs, curStorage, callKeysNode, callGetItemNode, getIteratorNode, nextNode, errorProfile, lib);
198222
}
199223

200224
@Specialization(guards = {"!isNoValue(iterable)", "!isPDict(iterable)", "!hasKeysAttribute(iterable)"})
@@ -623,7 +647,7 @@ protected long getHashWithState(Object key, PythonObjectLibrary lib, ThreadState
623647
* Adds all items from the given mapping object to storage. It is the caller responsibility to
624648
* ensure, that mapping has the 'keys' attribute.
625649
*/
626-
public static HashingStorage addMappingToStorage(VirtualFrame frame, Object mapping, PKeyword[] kwargs, HashingStorage storage,
650+
public static HashingStorage copyToStorage(VirtualFrame frame, Object mapping, PKeyword[] kwargs, HashingStorage storage,
627651
LookupAndCallUnaryNode callKeysNode, LookupAndCallBinaryNode callGetItemNode,
628652
GetIteratorNode getIteratorNode, GetNextNode nextNode,
629653
IsBuiltinClassProfile errorProfile, HashingStorageLibrary lib) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ public Object updateMapping(VirtualFrame frame, PDict self, Object[] args, PKeyw
531531
@Cached IsBuiltinClassProfile errorProfile,
532532
@Cached GetDictStorageNode getStorage,
533533
@Cached SetDictStorageNode setStorage) {
534-
HashingStorage storage = HashingStorage.addMappingToStorage(frame, args[0], kwargs, getStorage.execute(self),
534+
HashingStorage storage = HashingStorage.copyToStorage(frame, args[0], kwargs, getStorage.execute(self),
535535
callKeysNode, callGetItemNode, getIteratorNode, nextNode, errorProfile, lib);
536536
setStorage.execute(self, storage);
537537
return PNone.NONE;

0 commit comments

Comments
 (0)