comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 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 3db8ec140f3f
children ae81dd154fb6
comparison
equal deleted inserted replaced
18804:07b61dff860f 18805:121748e43a01
59 private final NodeData node; 59 private final NodeData node;
60 private final TypeSystemData typeSystem; 60 private final TypeSystemData typeSystem;
61 private final TypeData genericType; 61 private final TypeData genericType;
62 private final DSLOptions options; 62 private final DSLOptions options;
63 private final boolean singleSpecializable; 63 private final boolean singleSpecializable;
64 private final int varArgsThreshold;
64 65
65 public NodeGenFactory(ProcessorContext context, NodeData node) { 66 public NodeGenFactory(ProcessorContext context, NodeData node) {
66 this.context = context; 67 this.context = context;
67 this.node = node; 68 this.node = node;
68 this.typeSystem = node.getTypeSystem(); 69 this.typeSystem = node.getTypeSystem();
69 this.genericType = typeSystem.getGenericTypeData(); 70 this.genericType = typeSystem.getGenericTypeData();
70 this.options = typeSystem.getOptions(); 71 this.options = typeSystem.getOptions();
71 this.singleSpecializable = isSingleSpecializableImpl(); 72 this.singleSpecializable = isSingleSpecializableImpl();
73 this.varArgsThreshold = calculateVarArgsThresHold();
74
75 }
76
77 private int calculateVarArgsThresHold() {
78 TypeMirror specialization = context.getType(SpecializationNode.class);
79 TypeElement specializationType = fromTypeMirror(specialization);
80
81 int maxParameters = 0;
82 for (ExecutableElement element : ElementFilter.methodsIn(specializationType.getEnclosedElements())) {
83 if (element.getSimpleName().contentEquals("acceptAndExecute")) {
84 maxParameters = Math.max(maxParameters, element.getParameters().size());
85 }
86 }
87 return maxParameters;
72 } 88 }
73 89
74 public static String nodeTypeName(NodeData node) { 90 public static String nodeTypeName(NodeData node) {
75 return resolveNodeId(node) + "NodeGen"; 91 return resolveNodeId(node) + "NodeGen";
76 } 92 }
758 final String varArgsName = "args"; 774 final String varArgsName = "args";
759 final TypeData returnType = execType.getType(); 775 final TypeData returnType = execType.getType();
760 final TypeData executedType = execType.getEvaluatedCount() > 0 ? null : returnType; 776 final TypeData executedType = execType.getEvaluatedCount() > 0 ? null : returnType;
761 777
762 CodeExecutableElement method = cloneExecutableTypeOverride(execType, varArgsName); 778 CodeExecutableElement method = cloneExecutableTypeOverride(execType, varArgsName);
763 LocalContext locals = LocalContext.load(this, execType.getSignatureSize()); 779 LocalContext locals = LocalContext.load(this, execType.getSignatureSize(), Integer.MAX_VALUE);
764 780
765 // rename varargs parameter 781 // rename varargs parameter
766 int signatureIndex = 0; 782 int signatureIndex = 0;
767 for (Parameter parameter : execType.getSignatureParameters()) { 783 for (Parameter parameter : execType.getSignatureParameters()) {
768 if (parameter.isTypeVarArgs()) { 784 LocalVariable var = locals.get(parameter, signatureIndex);
769 String newName = varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]"; 785 if (var != null) {
770 NodeExecutionData execution = node.getChildExecutions().get(signatureIndex); 786 if (parameter.isTypeVarArgs()) {
771 locals.setValue(execution, locals.getValue(execution).accessWith(CodeTreeBuilder.singleString(newName))); 787 var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]"));
772 } 788 }
789 if (!parameter.getTypeSystemType().isGeneric()) {
790 var = var.newType(parameter.getTypeSystemType());
791 }
792 locals.setValue(node.getChildExecutions().get(signatureIndex), var);
793 }
794
773 signatureIndex++; 795 signatureIndex++;
774 } 796 }
775 797
776 Parameter frame = execType.getFrame(); 798 Parameter frame = execType.getFrame();
777 CodeTreeBuilder builder = method.createBuilder(); 799 CodeTreeBuilder builder = method.createBuilder();
1274 return false; 1296 return false;
1275 } 1297 }
1276 1298
1277 private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) { 1299 private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) {
1278 TypeData type = forType == null ? genericType : forType; 1300 TypeData type = forType == null ? genericType : forType;
1279 LocalContext currentLocals = LocalContext.load(this, evaluatedArguments); 1301 LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold);
1280 1302
1281 CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); 1303 CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE);
1282 executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); 1304 executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
1283 1305
1284 if (!type.isGeneric()) { 1306 if (!type.isGeneric()) {
1532 1554
1533 return false; 1555 return false;
1534 } 1556 }
1535 1557
1536 private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) { 1558 private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) {
1537 LocalContext locals = LocalContext.load(this, 0); 1559 LocalContext locals = LocalContext.load(this, 0, varArgsThreshold);
1538 1560
1539 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType.getPrimitiveType(), executeChildMethodName(execution, targetType), FRAME_VALUE); 1561 CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType.getPrimitiveType(), executeChildMethodName(execution, targetType), FRAME_VALUE);
1540 if (hasUnexpectedResult(execution, targetType)) { 1562 if (hasUnexpectedResult(execution, targetType)) {
1541 method.getThrownTypes().add(getType(UnexpectedResultException.class)); 1563 method.getThrownTypes().add(getType(UnexpectedResultException.class));
1542 } 1564 }
1889 if (!executableTypes.isEmpty()) { 1911 if (!executableTypes.isEmpty()) {
1890 builder.startElseBlock(); 1912 builder.startElseBlock();
1891 } 1913 }
1892 1914
1893 LocalVariable genericValue = target.makeGeneric().nextName(); 1915 LocalVariable genericValue = target.makeGeneric().nextName();
1894 LocalVariable genericShortCircuit = resolveShortCircuit(null, execution, currentValues); 1916 builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, null, currentValues));
1895
1896 builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, genericShortCircuit, currentValues));
1897 if (executableTypes.size() == sourceTypes.size()) { 1917 if (executableTypes.size() == sourceTypes.size()) {
1898 builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end(); 1918 builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end();
1899 } else { 1919 } else {
1900 builder.startStatement().tree(assignment); 1920 builder.startStatement().tree(assignment);
1901 builder.tree(TypeSystemCodeGenerator.implicitExpect(target.getType(), genericValue.createReference(), implicitClassFieldName)); 1921 builder.tree(TypeSystemCodeGenerator.implicitExpect(target.getType(), genericValue.createReference(), implicitClassFieldName));
2024 CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name); 2044 CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name);
2025 addParametersTo(method, optionalArguments); 2045 addParametersTo(method, optionalArguments);
2026 return method; 2046 return method;
2027 } 2047 }
2028 2048
2029 public static LocalContext load(NodeGenFactory factory, int signatureSize) { 2049 public static LocalContext load(NodeGenFactory factory, int signatureSize, int varargsThreshold) {
2030 LocalContext context = new LocalContext(factory); 2050 LocalContext context = new LocalContext(factory);
2031 context.loadValues(signatureSize); 2051 context.loadValues(signatureSize, varargsThreshold);
2032 return context; 2052 return context;
2033 } 2053 }
2034 2054
2035 public static LocalContext load(NodeGenFactory factory) { 2055 public static LocalContext load(NodeGenFactory factory) {
2036 return load(factory, factory.node.getSignatureSize()); 2056 return load(factory, factory.node.getSignatureSize(), factory.varArgsThreshold);
2037 } 2057 }
2038 2058
2039 public LocalContext copy() { 2059 public LocalContext copy() {
2040 LocalContext copy = new LocalContext(factory); 2060 LocalContext copy = new LocalContext(factory);
2041 copy.values.putAll(values); 2061 copy.values.putAll(values);
2073 2093
2074 public LocalVariable get(Parameter parameter, int signatureIndex) { 2094 public LocalVariable get(Parameter parameter, int signatureIndex) {
2075 LocalVariable var = get(parameter.getLocalName()); 2095 LocalVariable var = get(parameter.getLocalName());
2076 if (var == null && parameter.getSpecification().isSignature()) { 2096 if (var == null && parameter.getSpecification().isSignature()) {
2077 // lookup by signature index for executeWith 2097 // lookup by signature index for executeWith
2078 NodeExecutionData execution = factory.node.getChildExecutions().get(signatureIndex); 2098 List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
2079 var = getValue(execution); 2099 if (signatureIndex < childExecutions.size() && signatureIndex >= 0) {
2100 NodeExecutionData execution = childExecutions.get(signatureIndex);
2101 var = getValue(execution);
2102 }
2080 } 2103 }
2081 return var; 2104 return var;
2082 } 2105 }
2083 2106
2084 public LocalVariable getValue(NodeExecutionData execution) { 2107 public LocalVariable getValue(NodeExecutionData execution) {
2102 return; 2125 return;
2103 } 2126 }
2104 values.put(shortCircuitName(execution), var); 2127 values.put(shortCircuitName(execution), var);
2105 } 2128 }
2106 2129
2107 private boolean needsVarargs(boolean requireLoaded) { 2130 private boolean needsVarargs(boolean requireLoaded, int varArgsThreshold) {
2108 int size = 0; 2131 int size = 0;
2109 for (NodeExecutionData execution : factory.node.getChildExecutions()) { 2132 for (NodeExecutionData execution : factory.node.getChildExecutions()) {
2110 if (requireLoaded && getValue(execution) == null) { 2133 if (requireLoaded && getValue(execution) == null) {
2111 continue; 2134 continue;
2112 } 2135 }
2114 size += 2; 2137 size += 2;
2115 } else { 2138 } else {
2116 size++; 2139 size++;
2117 } 2140 }
2118 } 2141 }
2119 return size > 4; 2142 return size >= varArgsThreshold;
2120 } 2143 }
2121 2144
2122 private void loadValues(int evaluatedArguments) { 2145 private void loadValues(int evaluatedArguments, int varargsThreshold) {
2123 values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null)); 2146 values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null));
2124 2147
2125 for (NodeFieldData field : factory.node.getFields()) { 2148 for (NodeFieldData field : factory.node.getFields()) {
2126 String fieldName = fieldValueName(field); 2149 String fieldName = fieldValueName(field);
2127 values.put(fieldName, new LocalVariable(null, field.getType(), fieldName, factory.accessParent(field.getName()))); 2150 values.put(fieldName, new LocalVariable(null, field.getType(), fieldName, factory.accessParent(field.getName())));
2128 } 2151 }
2129 2152
2130 boolean varargs = needsVarargs(false); 2153 boolean varargs = needsVarargs(false, varargsThreshold);
2131 for (int i = 0; i < evaluatedArguments; i++) { 2154 for (int i = 0; i < evaluatedArguments; i++) {
2132 NodeExecutionData execution = factory.node.getChildExecutions().get(i); 2155 List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
2156 if (i >= childExecutions.size()) {
2157 break;
2158 }
2159 NodeExecutionData execution = childExecutions.get(i);
2133 if (execution.isShortCircuit()) { 2160 if (execution.isShortCircuit()) {
2134 LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(); 2161 LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric();
2135 if (varargs) { 2162 if (varargs) {
2136 shortCircuit = shortCircuit.accessWith(createReadVarargs(i)); 2163 shortCircuit = shortCircuit.accessWith(createReadVarargs(i));
2137 } 2164 }
2185 LocalVariable local = values.get(var); 2212 LocalVariable local = values.get(var);
2186 if (local != null) { 2213 if (local != null) {
2187 method.addParameter(local.createParameter()); 2214 method.addParameter(local.createParameter());
2188 } 2215 }
2189 } 2216 }
2190 if (needsVarargs(true)) { 2217 if (needsVarargs(true, factory.varArgsThreshold)) {
2191 method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_")); 2218 method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_"));
2192 method.setVarArgs(true); 2219 method.setVarArgs(true);
2193 } else { 2220 } else {
2194 for (NodeExecutionData execution : factory.node.getChildExecutions()) { 2221 for (NodeExecutionData execution : factory.node.getChildExecutions()) {
2195 if (execution.isShortCircuit()) { 2222 if (execution.isShortCircuit()) {