Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 20984:6361fa2e3321
Truffle-DSL: further fixes for polymorphic execute signatures.
author | Christian Humer <christian.humer@oracle.com> |
---|---|
date | Wed, 15 Apr 2015 21:13:43 +0200 |
parents | 05a2b72c071f |
children | ef2825da2e43 |
comparison
equal
deleted
inserted
replaced
20983:b99da6d86cfe | 20984:6361fa2e3321 |
---|---|
64 private final TypeMirror genericType; | 64 private final TypeMirror genericType; |
65 private final DSLOptions options; | 65 private final DSLOptions options; |
66 private final boolean singleSpecializable; | 66 private final boolean singleSpecializable; |
67 private final int varArgsThreshold; | 67 private final int varArgsThreshold; |
68 private final Set<TypeMirror> expectedTypes = new HashSet<>(); | 68 private final Set<TypeMirror> expectedTypes = new HashSet<>(); |
69 private final Set<NodeExecutionData> usedExecuteChildMethods = new HashSet<>(); | |
69 private boolean nextUsed; | 70 private boolean nextUsed; |
71 | |
70 private List<ExecutableTypeData> usedTypes; | 72 private List<ExecutableTypeData> usedTypes; |
71 private List<SpecializationData> reachableSpecializations; | 73 private List<SpecializationData> reachableSpecializations; |
72 | 74 |
73 public NodeGenFactory(ProcessorContext context, NodeData node) { | 75 public NodeGenFactory(ProcessorContext context, NodeData node) { |
74 this.context = context; | 76 this.context = context; |
208 clazz.add(createNodeField(PRIVATE, getType(boolean.class), excludedFieldName(specialization), CompilationFinal.class)); | 210 clazz.add(createNodeField(PRIVATE, getType(boolean.class), excludedFieldName(specialization), CompilationFinal.class)); |
209 } | 211 } |
210 } | 212 } |
211 | 213 |
212 for (ExecutableTypeData execType : usedTypes) { | 214 for (ExecutableTypeData execType : usedTypes) { |
213 if (execType.getMethod() == null) { | 215 if (!singleSpecializable && execType.getMethod() == null) { |
214 continue; | 216 continue; |
215 } | 217 } |
216 clazz.add(createExecutableTypeOverride(usedTypes, execType)); | 218 clazz.add(createExecutableTypeOverride(usedTypes, execType)); |
217 } | 219 } |
218 | 220 |
271 } | 273 } |
272 } | 274 } |
273 | 275 |
274 private Element createUnsupportedMethod() { | 276 private Element createUnsupportedMethod() { |
275 LocalContext locals = LocalContext.load(this); | 277 LocalContext locals = LocalContext.load(this); |
276 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED), getType(UnsupportedSpecializationException.class), "unsupported"); | 278 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED), getType(UnsupportedSpecializationException.class), "unsupported", varArgsThreshold); |
277 | 279 |
278 CodeTreeBuilder builder = method.createBuilder(); | 280 CodeTreeBuilder builder = method.createBuilder(); |
279 builder.startReturn(); | 281 builder.startReturn(); |
280 builder.startNew(getType(UnsupportedSpecializationException.class)); | 282 builder.startNew(getType(UnsupportedSpecializationException.class)); |
281 builder.string("this"); | 283 builder.string("this"); |
378 baseSpecialization.addOptional(createCreateNext(generated)); | 380 baseSpecialization.addOptional(createCreateNext(generated)); |
379 baseSpecialization.addOptional(createCreateFallback(generated)); | 381 baseSpecialization.addOptional(createCreateFallback(generated)); |
380 baseSpecialization.addOptional(createCreatePolymorphic(generated)); | 382 baseSpecialization.addOptional(createCreatePolymorphic(generated)); |
381 baseSpecialization.addOptional(createGetNext(baseSpecialization)); | 383 baseSpecialization.addOptional(createGetNext(baseSpecialization)); |
382 | 384 |
385 for (NodeExecutionData execution : node.getChildExecutions()) { | |
386 Collection<TypeMirror> specializedTypes = node.findSpecializedTypes(execution); | |
387 specializedTypes.add(genericType); | |
388 for (TypeMirror specializedType : specializedTypes) { | |
389 if (isExecuteChildShared(execution, specializedType)) { | |
390 baseSpecialization.addOptional(createExecuteChildMethod(execution, specializedType)); | |
391 } | |
392 } | |
393 } | |
394 | |
383 return node.getUninitializedSpecialization(); | 395 return node.getUninitializedSpecialization(); |
384 } | 396 } |
385 | 397 |
386 private boolean needsPolymorphic() { | 398 private boolean needsPolymorphic() { |
387 if (reachableSpecializations.size() != 1) { | 399 if (reachableSpecializations.size() != 1) { |
416 | 428 |
417 for (ExecutableTypeData type : usedTypes) { | 429 for (ExecutableTypeData type : usedTypes) { |
418 clazz.add(createFastPathExecuteMethod(null, type, usedTypes)); | 430 clazz.add(createFastPathExecuteMethod(null, type, usedTypes)); |
419 } | 431 } |
420 | 432 |
421 for (NodeExecutionData execution : node.getChildExecutions()) { | |
422 Collection<TypeMirror> specializedTypes = node.findSpecializedTypes(execution); | |
423 specializedTypes.add(genericType); | |
424 for (TypeMirror specializedType : specializedTypes) { | |
425 if (isExecuteChildShared(execution, specializedType)) { | |
426 clazz.add(createExecuteChildMethod(execution, specializedType)); | |
427 } | |
428 } | |
429 } | |
430 | |
431 return clazz; | 433 return clazz; |
432 } | 434 } |
433 | 435 |
434 private Element createAcceptAndExecute() { | 436 private Element createAcceptAndExecute() { |
435 | 437 ExecutableTypeData executableElement = createSpecializationNodeSignature(node.getSignatureSize()); |
436 TypeMirror[] parameters = new TypeMirror[node.getSignatureSize()]; | 438 LocalContext currentLocals = LocalContext.load(this, executableElement, varArgsThreshold); |
437 Arrays.fill(parameters, genericType); | 439 CodeExecutableElement executable = createExecuteMethod(null, executableElement, currentLocals, false, varArgsThreshold); |
438 | |
439 ExecutableTypeData executableElement = new ExecutableTypeData(genericType, "acceptAndExecute", context.getType(Frame.class), Arrays.asList(parameters)); | |
440 | |
441 LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); | |
442 CodeExecutableElement executable = createExecuteMethod(null, executableElement, currentLocals, false); | |
443 | 440 |
444 executable.getModifiers().add(FINAL); | 441 executable.getModifiers().add(FINAL); |
445 CodeTreeBuilder builder = executable.createBuilder(); | 442 CodeTreeBuilder builder = executable.createBuilder(); |
446 | 443 |
447 CodeTree receiver = CodeTreeBuilder.singleString("this"); | 444 CodeTree receiver = CodeTreeBuilder.singleString("this"); |
448 | 445 |
449 builder.tree(createCallDelegateExecute(builder, receiver, currentLocals, executableElement, node.getGenericExecutableType(null))); | 446 builder.tree(createCallDelegateExecute(builder, receiver, currentLocals, executableElement, node.getGenericExecutableType(null))); |
450 | 447 |
451 return executable; | 448 return executable; |
449 } | |
450 | |
451 private ExecutableTypeData createSpecializationNodeSignature(int argumentCount) { | |
452 TypeMirror[] parameters = new TypeMirror[argumentCount]; | |
453 Arrays.fill(parameters, genericType); | |
454 return new ExecutableTypeData(node, genericType, "acceptAndExecute", context.getType(Frame.class), Arrays.asList(parameters)); | |
452 } | 455 } |
453 | 456 |
454 private boolean shouldImplementExecutableType(SpecializationData specialization, ExecutableTypeData executableType) { | 457 private boolean shouldImplementExecutableType(SpecializationData specialization, ExecutableTypeData executableType) { |
455 // always implement the root execute method. they are declared abstract in the base node. | 458 // always implement the root execute method. they are declared abstract in the base node. |
456 if (executableType.getDelegatedTo() == null) { | 459 if (executableType.getDelegatedTo() == null) { |
457 return true; | 460 return true; |
458 } | 461 } |
459 | 462 |
460 // specializations with more parameters are just ignored | 463 // specializations with more parameters are just ignored |
461 if (executableType.getEvaluatedCount() > node.getSignatureSize()) { | 464 if (executableType.getEvaluatedCount() > node.getExecutionCount()) { |
462 return false; | 465 return false; |
463 } | 466 } |
464 | 467 |
465 if (!isSubtypeBoxed(context, specialization.getReturnType().getType(), executableType.getReturnType())) { | 468 if (!isSubtypeBoxed(context, specialization.getReturnType().getType(), executableType.getReturnType())) { |
466 return false; | 469 return false; |
467 } | 470 } |
468 | 471 |
469 // the evaluated signature might be compatible to the specialization | 472 // the evaluated signature might be compatible to the specialization |
470 boolean specializationCompatible = true; | 473 boolean specializationCompatible = true; |
471 for (int i = 0; i < executableType.getEvaluatedCount(); i++) { | 474 List<TypeMirror> signatureParameters = executableType.getSignatureParameters(); |
472 TypeMirror evaluatedType = executableType.getEvaluatedParameters().get(i); | 475 for (int i = 0; i < signatureParameters.size(); i++) { |
476 TypeMirror evaluatedType = signatureParameters.get(i); | |
473 TypeMirror specializedType = specialization.findParameterOrDie(node.getChildExecutions().get(i)).getType(); | 477 TypeMirror specializedType = specialization.findParameterOrDie(node.getChildExecutions().get(i)).getType(); |
474 | 478 |
475 if (!isSubtypeBoxed(context, evaluatedType, specializedType) && !isSubtypeBoxed(context, specializedType, evaluatedType)) { | 479 if (!isSubtypeBoxed(context, evaluatedType, specializedType) && !isSubtypeBoxed(context, specializedType, evaluatedType)) { |
476 specializationCompatible = false; | 480 specializationCompatible = false; |
477 break; | 481 break; |
487 return true; | 491 return true; |
488 } | 492 } |
489 } | 493 } |
490 | 494 |
491 // trigger type boxing elimination for unevaluated arguments | 495 // trigger type boxing elimination for unevaluated arguments |
492 for (int i = executableType.getEvaluatedCount(); i < node.getSignatureSize(); i++) { | 496 for (int i = executableType.getEvaluatedCount(); i < node.getExecutionCount(); i++) { |
493 NodeExecutionData execution = node.getChildExecutions().get(i); | 497 NodeExecutionData execution = node.getChildExecutions().get(i); |
494 TypeMirror specializedType = specialization.findParameterOrDie(execution).getType(); | 498 TypeMirror specializedType = specialization.findParameterOrDie(execution).getType(); |
495 if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), specializedType)) { | 499 if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), specializedType)) { |
496 // it does not make sense to do type boxing elimination for children with | 500 // it does not make sense to do type boxing elimination for children with |
497 // no type specialized execute method | 501 // no type specialized execute method |
510 return true; | 514 return true; |
511 } | 515 } |
512 } | 516 } |
513 | 517 |
514 // trigger generation for evaluated assignable type matches other than generic | 518 // trigger generation for evaluated assignable type matches other than generic |
515 for (int i = 0; i < executableType.getEvaluatedCount(); i++) { | 519 for (int i = 0; i < signatureParameters.size(); i++) { |
516 TypeMirror evaluatedType = executableType.getEvaluatedParameters().get(i); | 520 TypeMirror evaluatedType = signatureParameters.get(i); |
517 NodeExecutionData execution = node.getChildExecutions().get(i); | 521 NodeExecutionData execution = node.getChildExecutions().get(i); |
518 TypeMirror specializedType = specialization.findParameterOrDie(execution).getType(); | 522 TypeMirror specializedType = specialization.findParameterOrDie(execution).getType(); |
519 | 523 |
520 if (isSubtypeBoxed(context, evaluatedType, specializedType) && !isObject(specializedType)) { | 524 if (isSubtypeBoxed(context, evaluatedType, specializedType) && !isObject(specializedType)) { |
521 return true; | 525 return true; |
662 boolean cacheBoundGuard = specialization.hasMultipleInstances(); | 666 boolean cacheBoundGuard = specialization.hasMultipleInstances(); |
663 if (!cacheBoundGuard) { | 667 if (!cacheBoundGuard) { |
664 return null; | 668 return null; |
665 } | 669 } |
666 | 670 |
667 LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); | 671 LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold); |
668 currentLocals.loadFastPathState(specialization); | 672 currentLocals.loadFastPathState(specialization); |
669 | 673 |
670 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isIdentical"); | 674 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isIdentical"); |
671 method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other")); | 675 method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other")); |
672 currentLocals.addParametersTo(method, FRAME_VALUE); | 676 currentLocals.addParametersTo(method, varArgsThreshold, FRAME_VALUE); |
673 method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); | 677 method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); |
674 final CodeTreeBuilder builder = method.createBuilder(); | 678 final CodeTreeBuilder builder = method.createBuilder(); |
675 | 679 |
676 SpecializationGroup group = SpecializationGroup.create(specialization); | 680 SpecializationGroup group = SpecializationGroup.create(specialization); |
677 SpecializationBody executionFactory = new SpecializationBody(true, false) { | 681 SpecializationBody executionFactory = new SpecializationBody(true, false) { |
727 private Element createMergeMethod(SpecializationData specialization) { | 731 private Element createMergeMethod(SpecializationData specialization) { |
728 if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic()) { | 732 if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic()) { |
729 return null; | 733 return null; |
730 } | 734 } |
731 TypeMirror specializationNodeType = getType(SpecializationNode.class); | 735 TypeMirror specializationNodeType = getType(SpecializationNode.class); |
732 LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); | 736 LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold); |
733 | 737 |
734 CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), specializationNodeType, "merge"); | 738 CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), specializationNodeType, "merge"); |
735 executable.addParameter(new CodeVariableElement(specializationNodeType, "newNode")); | 739 executable.addParameter(new CodeVariableElement(specializationNodeType, "newNode")); |
736 currentLocals.addParametersTo(executable, FRAME_VALUE); | 740 currentLocals.addParametersTo(executable, varArgsThreshold, FRAME_VALUE); |
737 executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); | 741 executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); |
738 CodeTreeBuilder builder = executable.createBuilder(); | 742 CodeTreeBuilder builder = executable.createBuilder(); |
739 | 743 |
740 if (specialization.isPolymorphic()) { | 744 if (specialization.isPolymorphic()) { |
741 builder.startReturn(); | 745 builder.startReturn(); |
800 } | 804 } |
801 | 805 |
802 private CodeExecutableElement createCreateNext(final Map<SpecializationData, CodeTypeElement> specializationClasses) { | 806 private CodeExecutableElement createCreateNext(final Map<SpecializationData, CodeTypeElement> specializationClasses) { |
803 final LocalContext locals = LocalContext.load(this); | 807 final LocalContext locals = LocalContext.load(this); |
804 | 808 |
805 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), getType(SpecializationNode.class), "createNext", FRAME_VALUE); | 809 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), getType(SpecializationNode.class), "createNext", varArgsThreshold, FRAME_VALUE); |
806 method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); | 810 method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); |
807 | 811 |
808 CodeTreeBuilder builder = method.createBuilder(); | 812 CodeTreeBuilder builder = method.createBuilder(); |
809 SpecializationGroup group = createSpecializationGroups(); | 813 SpecializationGroup group = createSpecializationGroups(); |
810 CodeTree execution = createGuardAndCast(group, genericType, locals, new SpecializationBody(false, false) { | 814 CodeTree execution = createGuardAndCast(group, genericType, locals, new SpecializationBody(false, false) { |
832 | 836 |
833 if (!frameUsed) { | 837 if (!frameUsed) { |
834 locals.removeValue(FRAME_VALUE); | 838 locals.removeValue(FRAME_VALUE); |
835 } | 839 } |
836 | 840 |
837 CodeExecutableElement boundaryMethod = locals.createMethod(modifiers(PRIVATE), getType(boolean.class), "guardFallback", FRAME_VALUE); | 841 CodeExecutableElement boundaryMethod = locals.createMethod(modifiers(PRIVATE), getType(boolean.class), "guardFallback", varArgsThreshold, FRAME_VALUE); |
838 if (!frameUsed) { | 842 if (!frameUsed) { |
839 boundaryMethod.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(TruffleBoundary.class))); | 843 boundaryMethod.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(TruffleBoundary.class))); |
840 } | 844 } |
841 | 845 |
842 CodeTreeBuilder builder = boundaryMethod.createBuilder(); | 846 CodeTreeBuilder builder = boundaryMethod.createBuilder(); |
885 if (fallback == null || optimizeFallback(fallback) || fallback.getMethod() == null) { | 889 if (fallback == null || optimizeFallback(fallback) || fallback.getMethod() == null) { |
886 return null; | 890 return null; |
887 } | 891 } |
888 LocalContext locals = LocalContext.load(this); | 892 LocalContext locals = LocalContext.load(this); |
889 | 893 |
890 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", FRAME_VALUE); | 894 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", varArgsThreshold, FRAME_VALUE); |
891 method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); | 895 method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); |
892 | 896 |
893 CodeTreeBuilder builder = method.createBuilder(); | 897 CodeTreeBuilder builder = method.createBuilder(); |
894 builder.startReturn(); | 898 builder.startReturn(); |
895 builder.tree(callTemplateMethod(accessParent(null), fallback, locals)); | 899 builder.tree(callTemplateMethod(accessParent(null), fallback, locals)); |
948 throw new AssertionError(); | 952 throw new AssertionError(); |
949 } | 953 } |
950 } | 954 } |
951 | 955 |
952 private CodeExecutableElement createExecutableTypeOverride(List<ExecutableTypeData> usedExecutables, ExecutableTypeData execType) { | 956 private CodeExecutableElement createExecutableTypeOverride(List<ExecutableTypeData> usedExecutables, ExecutableTypeData execType) { |
953 LocalContext locals = LocalContext.load(this, execType.getEvaluatedCount(), Integer.MAX_VALUE); | 957 LocalContext locals = LocalContext.load(this, execType, Integer.MAX_VALUE); |
954 CodeExecutableElement method = createExecuteMethod(null, execType, locals, true); | 958 CodeExecutableElement method = createExecuteMethod(null, execType, locals, true, Integer.MAX_VALUE); |
955 | 959 |
956 CodeTreeBuilder builder = method.createBuilder(); | 960 CodeTreeBuilder builder = method.createBuilder(); |
957 if (singleSpecializable) { | 961 if (singleSpecializable) { |
958 SpecializationData specialization = reachableSpecializations.iterator().next(); | 962 SpecializationData specialization = reachableSpecializations.iterator().next(); |
959 builder.tree(createFastPath(builder, specialization, execType, usedExecutables, locals)); | 963 builder.tree(createFastPath(builder, specialization, execType, usedExecutables, locals)); |
1041 values.add(CodeTreeBuilder.singleString("null")); | 1045 values.add(CodeTreeBuilder.singleString("null")); |
1042 } else { | 1046 } else { |
1043 values.add(createTypeSafeReference(frameLocal, method.getFrameParameter())); | 1047 values.add(createTypeSafeReference(frameLocal, method.getFrameParameter())); |
1044 } | 1048 } |
1045 } | 1049 } |
1046 for (int parameterIndex = 0; parameterIndex < method.getEvaluatedCount(); parameterIndex++) { | 1050 |
1047 TypeMirror targetParameter = method.getEvaluatedParameters().get(parameterIndex); | 1051 int evaluatedIndex = 0; |
1048 LocalVariable variable; | 1052 for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) { |
1049 if (executeWith != null && parameterIndex < executeWith.size()) { | 1053 NodeExecutionData parameterExecution; |
1050 variable = currentValues.getValue(executeWith.get(parameterIndex)); | 1054 if (executeWith != null && executionIndex < executeWith.size()) { |
1055 parameterExecution = executeWith.get(executionIndex); | |
1051 } else { | 1056 } else { |
1052 variable = currentValues.getValue(parameterIndex); | 1057 parameterExecution = node.getChildExecutions().get(executionIndex); |
1053 } | 1058 } |
1054 values.add(createTypeSafeReference(variable, targetParameter)); | 1059 if (parameterExecution.isShortCircuit()) { |
1055 } | 1060 if (evaluatedIndex < method.getEvaluatedCount()) { |
1056 | 1061 TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex); |
1062 LocalVariable shortCircuit = currentValues.getShortCircuit(parameterExecution); | |
1063 if (shortCircuit != null) { | |
1064 values.add(createTypeSafeReference(shortCircuit, targetType)); | |
1065 } else { | |
1066 values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build()); | |
1067 } | |
1068 evaluatedIndex++; | |
1069 } | |
1070 } | |
1071 if (evaluatedIndex < method.getEvaluatedCount()) { | |
1072 TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex); | |
1073 LocalVariable value = currentValues.getValue(parameterExecution); | |
1074 if (value != null) { | |
1075 values.add(createTypeSafeReference(value, targetType)); | |
1076 } else { | |
1077 values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build()); | |
1078 } | |
1079 evaluatedIndex++; | |
1080 } | |
1081 } | |
1057 return values.toArray(new CodeTree[values.size()]); | 1082 return values.toArray(new CodeTree[values.size()]); |
1058 } | 1083 } |
1059 | 1084 |
1060 private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) { | 1085 private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) { |
1061 CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null; | 1086 CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null; |
1516 return content; | 1541 return content; |
1517 } | 1542 } |
1518 } | 1543 } |
1519 | 1544 |
1520 private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) { | 1545 private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) { |
1521 expectedTypes.add(forType); | 1546 if (sourceType == null || ElementUtils.needsCastTo(sourceType, forType)) { |
1522 return TypeSystemCodeGenerator.expect(typeSystem, sourceType, forType, tree); | 1547 expectedTypes.add(forType); |
1548 return TypeSystemCodeGenerator.expect(typeSystem, forType, tree); | |
1549 } | |
1550 return tree; | |
1523 } | 1551 } |
1524 | 1552 |
1525 private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) { | 1553 private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) { |
1526 if (execution.getChild() == null) { | 1554 if (execution.getChild() == null) { |
1527 return Collections.emptySet(); | 1555 return Collections.emptySet(); |
1552 } | 1580 } |
1553 return false; | 1581 return false; |
1554 } | 1582 } |
1555 | 1583 |
1556 private Element createFastPathExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, List<ExecutableTypeData> allTypes) { | 1584 private Element createFastPathExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, List<ExecutableTypeData> allTypes) { |
1557 LocalContext currentLocals = LocalContext.load(this, executedType.getEvaluatedCount(), varArgsThreshold); | 1585 LocalContext currentLocals = LocalContext.load(this, executedType, Integer.MAX_VALUE); |
1558 CodeExecutableElement executable = createExecuteMethod(specialization, executedType, currentLocals, false); | 1586 CodeExecutableElement executable = createExecuteMethod(specialization, executedType, currentLocals, false, Integer.MAX_VALUE); |
1559 CodeTreeBuilder builder = executable.createBuilder(); | 1587 CodeTreeBuilder builder = executable.createBuilder(); |
1560 if (specialization == null) { | 1588 if (specialization == null) { |
1561 if (executedType.getDelegatedTo() == null) { | 1589 if (executedType.getDelegatedTo() == null) { |
1562 executable.getModifiers().add(ABSTRACT); | 1590 executable.getModifiers().add(ABSTRACT); |
1563 } | 1591 } |
1567 builder.tree(createFastPath(builder, specialization, executedType, allTypes, currentLocals)); | 1595 builder.tree(createFastPath(builder, specialization, executedType, allTypes, currentLocals)); |
1568 | 1596 |
1569 return executable; | 1597 return executable; |
1570 } | 1598 } |
1571 | 1599 |
1572 private CodeExecutableElement createExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, LocalContext currentLocals, boolean originalOverride) { | 1600 private static final String VARARGS_NAME = "args"; |
1601 | |
1602 private CodeExecutableElement createExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, LocalContext currentLocals, boolean originalOverride, int varArgs) { | |
1573 TypeMirror returnType = executedType.getReturnType(); | 1603 TypeMirror returnType = executedType.getReturnType(); |
1574 TypeMirror frame = executedType.getFrameParameter(); | |
1575 List<TypeMirror> evaluatedParameters = executedType.getEvaluatedParameters(); | |
1576 | 1604 |
1577 if (specialization != null) { | 1605 if (specialization != null) { |
1578 currentLocals.loadFastPathState(specialization); | 1606 currentLocals.loadFastPathState(specialization); |
1579 } | 1607 } |
1580 | 1608 |
1581 if (frame == null) { | |
1582 currentLocals.removeValue(FRAME_VALUE); | |
1583 } else { | |
1584 currentLocals.set(FRAME_VALUE, currentLocals.get(FRAME_VALUE).newType(frame)); | |
1585 } | |
1586 | |
1587 for (int i = 0; i < Math.min(node.getChildExecutions().size(), evaluatedParameters.size()); i++) { | |
1588 NodeExecutionData execution = node.getChildExecutions().get(i); | |
1589 currentLocals.setValue(execution, currentLocals.getValue(execution).newType(evaluatedParameters.get(i))); | |
1590 } | |
1591 | |
1592 String methodName; | 1609 String methodName; |
1593 if (originalOverride) { | 1610 if (originalOverride && executedType.getMethod() != null) { |
1594 methodName = executedType.getMethod().getSimpleName().toString(); | 1611 methodName = executedType.getMethod().getSimpleName().toString(); |
1595 } else { | 1612 } else { |
1596 methodName = executedType.getUniqueName(); | 1613 methodName = executedType.getUniqueName(); |
1597 } | 1614 } |
1598 | 1615 |
1606 } | 1623 } |
1607 if (executedType.getFrameParameter() != null) { | 1624 if (executedType.getFrameParameter() != null) { |
1608 ((CodeVariableElement) executable.getParameters().get(0)).setName(FRAME_VALUE); | 1625 ((CodeVariableElement) executable.getParameters().get(0)).setName(FRAME_VALUE); |
1609 } | 1626 } |
1610 | 1627 |
1611 final String varArgsName = "args"; | |
1612 if (executable.isVarArgs()) { | 1628 if (executable.isVarArgs()) { |
1613 ((CodeVariableElement) executable.getParameters().get(executable.getParameters().size() - 1)).setName(varArgsName); | 1629 ((CodeVariableElement) executable.getParameters().get(executable.getParameters().size() - 1)).setName(VARARGS_NAME); |
1614 } | 1630 } |
1615 | 1631 |
1616 // rename varargs parameter | 1632 renameOriginalParameters(executedType, executable, currentLocals); |
1617 int signatureIndex = 0; | 1633 } else { |
1618 for (TypeMirror parameter : executedType.getEvaluatedParameters()) { | 1634 executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, varArgs, FRAME_VALUE); |
1619 LocalVariable var = currentLocals.getValue(signatureIndex); | |
1620 if (var != null) { | |
1621 int varArgsIndex = executedType.getVarArgsIndex(executedType.getParameterIndex(signatureIndex)); | |
1622 if (varArgsIndex >= 0) { | |
1623 var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + varArgsIndex + "]")); | |
1624 } else { | |
1625 ((CodeVariableElement) executable.getParameters().get(executedType.getParameterIndex(signatureIndex))).setName(var.getName()); | |
1626 } | |
1627 if (!isObject(parameter)) { | |
1628 var = var.newType(parameter); | |
1629 } | |
1630 currentLocals.setValue(node.getChildExecutions().get(signatureIndex), var); | |
1631 } | |
1632 | |
1633 signatureIndex++; | |
1634 } | |
1635 } else { | |
1636 executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, FRAME_VALUE); | |
1637 } | 1635 } |
1638 executable.getThrownTypes().clear(); | 1636 executable.getThrownTypes().clear(); |
1639 | 1637 |
1640 if (needsUnexpectedResultException(executedType)) { | 1638 if (needsUnexpectedResultException(executedType)) { |
1641 executable.getThrownTypes().add(context.getDeclaredType(UnexpectedResultException.class)); | 1639 executable.getThrownTypes().add(context.getDeclaredType(UnexpectedResultException.class)); |
1642 } | 1640 } |
1643 | 1641 |
1644 return executable; | 1642 return executable; |
1643 } | |
1644 | |
1645 private void renameOriginalParameters(ExecutableTypeData executedType, CodeExecutableElement executable, LocalContext currentLocals) { | |
1646 // rename varargs parameter | |
1647 int evaluatedIndex = 0; | |
1648 for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) { | |
1649 NodeExecutionData execution = node.getChildExecutions().get(executionIndex); | |
1650 if (execution.isShortCircuit()) { | |
1651 if (evaluatedIndex < executedType.getEvaluatedCount()) { | |
1652 TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex); | |
1653 LocalVariable shortCircuit = currentLocals.getShortCircuit(execution); | |
1654 if (shortCircuit != null) { | |
1655 currentLocals.setShortCircuitValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, shortCircuit)); | |
1656 } | |
1657 evaluatedIndex++; | |
1658 } | |
1659 } | |
1660 if (evaluatedIndex < executedType.getEvaluatedCount()) { | |
1661 TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex); | |
1662 LocalVariable value = currentLocals.getValue(execution); | |
1663 if (value != null) { | |
1664 currentLocals.setValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, value)); | |
1665 } | |
1666 evaluatedIndex++; | |
1667 } | |
1668 } | |
1669 } | |
1670 | |
1671 private static LocalVariable renameExecutableTypeParameter(CodeExecutableElement method, ExecutableTypeData executedType, int evaluatedIndex, TypeMirror targetType, LocalVariable var) { | |
1672 int parameterIndex = executedType.getParameterIndex(evaluatedIndex); | |
1673 int varArgsIndex = executedType.getVarArgsIndex(parameterIndex); | |
1674 LocalVariable returnVar = var; | |
1675 if (varArgsIndex >= 0) { | |
1676 returnVar = returnVar.accessWith(CodeTreeBuilder.singleString(VARARGS_NAME + "[" + varArgsIndex + "]")); | |
1677 } else { | |
1678 ((CodeVariableElement) method.getParameters().get(parameterIndex)).setName(returnVar.getName()); | |
1679 } | |
1680 if (!isObject(targetType)) { | |
1681 returnVar = returnVar.newType(targetType); | |
1682 } | |
1683 return returnVar; | |
1645 } | 1684 } |
1646 | 1685 |
1647 private boolean needsUnexpectedResultException(ExecutableTypeData executedType) { | 1686 private boolean needsUnexpectedResultException(ExecutableTypeData executedType) { |
1648 if (!executedType.hasUnexpectedValue(context)) { | 1687 if (!executedType.hasUnexpectedValue(context)) { |
1649 return false; | 1688 return false; |
1668 | 1707 |
1669 if (delegate == null) { | 1708 if (delegate == null) { |
1670 delegate = findFastPathDelegate((specialization != null ? specialization.getReturnType().getType() : genericType), executableType, allTypes); | 1709 delegate = findFastPathDelegate((specialization != null ? specialization.getReturnType().getType() : genericType), executableType, allTypes); |
1671 } | 1710 } |
1672 | 1711 |
1712 int delegateSignatureCount = delegate != null ? delegate.getSignatureParameters().size() : 0; | |
1673 for (NodeExecutionData execution : node.getChildExecutions()) { | 1713 for (NodeExecutionData execution : node.getChildExecutions()) { |
1674 if (specialization == null && delegate != null && execution.getIndex() >= delegate.getEvaluatedCount()) { | 1714 if (specialization == null && delegate != null && execution.getIndex() >= delegateSignatureCount) { |
1675 // we just evaluate children for the next delegate | 1715 // we just evaluate children for the next delegate |
1676 continue; | 1716 continue; |
1677 } else if (specialization != null && delegate != null) { | 1717 } else if (specialization != null && delegate != null) { |
1678 // skip if already delegated | 1718 // skip if already delegated |
1679 break; | 1719 break; |
1792 } | 1832 } |
1793 } | 1833 } |
1794 | 1834 |
1795 private LocalVariable resolveShortCircuit(SpecializationData specialization, NodeExecutionData execution, LocalContext currentLocals) { | 1835 private LocalVariable resolveShortCircuit(SpecializationData specialization, NodeExecutionData execution, LocalContext currentLocals) { |
1796 LocalVariable shortCircuit = null; | 1836 LocalVariable shortCircuit = null; |
1797 SpecializationData resolvedSpecialization = specialization; | |
1798 if (specialization == null) { | |
1799 resolvedSpecialization = node.getGenericSpecialization(); | |
1800 } | |
1801 | |
1802 if (execution.isShortCircuit()) { | 1837 if (execution.isShortCircuit()) { |
1803 ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution)); | 1838 shortCircuit = currentLocals.getShortCircuit(execution); |
1804 CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals); | 1839 |
1805 shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access); | 1840 if (shortCircuit == null) { |
1841 SpecializationData resolvedSpecialization = specialization; | |
1842 if (specialization == null) { | |
1843 resolvedSpecialization = node.getGenericSpecialization(); | |
1844 } | |
1845 ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution)); | |
1846 CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals); | |
1847 shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access); | |
1848 } else { | |
1849 CodeTree access = shortCircuit.createReference(); | |
1850 shortCircuit = shortCircuit.nextName().accessWith(access); | |
1851 } | |
1806 } | 1852 } |
1807 return shortCircuit; | 1853 return shortCircuit; |
1808 } | 1854 } |
1809 | 1855 |
1810 private int calculateShortCircuitIndex(NodeExecutionData execution) { | 1856 private int calculateShortCircuitIndex(NodeExecutionData execution) { |
2014 } | 2060 } |
2015 return false; | 2061 return false; |
2016 } | 2062 } |
2017 | 2063 |
2018 private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) { | 2064 private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) { |
2019 LocalContext locals = LocalContext.load(this, 0, varArgsThreshold); | 2065 if (!usedExecuteChildMethods.contains(execution)) { |
2020 | 2066 return null; |
2021 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), FRAME_VALUE); | 2067 } |
2068 | |
2069 LocalContext locals = LocalContext.load(this, createSpecializationNodeSignature(0), Integer.MAX_VALUE); | |
2070 | |
2071 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), Integer.MAX_VALUE, FRAME_VALUE); | |
2022 if (hasChildUnexpectedResult(execution, targetType)) { | 2072 if (hasChildUnexpectedResult(execution, targetType)) { |
2023 method.getThrownTypes().add(getType(UnexpectedResultException.class)); | 2073 method.getThrownTypes().add(getType(UnexpectedResultException.class)); |
2024 } | 2074 } |
2025 | 2075 |
2026 CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetType); | 2076 CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetType); |
2045 return method; | 2095 return method; |
2046 } | 2096 } |
2047 | 2097 |
2048 private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) { | 2098 private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) { |
2049 if (typeSystem.hasImplicitSourceTypes(targetType)) { | 2099 if (typeSystem.hasImplicitSourceTypes(targetType)) { |
2100 if (typeEquals(node.getGenericType(execution), targetType)) { | |
2101 return null; | |
2102 } | |
2103 | |
2050 switch (options.implicitCastOptimization()) { | 2104 switch (options.implicitCastOptimization()) { |
2051 case NONE: | 2105 case NONE: |
2052 return null; | 2106 return null; |
2053 case DUPLICATE_TAIL: | 2107 case DUPLICATE_TAIL: |
2054 return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution)); | 2108 return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution)); |
2183 | 2237 |
2184 private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) { | 2238 private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) { |
2185 if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) { | 2239 if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) { |
2186 throw new AssertionError("Execute child not shared with method but called."); | 2240 throw new AssertionError("Execute child not shared with method but called."); |
2187 } | 2241 } |
2242 usedExecuteChildMethods.add(execution); | |
2188 | 2243 |
2189 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | 2244 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); |
2190 builder.tree(targetValue.createReference()).string(" = "); | 2245 builder.tree(targetValue.createReference()).string(" = "); |
2191 builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror())); | 2246 builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror())); |
2192 if (currentValues.get(FRAME_VALUE) == null) { | 2247 if (currentValues.get(FRAME_VALUE) == null) { |
2592 TypeMirror type = assumption.getExpression().getResolvedType(); | 2647 TypeMirror type = assumption.getExpression().getResolvedType(); |
2593 set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null)); | 2648 set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null)); |
2594 } | 2649 } |
2595 } | 2650 } |
2596 | 2651 |
2597 public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, String... optionalArguments) { | 2652 public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, int varArgsThreshold, String... optionalArguments) { |
2598 CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name); | 2653 CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name); |
2599 addParametersTo(method, optionalArguments); | 2654 addParametersTo(method, varArgsThreshold, optionalArguments); |
2600 return method; | 2655 return method; |
2601 } | 2656 } |
2602 | 2657 |
2603 public static LocalContext load(NodeGenFactory factory, int signatureSize, int varargsThreshold) { | 2658 public static LocalContext load(NodeGenFactory factory, ExecutableTypeData type, int varargsThreshold) { |
2604 LocalContext context = new LocalContext(factory); | 2659 LocalContext context = new LocalContext(factory); |
2605 context.loadValues(signatureSize, varargsThreshold); | 2660 context.loadEvaluatedValues(type, varargsThreshold); |
2606 return context; | 2661 return context; |
2607 } | 2662 } |
2608 | 2663 |
2664 private void loadEvaluatedValues(ExecutableTypeData executedType, int varargsThreshold) { | |
2665 TypeMirror frame = executedType.getFrameParameter(); | |
2666 if (frame == null) { | |
2667 removeValue(FRAME_VALUE); | |
2668 } else { | |
2669 set(FRAME_VALUE, new LocalVariable(frame, FRAME_VALUE, null, null)); | |
2670 } | |
2671 for (NodeFieldData field : factory.node.getFields()) { | |
2672 String fieldName = fieldValueName(field); | |
2673 values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null)); | |
2674 } | |
2675 boolean varargs = needsVarargs(false, varargsThreshold); | |
2676 List<TypeMirror> evaluatedParameter = executedType.getEvaluatedParameters(); | |
2677 int evaluatedIndex = 0; | |
2678 for (int executionIndex = 0; executionIndex < factory.node.getExecutionCount(); executionIndex++) { | |
2679 NodeExecutionData execution = factory.node.getChildExecutions().get(executionIndex); | |
2680 if (execution.isShortCircuit()) { | |
2681 if (evaluatedIndex < executedType.getEvaluatedCount()) { | |
2682 TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex); | |
2683 LocalVariable shortCircuit = createShortCircuitValue(execution).newType(evaluatedType); | |
2684 if (varargs) { | |
2685 shortCircuit = shortCircuit.accessWith(createReadVarargs(evaluatedIndex)); | |
2686 } | |
2687 values.put(shortCircuit.getName(), shortCircuit.makeOriginal()); | |
2688 evaluatedIndex++; | |
2689 } | |
2690 } | |
2691 if (evaluatedIndex < executedType.getEvaluatedCount()) { | |
2692 TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex); | |
2693 LocalVariable value = createValue(execution, evaluatedType); | |
2694 if (varargs) { | |
2695 value = value.accessWith(createReadVarargs(evaluatedIndex)); | |
2696 } | |
2697 values.put(value.getName(), value.makeOriginal()); | |
2698 evaluatedIndex++; | |
2699 } | |
2700 } | |
2701 } | |
2702 | |
2609 public static LocalContext load(NodeGenFactory factory) { | 2703 public static LocalContext load(NodeGenFactory factory) { |
2610 return load(factory, factory.node.getSignatureSize(), factory.varArgsThreshold); | 2704 return load(factory, factory.createSpecializationNodeSignature(factory.node.getSignatureSize()), factory.varArgsThreshold); |
2611 } | 2705 } |
2612 | 2706 |
2613 public LocalContext copy() { | 2707 public LocalContext copy() { |
2614 LocalContext copy = new LocalContext(factory); | 2708 LocalContext copy = new LocalContext(factory); |
2615 copy.values.putAll(values); | 2709 copy.values.putAll(values); |
2697 } else { | 2791 } else { |
2698 size++; | 2792 size++; |
2699 } | 2793 } |
2700 } | 2794 } |
2701 return size >= varArgsThreshold; | 2795 return size >= varArgsThreshold; |
2702 } | |
2703 | |
2704 private void loadValues(int evaluatedArguments, int varargsThreshold) { | |
2705 values.put(FRAME_VALUE, new LocalVariable(factory.getType(Frame.class), FRAME_VALUE, null, null)); | |
2706 | |
2707 for (NodeFieldData field : factory.node.getFields()) { | |
2708 String fieldName = fieldValueName(field); | |
2709 values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null)); | |
2710 } | |
2711 | |
2712 boolean varargs = needsVarargs(false, varargsThreshold); | |
2713 for (int i = 0; i < evaluatedArguments; i++) { | |
2714 List<NodeExecutionData> childExecutions = factory.node.getChildExecutions(); | |
2715 if (i >= childExecutions.size()) { | |
2716 break; | |
2717 } | |
2718 NodeExecutionData execution = childExecutions.get(i); | |
2719 if (execution.isShortCircuit()) { | |
2720 LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(factory.context); | |
2721 if (varargs) { | |
2722 shortCircuit = shortCircuit.accessWith(createReadVarargs(i)); | |
2723 } | |
2724 values.put(shortCircuit.getName(), shortCircuit.makeOriginal()); | |
2725 } | |
2726 LocalVariable value = createValue(execution, factory.genericType); | |
2727 if (varargs) { | |
2728 value = value.accessWith(createReadVarargs(i)); | |
2729 } | |
2730 values.put(value.getName(), value.makeOriginal()); | |
2731 } | |
2732 } | 2796 } |
2733 | 2797 |
2734 private static CodeTree createReadVarargs(int i) { | 2798 private static CodeTree createReadVarargs(int i) { |
2735 return CodeTreeBuilder.createBuilder().string("args_[").string(String.valueOf(i)).string("]").build(); | 2799 return CodeTreeBuilder.createBuilder().string("args_[").string(String.valueOf(i)).string("]").build(); |
2736 } | 2800 } |
2764 builder.end(); | 2828 builder.end(); |
2765 } | 2829 } |
2766 } | 2830 } |
2767 } | 2831 } |
2768 | 2832 |
2769 public void addParametersTo(CodeExecutableElement method, String... optionalNames) { | 2833 public void addParametersTo(CodeExecutableElement method, int varArgsThreshold, String... optionalNames) { |
2770 for (String var : optionalNames) { | 2834 for (String var : optionalNames) { |
2771 LocalVariable local = values.get(var); | 2835 LocalVariable local = values.get(var); |
2772 if (local != null) { | 2836 if (local != null) { |
2773 method.addParameter(local.createParameter()); | 2837 method.addParameter(local.createParameter()); |
2774 } | 2838 } |
2775 } | 2839 } |
2776 if (needsVarargs(true, factory.varArgsThreshold)) { | 2840 if (needsVarargs(true, varArgsThreshold)) { |
2777 method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_")); | 2841 method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_")); |
2778 method.setVarArgs(true); | 2842 method.setVarArgs(true); |
2779 } else { | 2843 } else { |
2780 for (NodeExecutionData execution : factory.node.getChildExecutions()) { | 2844 for (NodeExecutionData execution : factory.node.getChildExecutions()) { |
2781 if (execution.isShortCircuit()) { | 2845 if (execution.isShortCircuit()) { |