4040 */
4141package com .oracle .graal .python .builtins .objects .common ;
4242
43+ import static com .oracle .graal .python .builtins .objects .function .PKeyword .EMPTY_KEYWORDS ;
4344import static com .oracle .graal .python .nodes .SpecialMethodNames .T_KEYS ;
4445import static com .oracle .graal .python .runtime .exception .PythonErrorType .TypeError ;
4546import static com .oracle .graal .python .runtime .exception .PythonErrorType .ValueError ;
47+ import static com .oracle .graal .python .util .PythonUtils .EMPTY_OBJECT_ARRAY ;
4648
4749import com .oracle .graal .python .PythonLanguage ;
4850import com .oracle .graal .python .builtins .objects .PNone ;
5860import com .oracle .graal .python .lib .GetNextNode ;
5961import com .oracle .graal .python .lib .PyObjectGetItem ;
6062import com .oracle .graal .python .lib .PyObjectGetIter ;
63+ import com .oracle .graal .python .lib .PyObjectLookupAttr ;
6164import com .oracle .graal .python .nodes .ErrorMessages ;
6265import com .oracle .graal .python .nodes .IndirectCallNode ;
6366import com .oracle .graal .python .nodes .PNodeWithContext ;
6467import com .oracle .graal .python .nodes .PRaiseNode ;
6568import com .oracle .graal .python .nodes .attributes .LookupCallableSlotInMRONode ;
66- import com .oracle .graal .python .nodes .attributes .LookupInheritedAttributeNode ;
6769import com .oracle .graal .python .nodes .builtins .ListNodes .FastConstructListNode ;
70+ import com .oracle .graal .python .nodes .call .special .CallVarargsMethodNode ;
6871import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode ;
6972import com .oracle .graal .python .nodes .object .BuiltinClassProfiles .IsBuiltinObjectProfile ;
7073import com .oracle .graal .python .nodes .object .GetClassNode ;
7477import com .oracle .graal .python .runtime .sequence .PSequence ;
7578import com .oracle .graal .python .util .ArrayBuilder ;
7679import com .oracle .truffle .api .Assumption ;
77- import com .oracle .truffle .api .CompilerDirectives ;
7880import com .oracle .truffle .api .Truffle ;
7981import com .oracle .truffle .api .dsl .Bind ;
8082import com .oracle .truffle .api .dsl .Cached ;
8385import com .oracle .truffle .api .dsl .Specialization ;
8486import com .oracle .truffle .api .frame .VirtualFrame ;
8587import com .oracle .truffle .api .nodes .Node ;
88+ import com .oracle .truffle .api .profiles .ConditionProfile ;
8689import com .oracle .truffle .api .profiles .InlinedConditionProfile ;
8790
8891public abstract class HashingStorage {
@@ -103,8 +106,6 @@ public Assumption needNotPassExceptionAssumption() {
103106
104107 public abstract HashingStorage execute (VirtualFrame frame , Object mapping , PKeyword [] kwargs );
105108
106- @ Child private LookupInheritedAttributeNode lookupKeysAttributeNode ;
107-
108109 protected boolean isEmpty (PKeyword [] kwargs ) {
109110 return kwargs .length == 0 ;
110111 }
@@ -123,14 +124,6 @@ protected static boolean isPDict(Object o) {
123124 return o instanceof PHashingCollection ;
124125 }
125126
126- protected boolean hasKeysAttribute (Object o ) {
127- if (lookupKeysAttributeNode == null ) {
128- CompilerDirectives .transferToInterpreterAndInvalidate ();
129- lookupKeysAttributeNode = insert (LookupInheritedAttributeNode .create (T_KEYS ));
130- }
131- return lookupKeysAttributeNode .execute (o ) != PNone .NO_VALUE ;
132- }
133-
134127 @ Specialization (guards = {"isEmpty(kwargs)" , "!hasIterAttrButNotBuiltin(inliningTarget, dictLike, getClassNode, lookupIter)" }, limit = "1" )
135128 static HashingStorage doPDict (PHashingCollection dictLike , @ SuppressWarnings ("unused" ) PKeyword [] kwargs ,
136129 @ SuppressWarnings ("unused" ) @ Bind ("this" ) Node inliningTarget ,
@@ -173,31 +166,20 @@ static HashingStorage doNoBuiltinKeysAttr(VirtualFrame frame, PHashingCollection
173166 @ Exclusive @ Cached GetNextNode nextNode ,
174167 @ Exclusive @ Cached IsBuiltinObjectProfile errorProfile ) {
175168 HashingStorage curStorage = PDict .createNewStorage (0 );
176- return copyToStorage (frame , inliningTarget , col , kwargs , curStorage , callKeysNode , getItemNode , getIter , nextNode , errorProfile , setHashingStorageItem , addAllToOther );
169+ Object keysIterable = callKeysNode .executeObject (frame , col );
170+ return copyToStorage (frame , col , kwargs , curStorage , inliningTarget , keysIterable , getItemNode , getIter , nextNode , errorProfile , setHashingStorageItem , addAllToOther );
177171 }
178172
179173 protected static boolean hasIterAttrButNotBuiltin (Node inliningTarget , PHashingCollection col , GetClassNode getClassNode , LookupCallableSlotInMRONode lookupIter ) {
180174 Object attr = lookupIter .execute (getClassNode .execute (inliningTarget , col ));
181175 return attr != PNone .NO_VALUE && !(attr instanceof PBuiltinMethod || attr instanceof PBuiltinFunction );
182176 }
183177
184- @ Specialization (guards = {"!isPDict(mapping)" , "hasKeysAttribute(mapping)" })
185- static HashingStorage doMapping (VirtualFrame frame , Object mapping , PKeyword [] kwargs ,
186- @ Bind ("this" ) Node inliningTarget ,
187- @ Exclusive @ Cached HashingStorageSetItem setHasihngStorageItem ,
188- @ Exclusive @ Cached HashingStorageAddAllToOther addAllToOther ,
189- @ Exclusive @ Cached PyObjectGetIter getIter ,
190- @ Exclusive @ Cached ("create(T_KEYS)" ) LookupAndCallUnaryNode callKeysNode ,
191- @ Exclusive @ Cached PyObjectGetItem getItemNode ,
192- @ Exclusive @ Cached GetNextNode nextNode ,
193- @ Exclusive @ Cached IsBuiltinObjectProfile errorProfile ) {
194- HashingStorage curStorage = PDict .createNewStorage (0 );
195- return copyToStorage (frame , inliningTarget , mapping , kwargs , curStorage , callKeysNode , getItemNode , getIter , nextNode , errorProfile , setHasihngStorageItem , addAllToOther );
196- }
197-
198- @ Specialization (guards = {"!isNoValue(iterable)" , "!isPDict(iterable)" , "!hasKeysAttribute(iterable)" })
199- static HashingStorage doSequence (VirtualFrame frame , Object iterable , PKeyword [] kwargs ,
178+ @ Specialization (guards = {"!isNoValue(arg)" , "!isPDict(arg)" })
179+ static HashingStorage updateArg (VirtualFrame frame , Object arg , PKeyword [] kwargs ,
200180 @ Bind ("this" ) Node inliningTarget ,
181+ @ Cached PyObjectLookupAttr lookupKeysAttributeNode ,
182+ @ Cached CallVarargsMethodNode callKeysMethod ,
201183 @ Exclusive @ Cached HashingStorageSetItem setHasihngStorageItem ,
202184 @ Exclusive @ Cached HashingStorageAddAllToOther addAllToOther ,
203185 @ Exclusive @ Cached PyObjectGetIter getIter ,
@@ -207,12 +189,23 @@ static HashingStorage doSequence(VirtualFrame frame, Object iterable, PKeyword[]
207189 @ Exclusive @ Cached PyObjectGetItem getItemNode ,
208190 @ Cached SequenceNodes .LenNode seqLenNode ,
209191 @ Cached InlinedConditionProfile lengthTwoProfile ,
192+ @ Cached ConditionProfile hasKeyProfile ,
210193 @ Exclusive @ Cached IsBuiltinObjectProfile errorProfile ,
211194 @ Exclusive @ Cached IsBuiltinObjectProfile isTypeErrorProfile ) {
212-
213- return addSequenceToStorage (frame , inliningTarget , iterable , kwargs , PDict ::createNewStorage , getIter , nextNode , createListNode ,
214- seqLenNode , lengthTwoProfile , raise , getItemNode , isTypeErrorProfile ,
215- errorProfile , setHasihngStorageItem , addAllToOther );
195+ Object keyAttr = lookupKeysAttributeNode .execute (frame , inliningTarget , arg , T_KEYS );
196+ if (hasKeyProfile .profile (keyAttr != PNone .NO_VALUE )) {
197+ HashingStorage curStorage = PDict .createNewStorage (0 );
198+ // We don't need to pass self as the attribute object has it already.
199+ Object keysIterable = callKeysMethod .execute (frame , keyAttr , EMPTY_OBJECT_ARRAY , EMPTY_KEYWORDS );
200+ return copyToStorage (frame , arg , kwargs , curStorage ,
201+ inliningTarget , keysIterable , getItemNode , getIter , nextNode ,
202+ errorProfile , setHasihngStorageItem , addAllToOther );
203+ } else {
204+ return addSequenceToStorage (frame , arg , kwargs ,
205+ inliningTarget , PDict ::createNewStorage , getIter , nextNode , createListNode ,
206+ seqLenNode , lengthTwoProfile , raise , getItemNode , isTypeErrorProfile ,
207+ errorProfile , setHasihngStorageItem , addAllToOther );
208+ }
216209 }
217210
218211 @ NeverDefault
@@ -239,10 +232,15 @@ public final HashingStorage unionCached(HashingStorage other, HashingStorageCopy
239232 * Adds all items from the given mapping object to storage. It is the caller responsibility to
240233 * ensure, that mapping has the 'keys' attribute.
241234 */
242- public static HashingStorage copyToStorage (VirtualFrame frame , Node inliningTarget , Object mapping , PKeyword [] kwargs , HashingStorage storage ,
243- LookupAndCallUnaryNode callKeysNode , PyObjectGetItem callGetItemNode , PyObjectGetIter getIter , GetNextNode nextNode ,
244- IsBuiltinObjectProfile errorProfile , HashingStorageSetItem setHashingStorageItem , HashingStorageAddAllToOther addAllToOtherNode ) {
245- Object keysIterable = callKeysNode .executeObject (frame , mapping );
235+ public static HashingStorage copyToStorage (VirtualFrame frame , Object mapping , PKeyword [] kwargs , HashingStorage storage ,
236+ Node inliningTarget ,
237+ Object keysIterable ,
238+ PyObjectGetItem callGetItemNode ,
239+ PyObjectGetIter getIter ,
240+ GetNextNode nextNode ,
241+ IsBuiltinObjectProfile errorProfile ,
242+ HashingStorageSetItem setHashingStorageItem ,
243+ HashingStorageAddAllToOther addAllToOtherNode ) {
246244 Object keysIt = getIter .execute (frame , inliningTarget , keysIterable );
247245 HashingStorage curStorage = storage ;
248246 while (true ) {
@@ -267,10 +265,19 @@ public interface StorageSupplier {
267265 HashingStorage get (int length );
268266 }
269267
270- public static HashingStorage addSequenceToStorage (VirtualFrame frame , Node inliningTarget , Object iterable , PKeyword [] kwargs , StorageSupplier storageSupplier ,
271- PyObjectGetIter getIter , GetNextNode nextNode , FastConstructListNode createListNode , LenNode seqLenNode ,
272- InlinedConditionProfile lengthTwoProfile , PRaiseNode .Lazy raise , PyObjectGetItem getItemNode , IsBuiltinObjectProfile isTypeErrorProfile ,
273- IsBuiltinObjectProfile errorProfile , HashingStorageSetItem setHashingStorageItem , HashingStorageAddAllToOther addAllToOther ) throws PException {
268+ public static HashingStorage addSequenceToStorage (VirtualFrame frame , Object iterable , PKeyword [] kwargs , Node inliningTarget ,
269+ StorageSupplier storageSupplier ,
270+ PyObjectGetIter getIter ,
271+ GetNextNode nextNode ,
272+ FastConstructListNode createListNode ,
273+ LenNode seqLenNode ,
274+ InlinedConditionProfile lengthTwoProfile ,
275+ PRaiseNode .Lazy raise ,
276+ PyObjectGetItem getItemNode ,
277+ IsBuiltinObjectProfile isTypeErrorProfile ,
278+ IsBuiltinObjectProfile errorProfile ,
279+ HashingStorageSetItem setHashingStorageItem ,
280+ HashingStorageAddAllToOther addAllToOther ) throws PException {
274281 Object it = getIter .execute (frame , inliningTarget , iterable );
275282 ArrayBuilder <PSequence > elements = new ArrayBuilder <>();
276283 try {
0 commit comments