Mercurial > hg > graal-jvmci-8
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java @ 13527:25ecb47a6d0e
Truffle-DSL: Added support for references to child arrays in @ShortCircuit;
Introduced new layer NodeExecutionData to the implementation model which is in between NodeChildData and the actual parameters..
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 07 Jan 2014 12:22:47 +0100 |
parents | 2b9fcffd6f36 |
children | 5a0c694ef735 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Thu Dec 26 12:37:28 2013 -0800 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Jan 07 12:22:47 2014 +0100 @@ -34,9 +34,8 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; +import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature; import com.oracle.truffle.dsl.processor.typesystem.*; public class NodeParser extends TemplateParser<NodeData> { @@ -205,7 +204,6 @@ finalizeSpecializations(elements, splittedNode); verifyNode(splittedNode, elements); - expandExecutableTypeVarArgs(splittedNode); createPolymorphicSpecializations(splittedNode); assignShortCircuitsToSpecializations(splittedNode); } @@ -218,26 +216,6 @@ 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.<SpecializationData> emptyList()); @@ -277,7 +255,7 @@ } SpecializationData specialization = new SpecializationData(generic, false, false, true); - specialization.updateSignature(new Signature(polymorphicSignature)); + specialization.updateSignature(new TypeSignature(polymorphicSignature)); specialization.setNode(node); node.setGenericPolymorphicSpecialization(specialization); // TODO remove polymoprhic specializations @@ -336,6 +314,7 @@ nodeData.setTypeSystem(typeSystem); nodeData.setFields(parseFields(typeHierarchy, elements)); nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy)); + nodeData.setChildExecutions(parseDefaultSignature(nodeData, elements)); nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); // resolveChildren invokes cyclic parsing. @@ -345,6 +324,90 @@ return nodeData; } + private List<NodeExecutionData> parseDefaultSignature(NodeData node, List<? extends Element> elements) { + if (node.getChildren() == null) { + return null; + } + + // pre-parse short circuits + Set<String> shortCircuits = new HashSet<>(); + List<ExecutableElement> methods = ElementFilter.methodsIn(elements); + for (ExecutableElement method : methods) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); + if (mirror != null) { + shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); + } + } + + boolean hasVarArgs = false; + int maxSignatureSize = 0; + if (!node.getChildren().isEmpty()) { + int lastIndex = node.getChildren().size() - 1; + hasVarArgs = node.getChildren().get(lastIndex).getCardinality() == Cardinality.MANY; + if (hasVarArgs) { + maxSignatureSize = lastIndex; + } else { + maxSignatureSize = node.getChildren().size(); + } + } + + // pre-parse specializations + for (ExecutableElement method : methods) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class); + if (mirror == null) { + continue; + } + + int currentArgumentCount = 0; + boolean skipShortCircuit = false; + for (VariableElement var : method.getParameters()) { + TypeMirror type = var.asType(); + if (currentArgumentCount == 0) { + // skip optionals + if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) { + continue; + } + // TODO skip optional fields? + } + int childIndex = currentArgumentCount < node.getChildren().size() ? currentArgumentCount : node.getChildren().size() - 1; + if (childIndex == -1) { + continue; + } + if (!skipShortCircuit) { + NodeChildData child = node.getChildren().get(childIndex); + if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) { + skipShortCircuit = true; + continue; + } + } else { + skipShortCircuit = false; + } + + currentArgumentCount++; + } + maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); + } + + List<NodeExecutionData> executions = new ArrayList<>(); + for (int i = 0; i < maxSignatureSize; i++) { + int childIndex = i; + boolean varArg = false; + if (childIndex >= node.getChildren().size() - 1) { + if (hasVarArgs) { + childIndex = node.getChildren().size() - 1; + varArg = hasVarArgs; + } else if (childIndex >= node.getChildren().size()) { + break; + } + } + int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; + NodeChildData child = node.getChildren().get(childIndex); + boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex)); + executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); + } + return executions; + } + private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) { Set<String> names = new HashSet<>(); @@ -470,12 +533,7 @@ Element getter = findGetter(elements, name, childType); - ExecutionKind kind = ExecutionKind.DEFAULT; - if (shortCircuits.contains(name)) { - kind = ExecutionKind.SHORT_CIRCUIT; - } - - NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality, kind); + NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality); parsedChildren.add(nodeChild); @@ -727,62 +785,64 @@ } private SpecializationData createGenericSpecialization(final NodeData node, List<SpecializationData> specializations) { - SpecializationData genericSpecialization; SpecializationData specialization = specializations.get(0); GenericParser parser = new GenericParser(context, node); MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); + specification.getImplicitRequiredTypes().clear(); - List<ActualParameter> parameters = new ArrayList<>(); - for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - parameters.add(new ActualParameter(parameter)); - continue; + List<TypeMirror> parameterTypes = new ArrayList<>(); + int signatureIndex = 1; + for (ParameterSpec spec : specification.getRequired()) { + parameterTypes.add(createGenericType(spec, specializations, signatureIndex)); + if (spec.isSignature()) { + signatureIndex++; } - NodeData childNode = node; - NodeChildData child = node.findChild(parameter.getSpecification().getName()); - if (child != null) { - childNode = child.getNodeData(); + } + TypeMirror returnType = createGenericType(specification.getReturnType(), specializations, 0); + return parser.create("Generic", null, null, returnType, parameterTypes); + } + + private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) { + NodeExecutionData execution = spec.getExecution(); + if (execution == null) { + if (spec.getAllowedTypes().size() == 1) { + return spec.getAllowedTypes().get(0); + } else { + return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0])); + } + } else { + Set<TypeData> types = new HashSet<>(); + for (SpecializationData specialization : specializations) { + types.add(specialization.getTypeSignature().get(signatureIndex)); } - TypeData genericType = null; + NodeChildData child = execution.getChild(); - Set<TypeData> types = new HashSet<>(); - for (SpecializationData otherSpecialization : specializations) { - ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName()); - if (otherParameter != null) { - types.add(otherParameter.getTypeSystemType()); + TypeData genericType = null; + if (types.size() == 1) { + ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next()); + if (executable != null && !executable.hasUnexpectedValue(context)) { + genericType = types.iterator().next(); } } - - assert !types.isEmpty(); - - if (types.size() == 1) { - ExecutableTypeData executable = childNode.findExecutableType(types.iterator().next(), 0); - if (executable != null && !executable.hasUnexpectedValue(context)) { - genericType = types.iterator().next(); - } else { - genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); - } - } else { - genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); + if (genericType == null) { + genericType = child.findAnyGenericExecutableType(context).getType(); } - - parameters.add(new ActualParameter(parameter, genericType)); + return genericType.getPrimitiveType(); } - ActualParameter returnType = parameters.get(0); - parameters = parameters.subList(1, parameters.size()); - - TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); - genericSpecialization = new SpecializationData(genericMethod, true, false, false); - return genericSpecialization; } private void assignShortCircuitsToSpecializations(NodeData node) { Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); boolean valid = true; - for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) { - String valueName = field.getName(); + List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>(); + for (NodeExecutionData execution : node.getChildExecutions()) { + if (!execution.isShortCircuit()) { + continue; + } + shortCircuitExecutions.add(execution); + String valueName = execution.getShortCircuitId(); List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName); if (availableCircuits == null || availableCircuits.isEmpty()) { @@ -809,7 +869,7 @@ ShortCircuitData genericCircuit = null; for (ShortCircuitData circuit : availableCircuits) { - if (isGenericShortCutMethod(node, circuit)) { + if (isGenericShortCutMethod(circuit)) { genericCircuit = circuit; break; } @@ -832,16 +892,15 @@ return; } - NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); List<SpecializationData> specializations = new ArrayList<>(); specializations.addAll(node.getSpecializations()); specializations.addAll(node.getPolymorphicSpecializations()); for (SpecializationData specialization : specializations) { - List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length); + List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size()); - for (int i = 0; i < fields.length; i++) { - List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName()); + for (NodeExecutionData shortCircuit : shortCircuitExecutions) { + List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId()); ShortCircuitData genericShortCircuit = null; ShortCircuitData compatibleShortCircuit = null; @@ -897,7 +956,7 @@ List<String> paramIds = new LinkedList<>(); paramIds.add(Utils.getTypeId(other.getReturnType().getType())); for (ActualParameter param : other.getParameters()) { - if (other.getNode().findChild(param.getSpecification().getName()) == null) { + if (param.getSpecification().getExecution() == null) { continue; } paramIds.add(Utils.getTypeId(param.getType())); @@ -1230,14 +1289,14 @@ return null; } - private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { + private boolean isGenericShortCutMethod(ShortCircuitData method) { for (ActualParameter parameter : method.getParameters()) { - NodeChildData field = node.findChild(parameter.getSpecification().getName()); - if (field == null) { + NodeExecutionData execution = parameter.getSpecification().getExecution(); + if (execution == null) { continue; } ExecutableTypeData found = null; - List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context); + List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context); for (ExecutableTypeData executable : executableElements) { if (executable.getType().equalsType(parameter.getTypeSystemType())) { found = executable;