75
75
import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
76
76
import com .oracle .graal .python .nodes .attributes .SetAttributeNode ;
77
77
import com .oracle .graal .python .nodes .call .CallNode ;
78
+ import com .oracle .graal .python .nodes .call .special .CallUnaryMethodNode ;
78
79
import com .oracle .graal .python .nodes .call .special .LookupAndCallBinaryNode ;
79
80
import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode ;
80
81
import com .oracle .graal .python .nodes .datamodel .IsCallableNode ;
82
+ import com .oracle .graal .python .nodes .datamodel .IsIterableNode ;
81
83
import com .oracle .graal .python .nodes .datamodel .IsMappingNode ;
82
84
import com .oracle .graal .python .nodes .datamodel .IsSequenceNode ;
83
85
import com .oracle .graal .python .nodes .expression .CastToListNode ;
@@ -183,45 +185,119 @@ private static final class KeyForItemAccess extends KeyForForcedAccess {
183
185
private static final class ReadNode extends Node {
184
186
private static final Object NONEXISTING_IDENTIFIER = new Object ();
185
187
186
- @ Child private IsSequenceNode isSequence = IsSequenceNode .create ();
187
- @ Child private LookupAndCallBinaryNode readNode = LookupAndCallBinaryNode .create (__GETATTRIBUTE__ );
188
- @ Child private GetItemNode getItemNode = GetItemNode .create ();
189
188
@ Child private KeyForAttributeAccess getAttributeKey = new KeyForAttributeAccess ();
190
- @ Child private KeyForItemAccess getItemKey = new KeyForItemAccess ();
191
- final ConditionProfile strProfile = ConditionProfile .createBinaryProfile ();
192
189
@ Child private PTypeToForeignNode toForeign = PTypeToForeignNodeGen .create ();
193
190
191
+ @ Child private LookupAndCallBinaryNode readNode ;
192
+ @ Child private KeyForItemAccess getItemKey ;
193
+ @ Child private GetItemNode getItemNode ;
194
+ @ Child private IsSequenceNode isSequence ;
195
+ @ Child private IsIterableNode isIterableNode ;
196
+ @ Child private LookupAndCallUnaryNode getIter ;
197
+ @ Child private LookupAndCallUnaryNode callNext ;
198
+
199
+ final ConditionProfile strProfile = ConditionProfile .createBinaryProfile ();
200
+
201
+ private LookupAndCallBinaryNode getReadNode () {
202
+ if (readNode == null ) {
203
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
204
+ readNode = insert (LookupAndCallBinaryNode .create (__GETATTRIBUTE__ ));
205
+ }
206
+ return readNode ;
207
+ }
208
+
209
+ private KeyForItemAccess getGetItemKey () {
210
+ if (getItemKey == null ) {
211
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
212
+ getItemKey = insert (new KeyForItemAccess ());
213
+ }
214
+ return getItemKey ;
215
+ }
216
+
217
+ private GetItemNode getGetItemNode () {
218
+ if (getItemNode == null ) {
219
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
220
+ getItemNode = insert (GetItemNode .create ());
221
+ }
222
+ return getItemNode ;
223
+ }
224
+
225
+ private IsSequenceNode getIsSequenceNode () {
226
+ if (isSequence == null ) {
227
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
228
+ isSequence = insert (IsSequenceNode .create ());
229
+ }
230
+ return isSequence ;
231
+ }
232
+
233
+ private IsIterableNode getIsIterableNode () {
234
+ if (isIterableNode == null ) {
235
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
236
+ isIterableNode = insert (IsIterableNode .create ());
237
+ }
238
+ return isIterableNode ;
239
+ }
240
+
194
241
public Object execute (Object object , Object key ) {
195
242
String attrKey = getAttributeKey .execute (key );
196
243
if (attrKey != null ) {
197
244
try {
198
- return toForeign .executeConvert (readNode .executeObject (object , attrKey ));
245
+ return toForeign .executeConvert (getReadNode () .executeObject (object , attrKey ));
199
246
} catch (PException e ) {
200
247
// pass, we might be reading an item that starts with "@"
201
248
}
202
249
}
203
250
204
- String itemKey = getItemKey .execute (key );
251
+ String itemKey = getGetItemKey () .execute (key );
205
252
if (itemKey != null ) {
206
- return toForeign .executeConvert (getItemNode .execute (object , itemKey ));
253
+ return toForeign .executeConvert (getGetItemNode () .execute (object , itemKey ));
207
254
}
208
255
209
256
if (strProfile .profile (key instanceof String )) {
210
257
try {
211
- return toForeign .executeConvert (readNode .executeObject (object , key ));
258
+ return toForeign .executeConvert (getReadNode () .executeObject (object , key ));
212
259
} catch (PException e ) {
213
260
// pass
214
261
}
215
262
}
216
- if (isSequence .execute (object )) {
263
+
264
+ if (getIsSequenceNode ().execute (object )) {
217
265
try {
218
- return toForeign .executeConvert (getItemNode .execute (object , key ));
266
+ return toForeign .executeConvert (getGetItemNode () .execute (object , key ));
219
267
} catch (PException e ) {
220
268
// pass
221
269
}
222
270
}
271
+
272
+ if (key instanceof Integer ) {
273
+ int intKey = (int ) key ;
274
+ if (getIsIterableNode ().execute (object )) {
275
+ if (getIter == null ) {
276
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
277
+ getIter = insert (LookupAndCallUnaryNode .create (SpecialMethodNames .__ITER__ ));
278
+ }
279
+ Object iter = getIter .executeObject (object );
280
+ if (iter != object ) {
281
+ // there is a separate iterator for this object, should be safe to consume
282
+ return iterateToKey (iter , intKey );
283
+ }
284
+ }
285
+ }
286
+
223
287
return NONEXISTING_IDENTIFIER ;
224
288
}
289
+
290
+ private Object iterateToKey (Object iter , int key ) {
291
+ if (callNext == null ) {
292
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
293
+ callNext = insert (LookupAndCallUnaryNode .create (SpecialMethodNames .__NEXT__ ));
294
+ }
295
+ Object value = NONEXISTING_IDENTIFIER ;
296
+ for (int i = 0 ; i <= key ; i ++) {
297
+ value = callNext .executeObject (iter );
298
+ }
299
+ return value ;
300
+ }
225
301
}
226
302
227
303
private static final class KeysNode extends Node {
@@ -534,6 +610,7 @@ public Object access(Object object) {
534
610
@ Resolve (message = "HAS_SIZE" )
535
611
abstract static class PForeignHasSizeNode extends Node {
536
612
@ Child private IsSequenceNode isSequenceNode ;
613
+ @ Child private IsIterableNode isIterableNode ;
537
614
@ Child private IsMappingNode isMappingNode ;
538
615
@ Child private BuiltinFunctions .LenNode lenNode ;
539
616
@ Child private PTypeUnboxNode unboxNode ;
@@ -543,7 +620,10 @@ abstract static class PForeignHasSizeNode extends Node {
543
620
544
621
public Object access (Object object ) {
545
622
Object profiled = profile .profile (object );
546
- if (getIsSequenceNode ().execute (profiled ) && !getIsMappingNode ().execute (profiled )) {
623
+ boolean isMapping = getIsMappingNode ().execute (profiled );
624
+ if (isMapping ) {
625
+ return false ;
626
+ } else if (getIsSequenceNode ().execute (profiled )) {
547
627
// also try to access using an integer index
548
628
int len = (int ) getUnboxNode ().execute (getLenNode ().executeWith (profiled ));
549
629
if (len > 0 ) {
@@ -555,6 +635,8 @@ public Object access(Object object) {
555
635
}
556
636
}
557
637
return true ;
638
+ } else if (getIsIterableNode ().execute (profiled )) {
639
+ return true ;
558
640
}
559
641
return false ;
560
642
}
@@ -583,6 +665,14 @@ private LookupAndCallBinaryNode getCallGetItemNode() {
583
665
return callGetItemNode ;
584
666
}
585
667
668
+ private IsIterableNode getIsIterableNode () {
669
+ if (isIterableNode == null ) {
670
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
671
+ isIterableNode = insert (IsIterableNode .create ());
672
+ }
673
+ return isIterableNode ;
674
+ }
675
+
586
676
private IsSequenceNode getIsSequenceNode () {
587
677
if (isSequenceNode == null ) {
588
678
CompilerDirectives .transferToInterpreterAndInvalidate ();
@@ -605,10 +695,47 @@ abstract static class PForeignGetSizeNode extends Node {
605
695
@ Child IsSequenceNode isSeq = IsSequenceNode .create ();
606
696
@ Child private BuiltinFunctions .LenNode lenNode = BuiltinFunctionsFactory .LenNodeFactory .create ();
607
697
@ Child private PTypeUnboxNode unboxNode = PTypeUnboxNode .create ();
698
+ @ Child private IsIterableNode isIter ;
699
+ @ Child private LookupInheritedAttributeNode getLenHint ;
700
+ @ Child private CallUnaryMethodNode callNode ;
701
+ @ Child private CastToListNode castToList ;
702
+ @ Child private LookupAndCallUnaryNode getIter ;
608
703
609
704
public Object access (Object object ) {
610
705
if (isSeq .execute (object )) {
611
706
return unboxNode .execute (lenNode .executeWith (object ));
707
+ } else {
708
+ if (isIter == null ) {
709
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
710
+ isIter = insert (IsIterableNode .create ());
711
+ }
712
+ if (isIter .execute (object )) {
713
+ if (getLenHint == null ) {
714
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
715
+ getLenHint = insert (LookupInheritedAttributeNode .create (SpecialMethodNames .__LENGTH_HINT__ ));
716
+ }
717
+ Object lenHint = getLenHint .execute (object );
718
+ if (lenHint != PNone .NO_VALUE ) {
719
+ if (callNode == null ) {
720
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
721
+ callNode = insert (CallUnaryMethodNode .create ());
722
+ }
723
+ return unboxNode .execute (callNode .executeObject (lenHint , object ));
724
+ }
725
+ if (getIter == null ) {
726
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
727
+ getIter = insert (LookupAndCallUnaryNode .create (SpecialMethodNames .__ITER__ ));
728
+ }
729
+ Object iter = getIter .executeObject (object );
730
+ if (iter != object ) {
731
+ if (castToList == null ) {
732
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
733
+ castToList = insert (CastToListNode .create ());
734
+ }
735
+ // there is a separate iterator for this object, should be safe to consume
736
+ return unboxNode .execute (lenNode .executeWith (castToList .executeWith (iter )));
737
+ }
738
+ }
612
739
}
613
740
throw UnsupportedMessageException .raise (Message .GET_SIZE );
614
741
}
@@ -633,6 +760,10 @@ abstract static class PKeyInfoNode extends Node {
633
760
@ Child private KeyForItemAccess itemKey = new KeyForItemAccess ();
634
761
635
762
public int access (Object object , Object fieldName ) {
763
+ if (fieldName instanceof Integer ) {
764
+ return KeyInfo .READABLE | KeyInfo .READ_SIDE_EFFECTS ;
765
+ }
766
+
636
767
String itemFieldName = itemKey .execute (fieldName );
637
768
if (itemFieldName != null ) {
638
769
return KeyInfo .READABLE | KeyInfo .MODIFIABLE | KeyInfo .REMOVABLE | KeyInfo .REMOVABLE ;
0 commit comments