Mercurial > hg > graal-jvmci-8
diff graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 9279:2a4b57f02fb4
Implemented basic support for assumptions for sourcecode generation.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Wed, 24 Apr 2013 17:44:15 +0200 |
parents | fe5bc02fcd19 |
children | e16363e50252 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Tue Apr 23 21:03:47 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Wed Apr 24 17:44:15 2013 +0200 @@ -289,11 +289,11 @@ } private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, - CodeTree guardedStatements, CodeTree elseStatements) { + CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions) { NodeData node = targetSpecialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); - CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization); + CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions); CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); Set<String> valuesNeedsCast; @@ -392,10 +392,26 @@ return builder.getRoot(); } - private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean emitAssumptions) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); // Implict guards based on method signature String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + + if (emitAssumptions) { + boolean isStatic = parent.findMethod().getModifiers().contains(STATIC); + + for (String assumption : guardedSpecialization.getAssumptions()) { + builder.string(andOperator); + if (isStatic) { + builder.string(THIS_NODE_LOCAL_VAR_NAME); + } else { + builder.string("this"); + } + builder.string(".").string(assumption).string(".isValid()"); + andOperator = " && "; + } + } + for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); if (field == null) { @@ -528,6 +544,19 @@ return constructors; } + private static ExecutableElement findCopyConstructor(TypeMirror type) { + for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + return constructor; + } + } + + return null; + } + private static boolean isCopyConstructor(ExecutableElement element) { if (element.getParameters().size() != 1) { return false; @@ -578,6 +607,10 @@ } } + for (String assumption : node.getAssumptions()) { + clazz.add(createAssumptionField(assumption)); + } + createConstructors(node, clazz); if (node.getExtensionElements() != null) { @@ -588,93 +621,88 @@ } private void createConstructors(NodeData node, CodeTypeElement clazz) { - List<ExecutableElement> signatureConstructors = new ArrayList<>(); - ExecutableElement copyConstructor = null; - List<? extends ExecutableElement> constructors = ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements()); - for (ExecutableElement constructor : constructors) { - if (constructor.getModifiers().contains(Modifier.PRIVATE) || constructor.getParameters().isEmpty()) { - continue; + List<ExecutableElement> constructors = findUserConstructors(node.getNodeType()); + if (constructors.isEmpty()) { + clazz.add(createUserConstructor(clazz, null)); + } else { + for (ExecutableElement constructor : constructors) { + clazz.add(createUserConstructor(clazz, constructor)); } + } + clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()))); + } - if (isCopyConstructor(constructor)) { - assert copyConstructor == null; - copyConstructor = createConstructor(clazz, constructor, true); - } else { - signatureConstructors.add(createConstructor(clazz, constructor, false)); + private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + + if (superConstructor != null) { + for (VariableElement param : superConstructor.getParameters()) { + method.getParameters().add(CodeVariableElement.clone(param)); } } - if (copyConstructor == null && node.needsRewrites(getContext())) { - clazz.add(createConstructor(clazz, null, true)); - } else if (copyConstructor != null) { - clazz.add(copyConstructor); - } - - if (signatureConstructors.isEmpty() && !node.getChildren().isEmpty()) { - clazz.add(createConstructor(clazz, null, false)); - } else { - clazz.getEnclosedElements().addAll(signatureConstructors); - } - } - - private CodeExecutableElement createConstructor(CodeTypeElement type, ExecutableElement superConstructor, boolean copyConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - if (!copyConstructor) { - if (superConstructor != null) { - for (VariableElement param : superConstructor.getParameters()) { - method.getParameters().add(CodeVariableElement.clone(param)); - } - } - for (NodeChildData child : getModel().getChildren()) { - method.getParameters().add(new CodeVariableElement(child.getNodeType(), child.getName())); - } - } else { - if (!(superConstructor == null && getModel().getChildren().isEmpty())) { - method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); - } + for (VariableElement var : type.getFields()) { + method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); } if (superConstructor != null) { - builder.startStatement(); - builder.startSuperCall(); - if (copyConstructor) { - builder.string("copy"); - } else { - for (VariableElement param : superConstructor.getParameters()) { - builder.string(param.getSimpleName().toString()); - } + builder.startStatement().startSuperCall(); + for (VariableElement param : superConstructor.getParameters()) { + builder.string(param.getSimpleName().toString()); } - builder.end(); - builder.end(); + builder.end().end(); } - for (NodeChildData child : getModel().getChildren()) { - + for (VariableElement var : type.getFields()) { builder.startStatement(); - builder.string("this.").string(child.getName()).string(" = "); - - if (child.getCardinality() == Cardinality.MANY) { - builder.startCall("adoptChildren"); + String varName = var.getSimpleName().toString(); + builder.string("this.").string(varName); + if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { + builder.string(" = adoptChild(").string(varName).string(")"); + } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { + builder.string(" = adoptChildren(").string(varName).string(")"); } else { - builder.startCall("adoptChild"); + builder.string(" = ").string(varName); } + builder.end(); + } + return method; + } - builder.startGroup(); - if (copyConstructor) { - builder.string("copy."); - } - builder.string(child.getName()); - builder.end(); - - builder.end(); - builder.end(); - + private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + if (!(superConstructor == null && type.getFields().isEmpty())) { + method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); } + if (superConstructor != null) { + builder.startStatement().startSuperCall().string("copy").end().end(); + } + + for (VariableElement var : type.getFields()) { + builder.startStatement(); + String varName = var.getSimpleName().toString(); + builder.string("this.").string(varName); + if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { + builder.string(" = adoptChild(copy.").string(varName).string(")"); + } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { + builder.string(" = adoptChildren(copy.").string(varName).string(")"); + } else { + builder.string(" = copy.").string(varName); + } + builder.end(); + } return method; } + private CodeVariableElement createAssumptionField(String assumption) { + CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption); + var.getModifiers().add(Modifier.FINAL); + return var; + } + private CodeVariableElement createChildField(NodeChildData child) { CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName()); var.getModifiers().add(Modifier.PROTECTED); @@ -728,11 +756,8 @@ createFactoryMethods(node, clazz, createVisibility); - if (node.getSpecializations().size() > 1) { + if (node.needsRewrites(context)) { clazz.add(createCreateSpecializedMethod(node, createVisibility)); - } - - if (node.needsRewrites(context)) { clazz.add(createSpecializeMethod(node)); } @@ -912,7 +937,7 @@ private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node) { CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeSpecialized"); - CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), "thisNode"); + CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME); CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types"); method.addParameter(nodeParam); method.addParameter(arguments); @@ -928,7 +953,9 @@ builder.startBlock(); builder.startReturn().startCall("createSpecialized"); - builder.string("thisNode"); + builder.startGroup(); + builder.string(THIS_NODE_LOCAL_VAR_NAME); + builder.end(); builder.string("types[0]"); builder.end().end(); @@ -1085,10 +1112,16 @@ CodeTreeBuilder body = method.createBuilder(); - body.startStatement(); - body.type(generatedNode.asType()).string(" ").string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); - body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME); - body.end(); + boolean hasCopyConstructor = findCopyConstructor(generatedNode.asType()) != null; + + final String thisLocalVariableName = THIS_NODE_LOCAL_VAR_NAME + "Cast"; + + if (hasCopyConstructor) { + body.startStatement(); + body.type(generatedNode.asType()).string(" ").string(thisLocalVariableName); + body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME); + body.end(); + } boolean first = true; for (TypeData type : node.getTypeSystem().getTypes()) { @@ -1101,16 +1134,12 @@ body.startElseIf(); } body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); - body.startReturn().startNew(nodeSpecializationClassName(specialization)); - body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); - body.end().end(); // new, return + body.tree(createReturnNewSpecialization(body, specialization, thisLocalVariableName, hasCopyConstructor)); body.end(); // if } } - body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization())); - body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); - body.end().end(); + body.tree(createReturnNewSpecialization(body, node.getGenericSpecialization(), thisLocalVariableName, hasCopyConstructor)); return method; } @@ -1123,22 +1152,31 @@ CodeTreeBuilder body = method.createBuilder(); body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); + boolean hasCopyConstructor = findCopyConstructor(generatedNode.asType()) != null; + for (int i = 1; i < node.getSpecializations().size(); i++) { SpecializationData specialization = node.getSpecializations().get(i); body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(specialization)).string(".class)").end(); - CodeTreeBuilder guarded = new CodeTreeBuilder(body); - guarded.startReturn().startNew(nodeSpecializationClassName(specialization)); - guarded.string(THIS_NODE_LOCAL_VAR_NAME); - guarded.end().end(); + CodeTree guarded = createReturnNewSpecialization(body, specialization, THIS_NODE_LOCAL_VAR_NAME, hasCopyConstructor); - body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded.getRoot(), null)); + body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded, null, true)); } body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); return method; } + private CodeTree createReturnNewSpecialization(CodeTreeBuilder parent, SpecializationData specialization, String thisLocalVariableName, boolean hasCopyConstructor) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startReturn().startNew(nodeSpecializationClassName(specialization)); + if (hasCopyConstructor) { + builder.string(thisLocalVariableName); + } + builder.end().end(); + return builder.getRoot(); + } + private List<CodeExecutableElement> createGeneratedGenericMethod(NodeData node) { TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); if (node.needsRewrites(context)) { @@ -1155,7 +1193,7 @@ } else { String methodName = generatedGenericMethodName(current); CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName); - method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); + method.addParameter(new CodeVariableElement(generatedNode.asType(), THIS_NODE_LOCAL_VAR_NAME)); addInternalValueParameters(method, node.getGenericSpecialization(), true); emitGeneratedGenericSpecialization(method.createBuilder(), current, next); @@ -1168,7 +1206,7 @@ return methods; } else { CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null)); - method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); + method.addParameter(new CodeVariableElement(generatedNode.asType(), THIS_NODE_LOCAL_VAR_NAME)); addInternalValueParameters(method, node.getGenericSpecialization(), true); emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0); return Arrays.asList(method); @@ -1188,7 +1226,7 @@ addInternalValueParameterNames(nextBuilder, next, next, null, true, true); nextBuilder.end().end(); - invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); + invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot(), true); } builder.tree(invokeMethod); @@ -1274,7 +1312,7 @@ } } - if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) { + if (specialization.hasRewrite(getContext())) { buildSpecializeAndExecute(clazz, specialization); } } @@ -1469,7 +1507,7 @@ if (next != null) { returnSpecialized = createReturnSpecializeAndExecute(builder, executable, next, null); } - builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); + builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false)); return builder.getRoot(); } @@ -1507,10 +1545,16 @@ private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (!specialization.getExceptions().isEmpty()) { + if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) { builder.startTryBlock(); } + for (String assumption : specialization.getAssumptions()) { + builder.startStatement(); + builder.string("this.").string(assumption).string(".check()"); + builder.end(); + } + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { String genericMethodName = generatedGenericMethodName(null); @@ -1559,6 +1603,12 @@ } builder.end(); } + if (!specialization.getAssumptions().isEmpty()) { + builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); + builder.tree(createReturnSpecializeAndExecute(parent, executable, specialization.findNextSpecialization(), null)); + builder.end(); + } + return builder.getRoot(); }