|
56 | 56 | import com.oracle.graal.python.nodes.PNodeWithContext;
|
57 | 57 | import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.ApplyPositionalArgumentsNodeGen;
|
58 | 58 | import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.CreateAndCheckArgumentsNodeGen;
|
| 59 | +import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.FillDefaultsNodeGen; |
59 | 60 | import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.HandleTooManyArgumentsNodeGen;
|
60 | 61 | import com.oracle.graal.python.runtime.PythonOptions;
|
61 | 62 | import com.oracle.graal.python.runtime.exception.PException;
|
@@ -139,6 +140,7 @@ protected abstract static class CreateAndCheckArgumentsNode extends PNodeWithCon
|
139 | 140 | @Child private ApplyKeywordsNode applyKeywords;
|
140 | 141 | @Child private HandleTooManyArgumentsNode handleTooManyArgumentsNode;
|
141 | 142 | @Child private ApplyPositionalArguments applyPositional = ApplyPositionalArguments.create();
|
| 143 | + @Child private FillDefaultsNode fillDefaultsNode; |
142 | 144 |
|
143 | 145 | public static CreateAndCheckArgumentsNode create() {
|
144 | 146 | return CreateAndCheckArgumentsNodeGen.create();
|
@@ -230,24 +232,15 @@ private Object[] createAndCheckArguments(PythonObject callable, Object[] args_w,
|
230 | 232 |
|
231 | 233 | boolean more_filling = input_argcount < co_argcount + co_kwonlyargcount;
|
232 | 234 | if (more_filling) {
|
233 |
| - int firstDefaultArgIdx = co_argcount - defaults.length; |
234 | 235 |
|
235 |
| - int missingCnt = 0; |
236 | 236 | String[] missingNames = new String[co_argcount + co_kwonlyargcount];
|
237 | 237 |
|
238 | 238 | // then, fill the normal arguments with defaults_w (if needed)
|
239 |
| - for (int i = input_argcount; i < co_argcount; i++) { |
240 |
| - if (PArguments.getArgument(scope_w, i) != null) { |
241 |
| - continue; |
242 |
| - } |
243 |
| - int defnum = i - firstDefaultArgIdx; |
244 |
| - if (defnum >= 0) { |
245 |
| - PArguments.setArgument(scope_w, i, defaults[defnum]); |
246 |
| - } else { |
247 |
| - missingNames[missingCnt++] = arity.getParameterIds()[i]; |
248 |
| - } |
| 239 | + if (fillDefaultsNode == null) { |
| 240 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 241 | + fillDefaultsNode = insert(FillDefaultsNode.create()); |
249 | 242 | }
|
250 |
| - |
| 243 | + int missingCnt = fillDefaultsNode.execute(arity, scope_w, defaults, input_argcount, co_argcount, missingNames); |
251 | 244 | if (missingCnt > 0) {
|
252 | 245 | throw raise(PythonBuiltinClassType.TypeError, "%s() missing %d required positional argument%s: %s",
|
253 | 246 | getName(callable),
|
@@ -408,6 +401,58 @@ public static ApplyPositionalArguments create() {
|
408 | 401 | }
|
409 | 402 | }
|
410 | 403 |
|
| 404 | + protected abstract static class FillDefaultsNode extends Node { |
| 405 | + |
| 406 | + public abstract int execute(Arity arity, Object[] scope_w, Object[] defaults, int input_argcount, int co_argcount, String[] missingNames); |
| 407 | + |
| 408 | + @Specialization(guards = {"input_argcount == cachedInputArgcount", "co_argcount == cachedArgcount", "checkIterations(input_argcount, co_argcount)"}) |
| 409 | + @ExplodeLoop |
| 410 | + int doCached(Arity arity, Object[] scope_w, Object[] defaults, @SuppressWarnings("unused") int input_argcount, @SuppressWarnings("unused") int co_argcount, String[] missingNames, |
| 411 | + @Cached("input_argcount") int cachedInputArgcount, |
| 412 | + @Cached("co_argcount") int cachedArgcount) { |
| 413 | + int firstDefaultArgIdx = cachedArgcount - defaults.length; |
| 414 | + int missingCnt = 0; |
| 415 | + for (int i = cachedInputArgcount; i < cachedArgcount; i++) { |
| 416 | + if (PArguments.getArgument(scope_w, i) != null) { |
| 417 | + continue; |
| 418 | + } |
| 419 | + int defnum = i - firstDefaultArgIdx; |
| 420 | + if (defnum >= 0) { |
| 421 | + PArguments.setArgument(scope_w, i, defaults[defnum]); |
| 422 | + } else { |
| 423 | + missingNames[missingCnt++] = arity.getParameterIds()[i]; |
| 424 | + } |
| 425 | + } |
| 426 | + return missingCnt; |
| 427 | + } |
| 428 | + |
| 429 | + @Specialization(replaces = "doCached") |
| 430 | + int doUncached(Arity arity, Object[] scope_w, Object[] defaults, int input_argcount, int co_argcount, String[] missingNames) { |
| 431 | + int firstDefaultArgIdx = co_argcount - defaults.length; |
| 432 | + int missingCnt = 0; |
| 433 | + for (int i = input_argcount; i < co_argcount; i++) { |
| 434 | + if (PArguments.getArgument(scope_w, i) != null) { |
| 435 | + continue; |
| 436 | + } |
| 437 | + int defnum = i - firstDefaultArgIdx; |
| 438 | + if (defnum >= 0) { |
| 439 | + PArguments.setArgument(scope_w, i, defaults[defnum]); |
| 440 | + } else { |
| 441 | + missingNames[missingCnt++] = arity.getParameterIds()[i]; |
| 442 | + } |
| 443 | + } |
| 444 | + return missingCnt; |
| 445 | + } |
| 446 | + |
| 447 | + protected static boolean checkIterations(int input_argcount, int co_argcount) { |
| 448 | + return co_argcount - input_argcount < 32; |
| 449 | + } |
| 450 | + |
| 451 | + public static FillDefaultsNode create() { |
| 452 | + return FillDefaultsNodeGen.create(); |
| 453 | + } |
| 454 | + } |
| 455 | + |
411 | 456 | protected static Arity getArity(Object callable) {
|
412 | 457 | return getProperty(callable, ArityGetter.INSTANCE);
|
413 | 458 | }
|
|
0 commit comments