Skip to content

Commit 385d36e

Browse files
committed
Move filling defaults into nodes and use ExplodeLoop.
1 parent 6199e2b commit 385d36e

File tree

1 file changed

+153
-46
lines changed

1 file changed

+153
-46
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/CreateArgumentsNode.java

Lines changed: 153 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.ApplyPositionalArgumentsNodeGen;
5858
import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.CreateAndCheckArgumentsNodeGen;
5959
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;
6062
import com.oracle.graal.python.nodes.argument.CreateArgumentsNodeGen.HandleTooManyArgumentsNodeGen;
6163
import com.oracle.graal.python.runtime.PythonOptions;
6264
import com.oracle.graal.python.runtime.exception.PException;
@@ -66,6 +68,7 @@
6668
import com.oracle.truffle.api.dsl.Specialization;
6769
import com.oracle.truffle.api.nodes.ExplodeLoop;
6870
import com.oracle.truffle.api.nodes.Node;
71+
import com.oracle.truffle.api.profiles.ConditionProfile;
6972

7073
@ImportStatic({PythonOptions.class, PGuards.class})
7174
public abstract class CreateArgumentsNode extends PNodeWithContext {
@@ -141,6 +144,7 @@ protected abstract static class CreateAndCheckArgumentsNode extends PNodeWithCon
141144
@Child private HandleTooManyArgumentsNode handleTooManyArgumentsNode;
142145
@Child private ApplyPositionalArguments applyPositional = ApplyPositionalArguments.create();
143146
@Child private FillDefaultsNode fillDefaultsNode;
147+
@Child private FillKwDefaultsNode fillKwDefaultsNode;
144148

145149
public static CreateAndCheckArgumentsNode create() {
146150
return CreateAndCheckArgumentsNodeGen.create();
@@ -227,50 +231,18 @@ private Object[] createAndCheckArguments(PythonObject callable, Object[] args_w,
227231
}
228232

229233
if (too_many_args) {
234+
// the node acts as a profile
230235
throw handleTooManyArguments(scope_w, callable, arity, co_argcount, co_kwonlyargcount, defaults.length, avail, methodcall);
231236
}
232237

233238
boolean more_filling = input_argcount < co_argcount + co_kwonlyargcount;
234239
if (more_filling) {
235240

236-
String[] missingNames = new String[co_argcount + co_kwonlyargcount];
237-
238241
// 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);
251243

252244
// 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);
274246
}
275247

276248
return scope_w;
@@ -292,6 +264,22 @@ private PException handleTooManyArguments(Object[] scope_w, Object callable, Ari
292264
return handleTooManyArgumentsNode.execute(scope_w, callable, arity, co_argcount, co_kwonlyargcount, ndefaults, avail, methodcall);
293265
}
294266

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+
295283
}
296284

297285
protected abstract static class HandleTooManyArgumentsNode extends PNodeWithContext {
@@ -401,15 +389,32 @@ public static ApplyPositionalArguments create() {
401389
}
402390
}
403391

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 {
405408

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);
407410

408411
@Specialization(guards = {"input_argcount == cachedInputArgcount", "co_argcount == cachedArgcount", "checkIterations(input_argcount, co_argcount)"})
409412
@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,
411414
@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];
413418
int firstDefaultArgIdx = cachedArgcount - defaults.length;
414419
int missingCnt = 0;
415420
for (int i = cachedInputArgcount; i < cachedArgcount; i++) {
@@ -423,11 +428,15 @@ int doCached(Arity arity, Object[] scope_w, Object[] defaults, @SuppressWarnings
423428
missingNames[missingCnt++] = arity.getParameterIds()[i];
424429
}
425430
}
426-
return missingCnt;
431+
if (missingProfile.profile(missingCnt > 0)) {
432+
throw raiseMissing(callable, missingNames, missingCnt);
433+
}
427434
}
428435

429436
@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];
431440
int firstDefaultArgIdx = co_argcount - defaults.length;
432441
int missingCnt = 0;
433442
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
441450
missingNames[missingCnt++] = arity.getParameterIds()[i];
442451
}
443452
}
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+
}
449456
}
450457

451458
public static FillDefaultsNode create() {
452459
return FillDefaultsNodeGen.create();
453460
}
454461
}
455462

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+
456563
protected static Arity getArity(Object callable) {
457564
return getProperty(callable, ArityGetter.INSTANCE);
458565
}

0 commit comments

Comments
 (0)