40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .common ;
42
42
43
+ import static com .oracle .graal .python .builtins .objects .function .PKeyword .EMPTY_KEYWORDS ;
43
44
import static com .oracle .graal .python .nodes .SpecialMethodNames .T_KEYS ;
44
45
import static com .oracle .graal .python .runtime .exception .PythonErrorType .TypeError ;
45
46
import static com .oracle .graal .python .runtime .exception .PythonErrorType .ValueError ;
47
+ import static com .oracle .graal .python .util .PythonUtils .EMPTY_OBJECT_ARRAY ;
46
48
47
49
import com .oracle .graal .python .PythonLanguage ;
48
50
import com .oracle .graal .python .builtins .objects .PNone ;
58
60
import com .oracle .graal .python .lib .GetNextNode ;
59
61
import com .oracle .graal .python .lib .PyObjectGetItem ;
60
62
import com .oracle .graal .python .lib .PyObjectGetIter ;
63
+ import com .oracle .graal .python .lib .PyObjectLookupAttr ;
61
64
import com .oracle .graal .python .nodes .ErrorMessages ;
62
65
import com .oracle .graal .python .nodes .IndirectCallNode ;
63
66
import com .oracle .graal .python .nodes .PNodeWithContext ;
64
67
import com .oracle .graal .python .nodes .PRaiseNode ;
65
68
import com .oracle .graal .python .nodes .attributes .LookupCallableSlotInMRONode ;
66
- import com .oracle .graal .python .nodes .attributes .LookupInheritedAttributeNode ;
67
69
import com .oracle .graal .python .nodes .builtins .ListNodes .FastConstructListNode ;
70
+ import com .oracle .graal .python .nodes .call .special .CallVarargsMethodNode ;
68
71
import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode ;
69
72
import com .oracle .graal .python .nodes .object .BuiltinClassProfiles .IsBuiltinObjectProfile ;
70
73
import com .oracle .graal .python .nodes .object .GetClassNode ;
74
77
import com .oracle .graal .python .runtime .sequence .PSequence ;
75
78
import com .oracle .graal .python .util .ArrayBuilder ;
76
79
import com .oracle .truffle .api .Assumption ;
77
- import com .oracle .truffle .api .CompilerDirectives ;
78
80
import com .oracle .truffle .api .Truffle ;
79
81
import com .oracle .truffle .api .dsl .Bind ;
80
82
import com .oracle .truffle .api .dsl .Cached ;
83
85
import com .oracle .truffle .api .dsl .Specialization ;
84
86
import com .oracle .truffle .api .frame .VirtualFrame ;
85
87
import com .oracle .truffle .api .nodes .Node ;
88
+ import com .oracle .truffle .api .profiles .ConditionProfile ;
86
89
import com .oracle .truffle .api .profiles .InlinedConditionProfile ;
87
90
88
91
public abstract class HashingStorage {
@@ -103,8 +106,6 @@ public Assumption needNotPassExceptionAssumption() {
103
106
104
107
public abstract HashingStorage execute (VirtualFrame frame , Object mapping , PKeyword [] kwargs );
105
108
106
- @ Child private LookupInheritedAttributeNode lookupKeysAttributeNode ;
107
-
108
109
protected boolean isEmpty (PKeyword [] kwargs ) {
109
110
return kwargs .length == 0 ;
110
111
}
@@ -123,14 +124,6 @@ protected static boolean isPDict(Object o) {
123
124
return o instanceof PHashingCollection ;
124
125
}
125
126
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
-
134
127
@ Specialization (guards = {"isEmpty(kwargs)" , "!hasIterAttrButNotBuiltin(inliningTarget, dictLike, getClassNode, lookupIter)" }, limit = "1" )
135
128
static HashingStorage doPDict (PHashingCollection dictLike , @ SuppressWarnings ("unused" ) PKeyword [] kwargs ,
136
129
@ SuppressWarnings ("unused" ) @ Bind ("this" ) Node inliningTarget ,
@@ -173,31 +166,20 @@ static HashingStorage doNoBuiltinKeysAttr(VirtualFrame frame, PHashingCollection
173
166
@ Exclusive @ Cached GetNextNode nextNode ,
174
167
@ Exclusive @ Cached IsBuiltinObjectProfile errorProfile ) {
175
168
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 );
177
171
}
178
172
179
173
protected static boolean hasIterAttrButNotBuiltin (Node inliningTarget , PHashingCollection col , GetClassNode getClassNode , LookupCallableSlotInMRONode lookupIter ) {
180
174
Object attr = lookupIter .execute (getClassNode .execute (inliningTarget , col ));
181
175
return attr != PNone .NO_VALUE && !(attr instanceof PBuiltinMethod || attr instanceof PBuiltinFunction );
182
176
}
183
177
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 ,
200
180
@ Bind ("this" ) Node inliningTarget ,
181
+ @ Cached PyObjectLookupAttr lookupKeysAttributeNode ,
182
+ @ Cached CallVarargsMethodNode callKeysMethod ,
201
183
@ Exclusive @ Cached HashingStorageSetItem setHasihngStorageItem ,
202
184
@ Exclusive @ Cached HashingStorageAddAllToOther addAllToOther ,
203
185
@ Exclusive @ Cached PyObjectGetIter getIter ,
@@ -207,12 +189,23 @@ static HashingStorage doSequence(VirtualFrame frame, Object iterable, PKeyword[]
207
189
@ Exclusive @ Cached PyObjectGetItem getItemNode ,
208
190
@ Cached SequenceNodes .LenNode seqLenNode ,
209
191
@ Cached InlinedConditionProfile lengthTwoProfile ,
192
+ @ Cached ConditionProfile hasKeyProfile ,
210
193
@ Exclusive @ Cached IsBuiltinObjectProfile errorProfile ,
211
194
@ 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
+ }
216
209
}
217
210
218
211
@ NeverDefault
@@ -239,10 +232,15 @@ public final HashingStorage unionCached(HashingStorage other, HashingStorageCopy
239
232
* Adds all items from the given mapping object to storage. It is the caller responsibility to
240
233
* ensure, that mapping has the 'keys' attribute.
241
234
*/
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 ) {
246
244
Object keysIt = getIter .execute (frame , inliningTarget , keysIterable );
247
245
HashingStorage curStorage = storage ;
248
246
while (true ) {
@@ -267,10 +265,19 @@ public interface StorageSupplier {
267
265
HashingStorage get (int length );
268
266
}
269
267
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 {
274
281
Object it = getIter .execute (frame , inliningTarget , iterable );
275
282
ArrayBuilder <PSequence > elements = new ArrayBuilder <>();
276
283
try {
0 commit comments