38
38
import static com .oracle .graal .python .nodes .SpecialMethodNames .__ITER__ ;
39
39
import static com .oracle .graal .python .nodes .SpecialMethodNames .__REVERSED__ ;
40
40
import static com .oracle .graal .python .nodes .SpecialMethodNames .__LEN__ ;
41
- import static com .oracle .graal .python .nodes .SpecialMethodNames .__MISSING__ ;
42
41
import static com .oracle .graal .python .nodes .SpecialMethodNames .__SETITEM__ ;
43
42
import static com .oracle .graal .python .runtime .exception .PythonErrorType .KeyError ;
44
43
import static com .oracle .graal .python .runtime .exception .PythonErrorType .TypeError ;
44
+ import static com .oracle .graal .python .runtime .exception .PythonErrorType .RuntimeError ;
45
45
46
46
import java .util .List ;
47
47
51
51
import com .oracle .graal .python .builtins .PythonBuiltins ;
52
52
import com .oracle .graal .python .builtins .objects .PNone ;
53
53
import com .oracle .graal .python .builtins .objects .PNotImplemented ;
54
+ import com .oracle .graal .python .builtins .objects .common .EconomicMapStorage ;
54
55
import com .oracle .graal .python .builtins .objects .common .HashingCollectionNodes ;
55
56
import com .oracle .graal .python .builtins .objects .common .HashingCollectionNodes .GetDictStorageNode ;
56
57
import com .oracle .graal .python .builtins .objects .common .HashingCollectionNodes .SetDictStorageNode ;
57
58
import com .oracle .graal .python .builtins .objects .common .HashingStorage ;
58
59
import com .oracle .graal .python .builtins .objects .common .HashingStorage .DictEntry ;
59
60
import com .oracle .graal .python .builtins .objects .common .HashingStorage .StorageSupplier ;
60
61
import com .oracle .graal .python .builtins .objects .common .HashingStorageLibrary ;
62
+ import com .oracle .graal .python .builtins .objects .common .HashingStorageLibrary .HashingStorageIterator ;
61
63
import com .oracle .graal .python .builtins .objects .common .SequenceNodes ;
62
64
import com .oracle .graal .python .builtins .objects .function .PArguments ;
63
65
import com .oracle .graal .python .builtins .objects .function .PBuiltinFunction ;
64
66
import com .oracle .graal .python .builtins .objects .function .PKeyword ;
65
67
import com .oracle .graal .python .builtins .objects .mappingproxy .PMappingproxy ;
66
68
import com .oracle .graal .python .builtins .objects .method .PBuiltinMethod ;
69
+ import com .oracle .graal .python .builtins .objects .method .PMethod ;
67
70
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
68
71
import com .oracle .graal .python .builtins .objects .str .PString ;
69
72
import com .oracle .graal .python .builtins .objects .type .LazyPythonClass ;
70
73
import com .oracle .graal .python .builtins .objects .type .PythonBuiltinClass ;
71
74
import com .oracle .graal .python .nodes .ErrorMessages ;
72
- import com .oracle .graal .python .nodes .PGuards ;
73
75
import com .oracle .graal .python .nodes .PRaiseNode ;
76
+ import com .oracle .graal .python .nodes .SpecialMethodNames ;
77
+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__MISSING__ ;
74
78
import com .oracle .graal .python .nodes .builtins .ListNodes ;
75
79
import com .oracle .graal .python .nodes .call .CallNode ;
76
80
import com .oracle .graal .python .nodes .call .special .LookupAndCallBinaryNode ;
93
97
import com .oracle .truffle .api .dsl .Cached .Exclusive ;
94
98
import com .oracle .truffle .api .dsl .Fallback ;
95
99
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
100
+ import com .oracle .truffle .api .dsl .ImportStatic ;
96
101
import com .oracle .truffle .api .dsl .Specialization ;
97
102
import com .oracle .truffle .api .frame .VirtualFrame ;
98
103
import com .oracle .truffle .api .library .CachedLibrary ;
104
+ import com .oracle .truffle .api .nodes .Node ;
99
105
import com .oracle .truffle .api .profiles .BranchProfile ;
100
106
import com .oracle .truffle .api .profiles .ConditionProfile ;
101
107
@@ -271,18 +277,41 @@ public abstract static class GetItemNode extends PythonBinaryBuiltinNode {
271
277
Object getItem (VirtualFrame frame , PDict self , Object key ,
272
278
@ CachedLibrary (value = "self.getDictStorage()" ) HashingStorageLibrary hlib ,
273
279
@ Exclusive @ Cached ("createBinaryProfile()" ) ConditionProfile profile ,
274
- @ Cached ( "create(__MISSING__)" ) LookupAndCallBinaryNode specialNode ) {
280
+ @ Cached DispatchMissingNode missing ) {
275
281
final Object result = hlib .getItemWithFrame (self .getDictStorage (), key , profile , frame );
276
282
if (result == null ) {
277
- return specialNode . executeObject (frame , self , key );
283
+ return missing . execute (frame , self , key );
278
284
}
279
285
return result ;
280
286
}
281
287
}
282
288
283
- @ Builtin (name = __MISSING__ , minNumOfPositionalArgs = 2 )
284
- @ GenerateNodeFactory
285
- public abstract static class MissingNode extends PythonBinaryBuiltinNode {
289
+ @ ImportStatic (SpecialMethodNames .class )
290
+ protected abstract static class DispatchMissingNode extends Node {
291
+
292
+ protected abstract Object execute (VirtualFrame frame , Object self , Object key );
293
+
294
+ @ Specialization (guards = "hasMissing(self, lib)" , limit = "1" )
295
+ protected Object misssing (Object self , Object key ,
296
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
297
+ @ Exclusive @ Cached CallNode callNode ) {
298
+ return callNode .execute (lib .lookupAttribute (self , __MISSING__ ), key );
299
+ }
300
+
301
+ @ Specialization (guards = "!hasMissing(self, lib)" , limit = "1" )
302
+ protected Object misssing (VirtualFrame frame , Object self , Object key ,
303
+ @ SuppressWarnings ("unused" ) @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
304
+ @ Exclusive @ Cached DefaultMissingNode missing ) {
305
+ return missing .execute (frame , self , key );
306
+ }
307
+
308
+ protected boolean hasMissing (Object self , PythonObjectLibrary lib ) {
309
+ Object missing = lib .lookupAttribute (self , __MISSING__ );
310
+ return missing != PNone .NO_VALUE && missing instanceof PMethod ;
311
+ }
312
+ }
313
+
314
+ protected abstract static class DefaultMissingNode extends PythonBinaryBuiltinNode {
286
315
@ SuppressWarnings ("unused" )
287
316
@ Specialization
288
317
Object run (Object self , PString key ,
@@ -298,13 +327,8 @@ Object run(Object self, String key) {
298
327
299
328
@ SuppressWarnings ("unused" )
300
329
@ Specialization (guards = "!isString(key)" )
301
- Object run (VirtualFrame frame , Object self , Object key ,
302
- @ Cached ("create(__REPR__)" ) LookupAndCallUnaryNode specialNode ) {
303
- Object name = specialNode .executeObject (frame , key );
304
- if (!PGuards .isString (name )) {
305
- throw raise (TypeError , ErrorMessages .RETURNED_NON_STRING , "__repr__" , name );
306
- }
307
- throw raise (KeyError , "%s" , name );
330
+ Object run (VirtualFrame frame , Object self , Object key ) {
331
+ throw raise (KeyError , new Object []{key });
308
332
}
309
333
}
310
334
@@ -452,8 +476,10 @@ public abstract static class ClearNode extends PythonUnaryBuiltinNode {
452
476
453
477
@ Specialization (limit = "3" )
454
478
public PDict clear (PDict dict ,
455
- @ CachedLibrary ("dict.getDictStorage()" ) HashingStorageLibrary lib ) {
456
- lib .clear (dict .getDictStorage ());
479
+ @ CachedLibrary ("dict.getDictStorage()" ) HashingStorageLibrary lib ,
480
+ @ Cached SetDictStorageNode setStorage ) {
481
+ HashingStorage newStorage = lib .clear (dict .getDictStorage ());
482
+ setStorage .execute (dict , newStorage );
457
483
return dict ;
458
484
}
459
485
}
@@ -498,7 +524,7 @@ public Object update(VirtualFrame frame, PDict self, @SuppressWarnings("unused")
498
524
return PNone .NONE ;
499
525
}
500
526
501
- @ Specialization (guards = {"isDict (args)" , "kwargs.length == 0" })
527
+ @ Specialization (guards = {"isDictButNotEconomicMap (args, getStorage )" , "kwargs.length == 0" })
502
528
public Object updateDict (PDict self , Object [] args , @ SuppressWarnings ("unused" ) PKeyword [] kwargs ,
503
529
@ CachedLibrary (limit = "1" ) HashingStorageLibrary lib ,
504
530
@ Cached GetDictStorageNode getStorage ,
@@ -508,7 +534,7 @@ public Object updateDict(PDict self, Object[] args, @SuppressWarnings("unused")
508
534
return PNone .NONE ;
509
535
}
510
536
511
- @ Specialization (guards = {"isDict (args)" , "kwargs.length > 0" })
537
+ @ Specialization (guards = {"isDictButNotEconomicMap (args, getStorage )" , "kwargs.length > 0" })
512
538
public Object updateDict (VirtualFrame frame , PDict self , Object [] args , PKeyword [] kwargs ,
513
539
@ CachedLibrary (limit = "1" ) HashingStorageLibrary lib ,
514
540
@ Cached HashingStorage .InitNode initNode ,
@@ -520,6 +546,45 @@ public Object updateDict(VirtualFrame frame, PDict self, Object[] args, PKeyword
520
546
return PNone .NONE ;
521
547
}
522
548
549
+ @ Specialization (guards = {"isDictEconomicMap(args, getStorage)" , "kwargs.length == 0" }, limit = "1" )
550
+ public Object updateDict (PDict self , Object [] args , @ SuppressWarnings ("unused" ) PKeyword [] kwargs ,
551
+ @ Cached GetDictStorageNode getStorage ,
552
+ @ Cached SetDictStorageNode setStorage ,
553
+ @ CachedLibrary ("getStorage.execute(self)" ) HashingStorageLibrary libSelf ,
554
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary libOther ) {
555
+ HashingStorage newStorage = addAll (self , (PDict ) args [0 ], getStorage , libSelf , libOther );
556
+ setStorage .execute (self , newStorage );
557
+ return PNone .NONE ;
558
+ }
559
+
560
+ @ Specialization (guards = {"isDictEconomicMap(args, getStorage)" , "kwargs.length > 0" }, limit = "1" )
561
+ public Object updateDict (VirtualFrame frame , PDict self , Object [] args , PKeyword [] kwargs ,
562
+ @ Cached GetDictStorageNode getStorage ,
563
+ @ Cached SetDictStorageNode setStorage ,
564
+ @ CachedLibrary ("getStorage.execute(self)" ) HashingStorageLibrary libSelf ,
565
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary libOther ,
566
+ @ Cached HashingStorage .InitNode initNode ) {
567
+ HashingStorage newStorage = addAll (self , (PDict ) args [0 ], getStorage , libSelf , libOther );
568
+ newStorage = libOther .addAllToOther (initNode .execute (frame , PNone .NO_VALUE , kwargs ), newStorage );
569
+ setStorage .execute (self , newStorage );
570
+ return PNone .NONE ;
571
+ }
572
+
573
+ private HashingStorage addAll (PDict self , PDict other , GetDictStorageNode getStorage , HashingStorageLibrary libSelf , HashingStorageLibrary libOther ) throws PException {
574
+ HashingStorage selfStorage = getStorage .execute (self );
575
+ HashingStorage otherStorage = getStorage .execute (other );
576
+ HashingStorageIterator <DictEntry > itOther = libOther .entries (otherStorage ).iterator ();
577
+ HashingStorage newStorage = selfStorage ;
578
+ while (itOther .hasNext ()) {
579
+ DictEntry next = itOther .next ();
580
+ newStorage = libSelf .setItem (selfStorage , next .key , next .value );
581
+ if (otherStorage != getStorage .execute (other )) {
582
+ throw raise (RuntimeError , ErrorMessages .MUTATED_DURING_UPDATE , "dict" );
583
+ }
584
+ }
585
+ return newStorage ;
586
+ }
587
+
523
588
@ Specialization (guards = {"args.length == 1" , "!isDict(args)" , "hasKeysAttr(args, libArg)" })
524
589
public Object updateMapping (VirtualFrame frame , PDict self , Object [] args , PKeyword [] kwargs ,
525
590
@ SuppressWarnings ("unused" ) @ CachedLibrary (limit = "1" ) PythonObjectLibrary libArg ,
@@ -570,6 +635,14 @@ protected boolean isDict(Object[] args) {
570
635
return args .length == 1 && args [0 ] instanceof PDict ;
571
636
}
572
637
638
+ protected boolean isDictEconomicMap (Object [] args , GetDictStorageNode getStorage ) {
639
+ return args .length == 1 && args [0 ] instanceof PDict && getStorage .execute ((PDict ) args [0 ]) instanceof EconomicMapStorage ;
640
+ }
641
+
642
+ protected boolean isDictButNotEconomicMap (Object [] args , GetDictStorageNode getStorage ) {
643
+ return args .length == 1 && args [0 ] instanceof PDict && !(getStorage .execute ((PDict ) args [0 ]) instanceof EconomicMapStorage );
644
+ }
645
+
573
646
protected boolean isSeq (Object [] args ) {
574
647
return args .length == 1 && args [0 ] instanceof PSequence ;
575
648
}
0 commit comments