57
57
import com .oracle .graal .python .nodes .argument .CreateArgumentsNodeGen .ApplyPositionalArgumentsNodeGen ;
58
58
import com .oracle .graal .python .nodes .argument .CreateArgumentsNodeGen .CreateAndCheckArgumentsNodeGen ;
59
59
import com .oracle .graal .python .nodes .argument .CreateArgumentsNodeGen .FillDefaultsNodeGen ;
60
+ import com .oracle .graal .python .nodes .argument .CreateArgumentsNodeGen .FillKwDefaultsNodeGen ;
61
+ import com .oracle .graal .python .nodes .argument .CreateArgumentsNodeGen .FindKwDefaultNodeGen ;
60
62
import com .oracle .graal .python .nodes .argument .CreateArgumentsNodeGen .HandleTooManyArgumentsNodeGen ;
61
63
import com .oracle .graal .python .runtime .PythonOptions ;
62
64
import com .oracle .graal .python .runtime .exception .PException ;
66
68
import com .oracle .truffle .api .dsl .Specialization ;
67
69
import com .oracle .truffle .api .nodes .ExplodeLoop ;
68
70
import com .oracle .truffle .api .nodes .Node ;
71
+ import com .oracle .truffle .api .profiles .ConditionProfile ;
69
72
70
73
@ ImportStatic ({PythonOptions .class , PGuards .class })
71
74
public abstract class CreateArgumentsNode extends PNodeWithContext {
@@ -141,6 +144,7 @@ protected abstract static class CreateAndCheckArgumentsNode extends PNodeWithCon
141
144
@ Child private HandleTooManyArgumentsNode handleTooManyArgumentsNode ;
142
145
@ Child private ApplyPositionalArguments applyPositional = ApplyPositionalArguments .create ();
143
146
@ Child private FillDefaultsNode fillDefaultsNode ;
147
+ @ Child private FillKwDefaultsNode fillKwDefaultsNode ;
144
148
145
149
public static CreateAndCheckArgumentsNode create () {
146
150
return CreateAndCheckArgumentsNodeGen .create ();
@@ -227,50 +231,18 @@ private Object[] createAndCheckArguments(PythonObject callable, Object[] args_w,
227
231
}
228
232
229
233
if (too_many_args ) {
234
+ // the node acts as a profile
230
235
throw handleTooManyArguments (scope_w , callable , arity , co_argcount , co_kwonlyargcount , defaults .length , avail , methodcall );
231
236
}
232
237
233
238
boolean more_filling = input_argcount < co_argcount + co_kwonlyargcount ;
234
239
if (more_filling ) {
235
240
236
- String [] missingNames = new String [co_argcount + co_kwonlyargcount ];
237
-
238
241
// then, fill the normal arguments with defaults_w (if needed)
239
- if (fillDefaultsNode == null ) {
240
- CompilerDirectives .transferToInterpreterAndInvalidate ();
241
- fillDefaultsNode = insert (FillDefaultsNode .create ());
242
- }
243
- int missingCnt = fillDefaultsNode .execute (arity , scope_w , defaults , input_argcount , co_argcount , missingNames );
244
- if (missingCnt > 0 ) {
245
- throw raise (PythonBuiltinClassType .TypeError , "%s() missing %d required positional argument%s: %s" ,
246
- getName (callable ),
247
- missingCnt ,
248
- missingCnt == 1 ? "" : "s" ,
249
- String .join ("," , Arrays .copyOf (missingNames , missingCnt )));
250
- }
242
+ fillDefaults (callable , arity , scope_w , defaults , input_argcount , co_argcount );
251
243
252
244
// finally, fill kwonly arguments with w_kw_defs (if needed)
253
- kwnames : for (int i = co_argcount ; i < co_argcount + co_kwonlyargcount ; i ++) {
254
- if (PArguments .getArgument (scope_w , i ) != null ) {
255
- continue ;
256
- }
257
- String kwname = arity .getKeywordNames ()[i - co_argcount ];
258
- for (int j = 0 ; j < kwdefaults .length ; j ++) {
259
- if (kwdefaults [j ].getName ().equals (kwname )) {
260
- PArguments .setArgument (scope_w , i , kwdefaults [j ].getValue ());
261
- continue kwnames ;
262
- }
263
- }
264
- missingNames [missingCnt ++] = kwname ;
265
- }
266
-
267
- if (missingCnt > 0 ) {
268
- throw raise (PythonBuiltinClassType .TypeError , "%s() missing %d required keyword-only argument%s: %s" ,
269
- getName (callable ),
270
- missingCnt ,
271
- missingCnt == 1 ? "" : "s" ,
272
- String .join ("," , Arrays .copyOf (missingNames , missingCnt )));
273
- }
245
+ fillKwDefaults (callable , scope_w , arity , kwdefaults , co_argcount , co_kwonlyargcount );
274
246
}
275
247
276
248
return scope_w ;
@@ -292,6 +264,22 @@ private PException handleTooManyArguments(Object[] scope_w, Object callable, Ari
292
264
return handleTooManyArgumentsNode .execute (scope_w , callable , arity , co_argcount , co_kwonlyargcount , ndefaults , avail , methodcall );
293
265
}
294
266
267
+ private void fillDefaults (Object callable , Arity arity , Object [] scope_w , Object [] defaults , int input_argcount , int co_argcount ) {
268
+ if (fillDefaultsNode == null ) {
269
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
270
+ fillDefaultsNode = insert (FillDefaultsNode .create ());
271
+ }
272
+ fillDefaultsNode .execute (callable , arity , scope_w , defaults , input_argcount , co_argcount );
273
+ }
274
+
275
+ private void fillKwDefaults (Object callable , Object [] scope_w , Arity arity , PKeyword [] kwdefaults , int co_argcount , int co_kwonlyargcount ) {
276
+ if (fillKwDefaultsNode == null ) {
277
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
278
+ fillKwDefaultsNode = insert (FillKwDefaultsNode .create ());
279
+ }
280
+ fillKwDefaultsNode .execute (callable , scope_w , arity , kwdefaults , co_argcount , co_kwonlyargcount );
281
+ }
282
+
295
283
}
296
284
297
285
protected abstract static class HandleTooManyArgumentsNode extends PNodeWithContext {
@@ -401,15 +389,32 @@ public static ApplyPositionalArguments create() {
401
389
}
402
390
}
403
391
404
- protected abstract static class FillDefaultsNode extends Node {
392
+ protected abstract static class FillBaseNode extends PNodeWithContext {
393
+
394
+ protected PException raiseMissing (Object callable , String [] missingNames , int missingCnt ) {
395
+ throw raise (PythonBuiltinClassType .TypeError , "%s() missing %d required positional argument%s: %s" ,
396
+ getName (callable ),
397
+ missingCnt ,
398
+ missingCnt == 1 ? "" : "s" ,
399
+ String .join ("," , Arrays .copyOf (missingNames , missingCnt )));
400
+ }
401
+
402
+ protected static boolean checkIterations (int input_argcount , int co_argcount ) {
403
+ return co_argcount - input_argcount < 32 ;
404
+ }
405
+ }
406
+
407
+ protected abstract static class FillDefaultsNode extends FillBaseNode {
405
408
406
- public abstract int execute (Arity arity , Object [] scope_w , Object [] defaults , int input_argcount , int co_argcount , String [] missingNames );
409
+ public abstract void execute (Object callable , Arity arity , Object [] scope_w , Object [] defaults , int input_argcount , int co_argcount );
407
410
408
411
@ Specialization (guards = {"input_argcount == cachedInputArgcount" , "co_argcount == cachedArgcount" , "checkIterations(input_argcount, co_argcount)" })
409
412
@ ExplodeLoop
410
- int doCached (Arity arity , Object [] scope_w , Object [] defaults , @ SuppressWarnings ("unused" ) int input_argcount , @ SuppressWarnings ("unused" ) int co_argcount , String [] missingNames ,
413
+ void doCached (Object callable , Arity arity , Object [] scope_w , Object [] defaults , @ SuppressWarnings ("unused" ) int input_argcount , @ SuppressWarnings ("unused" ) int co_argcount ,
411
414
@ Cached ("input_argcount" ) int cachedInputArgcount ,
412
- @ Cached ("co_argcount" ) int cachedArgcount ) {
415
+ @ Cached ("co_argcount" ) int cachedArgcount ,
416
+ @ Cached ("createBinaryProfile()" ) ConditionProfile missingProfile ) {
417
+ String [] missingNames = new String [cachedArgcount - cachedInputArgcount ];
413
418
int firstDefaultArgIdx = cachedArgcount - defaults .length ;
414
419
int missingCnt = 0 ;
415
420
for (int i = cachedInputArgcount ; i < cachedArgcount ; i ++) {
@@ -423,11 +428,15 @@ int doCached(Arity arity, Object[] scope_w, Object[] defaults, @SuppressWarnings
423
428
missingNames [missingCnt ++] = arity .getParameterIds ()[i ];
424
429
}
425
430
}
426
- return missingCnt ;
431
+ if (missingProfile .profile (missingCnt > 0 )) {
432
+ throw raiseMissing (callable , missingNames , missingCnt );
433
+ }
427
434
}
428
435
429
436
@ Specialization (replaces = "doCached" )
430
- int doUncached (Arity arity , Object [] scope_w , Object [] defaults , int input_argcount , int co_argcount , String [] missingNames ) {
437
+ void doUncached (Object callable , Arity arity , Object [] scope_w , Object [] defaults , int input_argcount , int co_argcount ,
438
+ @ Cached ("createBinaryProfile()" ) ConditionProfile missingProfile ) {
439
+ String [] missingNames = new String [co_argcount - input_argcount ];
431
440
int firstDefaultArgIdx = co_argcount - defaults .length ;
432
441
int missingCnt = 0 ;
433
442
for (int i = input_argcount ; i < co_argcount ; i ++) {
@@ -441,18 +450,116 @@ int doUncached(Arity arity, Object[] scope_w, Object[] defaults, int input_argco
441
450
missingNames [missingCnt ++] = arity .getParameterIds ()[i ];
442
451
}
443
452
}
444
- return missingCnt ;
445
- }
446
-
447
- protected static boolean checkIterations (int input_argcount , int co_argcount ) {
448
- return co_argcount - input_argcount < 32 ;
453
+ if (missingProfile .profile (missingCnt > 0 )) {
454
+ throw raiseMissing (callable , missingNames , missingCnt );
455
+ }
449
456
}
450
457
451
458
public static FillDefaultsNode create () {
452
459
return FillDefaultsNodeGen .create ();
453
460
}
454
461
}
455
462
463
+ protected abstract static class FillKwDefaultsNode extends FillBaseNode {
464
+
465
+ @ Child private FindKwDefaultNode findKwDefaultNode ;
466
+
467
+ public abstract void execute (Object callable , Object [] scope_w , Arity arity , PKeyword [] kwdefaults , int co_argcount , int co_kwonlyargcount );
468
+
469
+ @ Specialization (guards = {"co_argcount == cachedArgcount" , "co_kwonlyargcount == cachedKwOnlyArgcount" , "checkIterations(co_argcount, co_kwonlyargcount)" })
470
+ @ ExplodeLoop
471
+ void doCached (Object callable , Object [] scope_w , Arity arity , PKeyword [] kwdefaults , @ SuppressWarnings ("unused" ) int co_argcount , @ SuppressWarnings ("unused" ) int co_kwonlyargcount ,
472
+ @ Cached ("co_argcount" ) int cachedArgcount ,
473
+ @ Cached ("co_kwonlyargcount" ) int cachedKwOnlyArgcount ,
474
+ @ Cached ("createBinaryProfile()" ) ConditionProfile missingProfile ) {
475
+ String [] missingNames = new String [cachedKwOnlyArgcount ];
476
+ int missingCnt = 0 ;
477
+ for (int i = cachedArgcount ; i < cachedArgcount + cachedKwOnlyArgcount ; i ++) {
478
+ if (PArguments .getArgument (scope_w , i ) != null ) {
479
+ continue ;
480
+ }
481
+
482
+ String kwname = arity .getKeywordNames ()[i - cachedArgcount ];
483
+ PKeyword kwdefault = findKwDefault (kwdefaults , kwname );
484
+ if (kwdefault != null ) {
485
+ PArguments .setArgument (scope_w , i , kwdefault .getValue ());
486
+ } else {
487
+ missingNames [missingCnt ++] = kwname ;
488
+ }
489
+ }
490
+ if (missingProfile .profile (missingCnt > 0 )) {
491
+ throw raiseMissing (callable , missingNames , missingCnt );
492
+ }
493
+ }
494
+
495
+ @ Specialization (replaces = "doCached" )
496
+ void doUncached (Object callable , Object [] scope_w , Arity arity , PKeyword [] kwdefaults , int co_argcount , int co_kwonlyargcount ,
497
+ @ Cached ("createBinaryProfile()" ) ConditionProfile missingProfile ) {
498
+ String [] missingNames = new String [co_kwonlyargcount ];
499
+ int missingCnt = 0 ;
500
+ for (int i = co_argcount ; i < co_argcount + co_kwonlyargcount ; i ++) {
501
+ if (PArguments .getArgument (scope_w , i ) != null ) {
502
+ continue ;
503
+ }
504
+
505
+ String kwname = arity .getKeywordNames ()[i - co_argcount ];
506
+ PKeyword kwdefault = findKwDefault (kwdefaults , kwname );
507
+ if (kwdefault != null ) {
508
+ PArguments .setArgument (scope_w , i , kwdefault .getValue ());
509
+ } else {
510
+ missingNames [missingCnt ++] = kwname ;
511
+ }
512
+ }
513
+ if (missingProfile .profile (missingCnt > 0 )) {
514
+ throw raiseMissing (callable , missingNames , missingCnt );
515
+ }
516
+ }
517
+
518
+ private PKeyword findKwDefault (PKeyword [] kwdefaults , String kwname ) {
519
+ if (findKwDefaultNode == null ) {
520
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
521
+ findKwDefaultNode = insert (FindKwDefaultNode .create ());
522
+ }
523
+ return findKwDefaultNode .execute (kwdefaults , kwname );
524
+ }
525
+
526
+ public static FillKwDefaultsNode create () {
527
+ return FillKwDefaultsNodeGen .create ();
528
+ }
529
+ }
530
+
531
+ /** finds a keyword-default value by a given name */
532
+ protected abstract static class FindKwDefaultNode extends Node {
533
+
534
+ public abstract PKeyword execute (PKeyword [] kwdefaults , String kwname );
535
+
536
+ @ Specialization (guards = {"kwdefaults.length == cachedLength" , "kwdefaults.length < 32" })
537
+ @ ExplodeLoop
538
+ PKeyword doCached (PKeyword [] kwdefaults , String kwname ,
539
+ @ Cached ("kwdefaults.length" ) int cachedLength ) {
540
+ for (int j = 0 ; j < cachedLength ; j ++) {
541
+ if (kwdefaults [j ].getName ().equals (kwname )) {
542
+ return kwdefaults [j ];
543
+ }
544
+ }
545
+ return null ;
546
+ }
547
+
548
+ @ Specialization (replaces = "doCached" )
549
+ PKeyword doUncached (PKeyword [] kwdefaults , String kwname ) {
550
+ for (int j = 0 ; j < kwdefaults .length ; j ++) {
551
+ if (kwdefaults [j ].getName ().equals (kwname )) {
552
+ return kwdefaults [j ];
553
+ }
554
+ }
555
+ return null ;
556
+ }
557
+
558
+ public static FindKwDefaultNode create () {
559
+ return FindKwDefaultNodeGen .create ();
560
+ }
561
+ }
562
+
456
563
protected static Arity getArity (Object callable ) {
457
564
return getProperty (callable , ArityGetter .INSTANCE );
458
565
}
0 commit comments