Mercurial > hg > graal-jvmci-8
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()) { |