changeset 18805:121748e43a01

Truffle-DSL: fix execute methods with evaluated arguments were not handled correctly with varargs arguments.
author Christian Humer <christian.humer@gmail.com>
date Fri, 09 Jan 2015 16:02:55 +0100
parents 07b61dff860f
children b9cf6f3150ea
files graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java
diffstat 2 files changed, 86 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Fri Jan 09 16:01:11 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Fri Jan 09 16:02:55 2015 +0100
@@ -61,6 +61,7 @@
     private final TypeData genericType;
     private final DSLOptions options;
     private final boolean singleSpecializable;
+    private final int varArgsThreshold;
 
     public NodeGenFactory(ProcessorContext context, NodeData node) {
         this.context = context;
@@ -69,6 +70,21 @@
         this.genericType = typeSystem.getGenericTypeData();
         this.options = typeSystem.getOptions();
         this.singleSpecializable = isSingleSpecializableImpl();
+        this.varArgsThreshold = calculateVarArgsThresHold();
+
+    }
+
+    private int calculateVarArgsThresHold() {
+        TypeMirror specialization = context.getType(SpecializationNode.class);
+        TypeElement specializationType = fromTypeMirror(specialization);
+
+        int maxParameters = 0;
+        for (ExecutableElement element : ElementFilter.methodsIn(specializationType.getEnclosedElements())) {
+            if (element.getSimpleName().contentEquals("acceptAndExecute")) {
+                maxParameters = Math.max(maxParameters, element.getParameters().size());
+            }
+        }
+        return maxParameters;
     }
 
     public static String nodeTypeName(NodeData node) {
@@ -760,16 +776,22 @@
         final TypeData executedType = execType.getEvaluatedCount() > 0 ? null : returnType;
 
         CodeExecutableElement method = cloneExecutableTypeOverride(execType, varArgsName);
-        LocalContext locals = LocalContext.load(this, execType.getSignatureSize());
+        LocalContext locals = LocalContext.load(this, execType.getSignatureSize(), Integer.MAX_VALUE);
 
         // rename varargs parameter
         int signatureIndex = 0;
         for (Parameter parameter : execType.getSignatureParameters()) {
-            if (parameter.isTypeVarArgs()) {
-                String newName = varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]";
-                NodeExecutionData execution = node.getChildExecutions().get(signatureIndex);
-                locals.setValue(execution, locals.getValue(execution).accessWith(CodeTreeBuilder.singleString(newName)));
+            LocalVariable var = locals.get(parameter, signatureIndex);
+            if (var != null) {
+                if (parameter.isTypeVarArgs()) {
+                    var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]"));
+                }
+                if (!parameter.getTypeSystemType().isGeneric()) {
+                    var = var.newType(parameter.getTypeSystemType());
+                }
+                locals.setValue(node.getChildExecutions().get(signatureIndex), var);
             }
+
             signatureIndex++;
         }
 
@@ -1276,7 +1298,7 @@
 
     private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) {
         TypeData type = forType == null ? genericType : forType;
-        LocalContext currentLocals = LocalContext.load(this, evaluatedArguments);
+        LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold);
 
         CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE);
         executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
@@ -1534,7 +1556,7 @@
     }
 
     private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) {
-        LocalContext locals = LocalContext.load(this, 0);
+        LocalContext locals = LocalContext.load(this, 0, varArgsThreshold);
 
         CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType.getPrimitiveType(), executeChildMethodName(execution, targetType), FRAME_VALUE);
         if (hasUnexpectedResult(execution, targetType)) {
@@ -1891,9 +1913,7 @@
         }
 
         LocalVariable genericValue = target.makeGeneric().nextName();
-        LocalVariable genericShortCircuit = resolveShortCircuit(null, execution, currentValues);
-
-        builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, genericShortCircuit, currentValues));
+        builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, null, currentValues));
         if (executableTypes.size() == sourceTypes.size()) {
             builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end();
         } else {
@@ -2026,14 +2046,14 @@
             return method;
         }
 
-        public static LocalContext load(NodeGenFactory factory, int signatureSize) {
+        public static LocalContext load(NodeGenFactory factory, int signatureSize, int varargsThreshold) {
             LocalContext context = new LocalContext(factory);
-            context.loadValues(signatureSize);
+            context.loadValues(signatureSize, varargsThreshold);
             return context;
         }
 
         public static LocalContext load(NodeGenFactory factory) {
-            return load(factory, factory.node.getSignatureSize());
+            return load(factory, factory.node.getSignatureSize(), factory.varArgsThreshold);
         }
 
         public LocalContext copy() {
@@ -2075,8 +2095,11 @@
             LocalVariable var = get(parameter.getLocalName());
             if (var == null && parameter.getSpecification().isSignature()) {
                 // lookup by signature index for executeWith
-                NodeExecutionData execution = factory.node.getChildExecutions().get(signatureIndex);
-                var = getValue(execution);
+                List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
+                if (signatureIndex < childExecutions.size() && signatureIndex >= 0) {
+                    NodeExecutionData execution = childExecutions.get(signatureIndex);
+                    var = getValue(execution);
+                }
             }
             return var;
         }
@@ -2104,7 +2127,7 @@
             values.put(shortCircuitName(execution), var);
         }
 
-        private boolean needsVarargs(boolean requireLoaded) {
+        private boolean needsVarargs(boolean requireLoaded, int varArgsThreshold) {
             int size = 0;
             for (NodeExecutionData execution : factory.node.getChildExecutions()) {
                 if (requireLoaded && getValue(execution) == null) {
@@ -2116,10 +2139,10 @@
                     size++;
                 }
             }
-            return size > 4;
+            return size >= varArgsThreshold;
         }
 
-        private void loadValues(int evaluatedArguments) {
+        private void loadValues(int evaluatedArguments, int varargsThreshold) {
             values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null));
 
             for (NodeFieldData field : factory.node.getFields()) {
@@ -2127,9 +2150,13 @@
                 values.put(fieldName, new LocalVariable(null, field.getType(), fieldName, factory.accessParent(field.getName())));
             }
 
-            boolean varargs = needsVarargs(false);
+            boolean varargs = needsVarargs(false, varargsThreshold);
             for (int i = 0; i < evaluatedArguments; i++) {
-                NodeExecutionData execution = factory.node.getChildExecutions().get(i);
+                List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
+                if (i >= childExecutions.size()) {
+                    break;
+                }
+                NodeExecutionData execution = childExecutions.get(i);
                 if (execution.isShortCircuit()) {
                     LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric();
                     if (varargs) {
@@ -2187,7 +2214,7 @@
                     method.addParameter(local.createParameter());
                 }
             }
-            if (needsVarargs(true)) {
+            if (needsVarargs(true, factory.varArgsThreshold)) {
                 method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_"));
                 method.setVarArgs(true);
             } else {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Fri Jan 09 16:01:11 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Fri Jan 09 16:02:55 2015 +0100
@@ -1079,4 +1079,42 @@
         return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement());
     }
 
+    public static ExecutableElement findMethod(TypeElement type, Set<Modifier> includeModifiers, Set<Modifier> excludeModifiers, String methodName, List<TypeMirror> types) {
+        outer: for (ExecutableElement executable : ElementFilter.methodsIn(type.getEnclosedElements())) {
+            if (includeModifiers != null) {
+                if (!executable.getModifiers().containsAll(includeModifiers)) {
+                    continue;
+                }
+            }
+            if (excludeModifiers != null) {
+                if (executable.getModifiers().containsAll(excludeModifiers)) {
+                    continue;
+                }
+            }
+            if (!executable.getSimpleName().toString().equals(methodName)) {
+                continue;
+            }
+            if (types.size() != executable.getParameters().size()) {
+                continue;
+            }
+            for (int i = 0; i < types.size(); i++) {
+                TypeMirror var1 = types.get(i);
+                VariableElement var2 = executable.getParameters().get(i);
+                if (ElementUtils.typeEquals(var1, var2.asType())) {
+                    continue outer;
+                }
+            }
+            return executable;
+        }
+        return null;
+    }
+
+    public static List<TypeMirror> asTypes(List<? extends Element> elements) {
+        List<TypeMirror> types = new ArrayList<>(elements.size());
+        for (Element element : elements) {
+            types.add(element.asType());
+        }
+        return types;
+    }
+
 }