# HG changeset patch # User Christian Humer # Date 1386670214 -3600 # Node ID 038f55aab194dd3a3025404b20fc88b92cbd3141 # Parent ce017d1e4234611b7f693f828b6b84edb11ac5f8# Parent d86dc1b84973a1b591275dca28fcd4c4b5bb3dfe Merge. diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Tue Dec 10 11:10:14 2013 +0100 @@ -26,8 +26,22 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.*; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedGenerationFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs0Factory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs1Factory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs2Factory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs3Factory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs4Factory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs5Factory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -126,4 +140,120 @@ } } + @Test + public void test0VarArgs1() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs0Factory.getInstance()); + Assert.assertEquals(42, root.getNode().execute1(null)); + } + + abstract static class TestEvaluatedVarArgs0 extends ChildrenNode { + + public abstract Object execute1(VirtualFrame frame, Object... value); + + @Specialization + int call() { + return 42; + } + } + + @Test + public void test1VarArgs1() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs1Factory.getInstance()); + Assert.assertEquals(42, root.getNode().execute1(null, 42)); + } + + @Test(expected = AssertionError.class) + public void test1VarArgs2() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance()); + Assert.assertEquals(-1, root.getNode().execute1(null)); + } + + abstract static class TestEvaluatedVarArgs1 extends ChildrenNode { + + public abstract Object execute1(VirtualFrame frame, Object... value); + + @Specialization + int call(int exp0) { + return exp0; + } + } + + @Test + public void test2VarArgs1() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance()); + Assert.assertEquals(42, root.getNode().execute1(null, 21, 21)); + } + + @Test(expected = AssertionError.class) + public void test2VarArgs2() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance()); + Assert.assertEquals(-1, root.getNode().execute1(null, 42)); + } + + @Test(expected = AssertionError.class) + public void test2VarArgs3() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance()); + Assert.assertEquals(-1, root.getNode().execute1(null)); + } + + abstract static class TestEvaluatedVarArgs2 extends ChildrenNode { + + public abstract Object execute1(VirtualFrame frame, Object... value); + + @Specialization + int call(int exp0, int exp1) { + return exp0 + exp1; + } + } + + @Test + public void test3VarArgs1() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs3Factory.getInstance()); + Assert.assertEquals(42, root.getNode().execute1(null, 42)); + } + + @NodeChild + abstract static class TestEvaluatedVarArgs3 extends ValueNode { + + public abstract Object execute1(VirtualFrame frame, Object... value); + + @Specialization + int call(int exp0) { + return exp0; + } + } + + @Test + public void test4VarArgs1() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs4Factory.getInstance()); + Assert.assertEquals(42, root.getNode().execute1(null, 21, 21)); + } + + @NodeChildren({@NodeChild, @NodeChild}) + abstract static class TestEvaluatedVarArgs4 extends ValueNode { + + public abstract Object execute1(VirtualFrame frame, Object... value); + + @Specialization + int call(int exp0, int exp1) { + return exp0 + exp1; + } + } + + @Test + public void test5VarArgs1() { + TestRootNode root = TestHelper.createRoot(TestEvaluatedVarArgs5Factory.getInstance()); + Assert.assertEquals(42, root.getNode().execute1(null)); + } + + abstract static class TestEvaluatedVarArgs5 extends ValueNode { + + public abstract Object execute1(VirtualFrame frame, Object... value); + + @Specialization + int call() { + return 42; + } + } + } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java Tue Dec 10 11:10:14 2013 +0100 @@ -113,6 +113,11 @@ return name; } + public CodeTreeBuilder getBuilder() { + CodeTree tree = this.bodyTree; + return createBuilder().tree(tree); + } + public CodeTreeBuilder createBuilder() { CodeTreeBuilder builder = new CodeTreeBuilder(null); this.bodyTree = builder.getTree(); diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java Tue Dec 10 11:10:14 2013 +0100 @@ -274,16 +274,28 @@ } } } else { + Element enclosing = f.getEnclosingElement(); writeModifiers(f.getModifiers()); - write(useImport(f, f.asType())); - if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { - ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); + boolean varArgs = false; + if (enclosing.getKind() == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) enclosing; if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) { - write("..."); + varArgs = true; } } + TypeMirror varType = f.asType(); + if (varArgs) { + if (varType.getKind() == TypeKind.ARRAY) { + varType = ((ArrayType) varType).getComponentType(); + } + write(useImport(f, varType)); + write("..."); + } else { + write(useImport(f, varType)); + } + write(" "); write(f.getSimpleName()); if (init != null) { diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Tue Dec 10 11:10:14 2013 +0100 @@ -39,6 +39,7 @@ super(context, node); setEmitErrors(false); setParseNullOnError(false); + setUseVarArgs(true); } @Override diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Dec 10 11:10:14 2013 +0100 @@ -478,6 +478,14 @@ return createCastType(typeSystem, sourceType, targetType, true, expression); } + public CodeTree createDeoptimize(CodeTreeBuilder parent) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement(); + builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); + builder.end(); + return builder.getRoot(); + } + private class NodeFactoryFactory extends ClassElementFactory { private final Map> childTypes; @@ -1015,7 +1023,7 @@ CodeTreeBuilder access = builder.create(); access.string("this.").string(child.getName()); if (child.getCardinality().isMany()) { - access.string("[").string(String.valueOf(param.getIndex())).string("]"); + access.string("[").string(String.valueOf(param.getSpecificationIndex())).string("]"); } String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName()); @@ -2102,7 +2110,7 @@ return null; } String prefix = expect ? "expect" : "execute"; - return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getIndex(); + return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getSpecificationIndex(); } private List createExecuteChilds(ActualParameter param, Set expectTypes) { @@ -2418,7 +2426,7 @@ throw new AssertionError(); } if (targetParameter.getSpecification().isIndexed()) { - builder.string("[" + targetParameter.getIndex() + "]"); + builder.string("[" + targetParameter.getSpecificationIndex() + "]"); } return builder.getRoot(); } @@ -2470,14 +2478,6 @@ return builder.getRoot(); } - protected CodeTree createDeoptimize(CodeTreeBuilder parent) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement(); - builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end(); - builder.end(); - return builder.getRoot(); - } - protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData current, ActualParameter exceptionParam, String reason) { NodeData node = current.getNode(); SpecializationData generic = node.getGenericSpecialization(); @@ -2729,7 +2729,7 @@ } CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true); clazz.add(executeMethod); - CodeTreeBuilder builder = executeMethod.createBuilder(); + CodeTreeBuilder builder = executeMethod.getBuilder(); CodeTree result = createExecuteBody(builder, specialization, execType); if (result != null) { builder.tree(result); @@ -2757,7 +2757,7 @@ ExecutableTypeData execType = parser.parse(Arrays.asList(executeCached)).get(0); CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); - CodeTreeBuilder builder = executeMethod.createBuilder(); + CodeTreeBuilder builder = executeMethod.getBuilder(); if (specialization.isGeneric() || specialization.isPolymorphic()) { builder.startThrow().startNew(getContext().getType(AssertionError.class)); @@ -2786,7 +2786,7 @@ NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); + builder.tree(createDeoptimize(builder)); builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this"); builder.declaration(getContext().getType(int.class), "depth", "0"); @@ -2851,15 +2851,46 @@ private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); + CodeTreeBuilder builder = method.createBuilder(); int i = 0; + int signatureIndex = -1; for (VariableElement param : method.getParameters()) { CodeVariableElement var = CodeVariableElement.clone(param); ActualParameter actualParameter = execType.getParameters().get(i); + if (actualParameter.getSpecification().isSignature()) { + signatureIndex++; + } + + String name; if (evaluated && actualParameter.getSpecification().isSignature()) { - var.setName(valueNameEvaluated(actualParameter)); + name = valueNameEvaluated(actualParameter); } else { - var.setName(valueName(actualParameter)); + name = valueName(actualParameter); } + + int varArgCount = getModel().getSignatureSize() - signatureIndex; + if (evaluated && actualParameter.isVarArgs()) { + ActualParameter baseVarArgs = actualParameter; + name = valueName(baseVarArgs) + "Args"; + + builder.startAssert().string(name).string(" != null").end(); + builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end(); + if (varArgCount > 0) { + List varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size()); + for (ActualParameter varArg : varArgsParameter) { + if (varArgCount <= 0) { + break; + } + TypeMirror type = baseVarArgs.getType(); + if (type.getKind() == TypeKind.ARRAY) { + type = ((ArrayType) type).getComponentType(); + } + builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getVarArgsIndex() + "]"); + varArgCount--; + } + } + } + var.setName(name); method.getParameters().set(i, var); i++; } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Tue Dec 10 11:10:14 2013 +0100 @@ -78,6 +78,13 @@ this.assumptions = splitSource.assumptions; } + public int getSignatureSize() { + if (getSpecializations() != null && !getSpecializations().isEmpty()) { + return getSpecializations().get(0).getSignatureSize(); + } + return 0; + } + public boolean needsFrame(ProcessorContext context) { for (SpecializationData specialization : specializations) { if (!specialization.isReachable()) { diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Dec 10 11:10:14 2013 +0100 @@ -205,6 +205,7 @@ finalizeSpecializations(elements, splittedNode); verifyNode(splittedNode, elements); + expandExecutableTypeVarArgs(splittedNode); createPolymorphicSpecializations(splittedNode); assignShortCircuitsToSpecializations(splittedNode); } @@ -217,6 +218,26 @@ return node; } + private static void expandExecutableTypeVarArgs(NodeData node) { + for (ExecutableTypeData executableMethod : node.getExecutableTypes()) { + if (!(executableMethod.getMethod().isVarArgs() && executableMethod.getSpecification().isVariableRequiredArguments())) { + continue; + } + int expandArguments = node.getSignatureSize() - executableMethod.getSignatureSize(); + if (expandArguments > 0) { + int signatureSize = executableMethod.getSignatureSize(); + ActualParameter parameter = executableMethod.getSignatureParameter(signatureSize - 1); + for (int i = 0; i < expandArguments; i++) { + int newVarArgsIndex = parameter.getVarArgsIndex() + i + 1; + int newSpecificationIndex = parameter.getSpecificationIndex() + i + 1; + executableMethod.getParameters().add( + new ActualParameter(parameter.getSpecification(), parameter.getTypeSystemType(), newSpecificationIndex, newVarArgsIndex, parameter.isImplicit())); + } + + } + } + } + private void createPolymorphicSpecializations(NodeData node) { if (!node.needsRewrites(context) || !node.isPolymorphic()) { node.setPolymorphicSpecializations(Collections. emptyList()); diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Dec 10 11:10:14 2013 +0100 @@ -261,7 +261,7 @@ if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) { ParameterSpec frameSpec = getSpecification().findParameterSpec("frame"); if (frameSpec != null) { - getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, false)); + getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, -1, false)); } } } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java Tue Dec 10 11:10:14 2013 +0100 @@ -33,49 +33,56 @@ private TypeData typeSystemType; private TemplateMethod method; private final String localName; - private final int index; + private final int specificationIndex; + private final int varArgsIndex; private final boolean implicit; private final TypeMirror type; - public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) { + public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationIndex, int varArgsIndex, boolean implicit) { this.specification = specification; this.type = actualType; this.typeSystemType = null; - this.index = index; + this.specificationIndex = specificationIndex; this.implicit = implicit; String valueName = specification.getName() + "Value"; if (specification.isIndexed()) { - valueName += index; + valueName += specificationIndex; } + this.varArgsIndex = varArgsIndex; this.localName = valueName; } - public ActualParameter(ParameterSpec specification, TypeData actualType, int index, boolean implicit) { - this(specification, actualType.getPrimitiveType(), index, implicit); + public ActualParameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex, boolean implicit) { + this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex, implicit); this.typeSystemType = actualType; } public ActualParameter(ActualParameter parameter, TypeData otherType) { - this(parameter.specification, otherType, parameter.index, parameter.implicit); + this(parameter.specification, otherType, parameter.specificationIndex, parameter.varArgsIndex, parameter.implicit); } public ActualParameter(ActualParameter parameter) { this.specification = parameter.specification; this.type = parameter.type; this.typeSystemType = parameter.typeSystemType; - this.index = parameter.index; + this.specificationIndex = parameter.specificationIndex; this.implicit = parameter.implicit; this.localName = parameter.localName; + this.varArgsIndex = parameter.varArgsIndex; + } + + public int getVarArgsIndex() { + return varArgsIndex; } public boolean isImplicit() { return implicit; } - public int getIndex() { - return index; + public int getSpecificationIndex() { + return specificationIndex; } public String getLocalName() { @@ -102,6 +109,10 @@ return typeSystemType; } + public boolean isVarArgs() { + return varArgsIndex >= 0; + } + public ActualParameter getPreviousParameter() { return method.getPreviousParam(this); } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java Tue Dec 10 11:10:14 2013 +0100 @@ -37,6 +37,7 @@ private final List optional = new ArrayList<>(); private final List required = new ArrayList<>(); + private int minimumRequiredArguments; private boolean variableRequiredArguments; private List typeDefinitions; @@ -44,6 +45,14 @@ this.returnType = returnType; } + public void setMinimumRequiredArguments(int minimumRequiredArguments) { + this.minimumRequiredArguments = minimumRequiredArguments; + } + + public int getMinimumRequiredArguments() { + return minimumRequiredArguments; + } + public void setVariableRequiredArguments(boolean variableArguments) { this.variableRequiredArguments = variableArguments; } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Dec 10 11:10:14 2013 +0100 @@ -202,6 +202,17 @@ return prev; } + public int getSignatureSize() { + int signatureSize = 0; + for (ActualParameter parameter : getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + signatureSize++; + } + return signatureSize; + } + public Signature getSignature() { Signature signature = new Signature(); for (ActualParameter parameter : getReturnTypeAndParameters()) { diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Tue Dec 10 11:10:14 2013 +0100 @@ -44,12 +44,21 @@ private boolean emitErrors = true; private boolean parseNullOnError = false; + private boolean useVarArgs = false; public TemplateMethodParser(ProcessorContext context, T template) { this.template = template; this.context = context; } + protected void setUseVarArgs(boolean useVarArgs) { + this.useVarArgs = useVarArgs; + } + + public boolean isUseVarArgs() { + return useVarArgs; + } + public boolean isEmitErrors() { return emitErrors; } @@ -140,7 +149,7 @@ ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); - ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); + ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, -1, false); if (returnTypeMirror == null) { if (emitErrors) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); @@ -161,7 +170,7 @@ parameterTypes.add(var.asType()); } - List parameters = parseParameters(methodSpecification, parameterTypes); + List parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method.isVarArgs()); if (parameters == null) { if (isEmitErrors()) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); @@ -201,7 +210,7 @@ * ones are cut and used to parse the optional parameters. All those remaining parameters must * be consumed otherwise its an error. */ - private List parseParameters(MethodSpec spec, List parameterTypes) { + private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { List implicitTypes = spec.getImplicitRequiredTypes(); int offset = -1; @@ -211,7 +220,7 @@ offset++; types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes)); types.data.addAll(parameterTypes.subList(offset, parameterTypes.size())); - parsedRequired = parseParametersRequired(spec, types); + parsedRequired = parseParametersRequired(spec, types, varArgs); } if (parsedRequired == null && offset >= 0) { @@ -244,7 +253,7 @@ int oldIndex = types.getIndex(); int optionalCount = 1; for (ParameterSpec paramspec : optionals) { - ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, false); + ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, -1, false); if (optionalParam != null) { optionals.consume(optionalCount); types.consume(); @@ -264,9 +273,10 @@ return parsedParams; } - private List parseParametersRequired(MethodSpec spec, ConsumableListIterator types) { + private List parseParametersRequired(MethodSpec spec, ConsumableListIterator types, boolean varArgs) { List parsedParams = new ArrayList<>(); + int varArgsParameterIndex = -1; int specificationParameterIndex = 0; ConsumableListIterator required = new ConsumableListIterator<>(spec.getRequired()); while (required.get() != null || types.get() != null) { @@ -278,8 +288,15 @@ } break; } + TypeMirror actualType = types.get(); + if (varArgs && types.isLast()) { + if (actualType.getKind() == TypeKind.ARRAY) { + actualType = ((ArrayType) actualType).getComponentType(); + } + varArgsParameterIndex++; + } boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); - ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); + ActualParameter resolvedParameter = matchParameter(required.get(), actualType, template, specificationParameterIndex, varArgsParameterIndex, implicit); if (resolvedParameter == null) { if (required.get().getCardinality() == Cardinality.MANY) { required.consume(); @@ -289,7 +306,16 @@ return null; } else { parsedParams.add(resolvedParameter); - types.consume(); + + if (varArgs && types.isLast()) { + /* Both varargs spec and varargs definition. Need to consume to terminate. */ + if (required.get().getCardinality() == Cardinality.MANY) { + types.consume(); + } + } else { + types.consume(); + } + if (required.get().getCardinality() == Cardinality.ONE) { required.consume(); specificationParameterIndex = 0; @@ -299,7 +325,7 @@ } } - if (!types.toList().isEmpty()) { + if (!types.toList().isEmpty() && !(varArgs && types.isLast())) { // additional types -> error return null; } @@ -311,7 +337,7 @@ return parsedParams; } - private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int index, boolean implicit) { + private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) { TypeMirror resolvedType = mirror; if (hasError(resolvedType)) { resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); @@ -323,9 +349,9 @@ TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); if (resolvedTypeData != null) { - return new ActualParameter(specification, resolvedTypeData, index, implicit); + return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex, implicit); } else { - return new ActualParameter(specification, resolvedType, index, implicit); + return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex, implicit); } } @@ -346,6 +372,10 @@ return data.get(index); } + public boolean isLast() { + return index == data.size() - 1; + } + public E consume() { return consume(1); } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Tue Dec 10 11:10:14 2013 +0100 @@ -93,9 +93,11 @@ } else { ActualParameter p; if (parameter.getTypeSystemType() != null) { - p = new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit()); + p = new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getSpecificationIndex(), + specializationParameter.getVarArgsIndex(), parameter.isImplicit()); } else { - p = new ActualParameter(specializationParameter.getSpecification(), parameter.getType(), specializationParameter.getIndex(), parameter.isImplicit()); + p = new ActualParameter(specializationParameter.getSpecification(), parameter.getType(), specializationParameter.getSpecificationIndex(), + specializationParameter.getVarArgsIndex(), parameter.isImplicit()); } newParameters.add(p); } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java Tue Dec 10 11:10:14 2013 +0100 @@ -221,7 +221,7 @@ } builder.startElseBlock(); - builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); + builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); builder.end(); return method; @@ -248,7 +248,7 @@ } builder.startElseBlock(); - builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); + builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); builder.end(); diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java Tue Dec 10 11:10:14 2013 +0100 @@ -59,10 +59,6 @@ this.parser = parser; } - public CallTarget findFunction(String name) { - return context.getFunctionRegistry().lookup(name); - } - public void startFunction() { frameDescriptor = new FrameDescriptor(); } diff -r d86dc1b84973 -r 038f55aab194 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java Mon Dec 09 18:13:58 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java Tue Dec 10 11:10:14 2013 +0100 @@ -140,22 +140,21 @@ } return new InlinableCallNode((DefaultCallTarget) function, clonedArgs); } + // got a call target that is not inlinable (should not occur for SL) + return new DispatchedCallNode(defaultFunction, clonedArgs); + } else { + throw new AssertionError(); } - // got a call target that is not inlinable (should not occur for SL) - return new DispatchedCallNode(function, clonedArgs); } } private static final class InlinableCallNode extends DispatchedCallNode implements InlinableCallSite { - private final DefaultCallTarget inlinableTarget; - @CompilationFinal private int callCount; InlinableCallNode(DefaultCallTarget function, ArgumentsNode arguments) { super(function, arguments); - this.inlinableTarget = function; } @Override @@ -170,7 +169,7 @@ @Override public Node getInlineTree() { - RootNode root = inlinableTarget.getRootNode(); + RootNode root = function.getRootNode(); if (root instanceof FunctionRootNode) { return ((FunctionRootNode) root).getUninitializedBody(); } @@ -182,7 +181,7 @@ CompilerAsserts.neverPartOfCompilation(); TypedNode functionCall = null; - RootNode root = inlinableTarget.getRootNode(); + RootNode root = function.getRootNode(); if (root instanceof FunctionRootNode) { functionCall = ((FunctionRootNode) root).inline(NodeUtil.cloneNode(args)); } @@ -204,7 +203,7 @@ @Override public CallTarget getCallTarget() { - return inlinableTarget; + return function; } } @@ -212,9 +211,9 @@ private static class DispatchedCallNode extends TypedNode { @Child protected ArgumentsNode args; - protected final CallTarget function; + protected final DefaultCallTarget function; - DispatchedCallNode(CallTarget function, ArgumentsNode arguments) { + DispatchedCallNode(DefaultCallTarget function, ArgumentsNode arguments) { this.args = adoptChild(arguments); this.function = function; }