Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 8595:8a1115c92271
Implemented codegen guard definitions can now omit unused parameters.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 01 Apr 2013 21:43:20 +0200 |
parents | a80bf36c6a1e |
children | e0ff5cf358a4 |
comparison
equal
deleted
inserted
replaced
8594:ce6e8672f798 | 8595:8a1115c92271 |
---|---|
115 builder.string(valueName(parameter)); | 115 builder.string(valueName(parameter)); |
116 } | 116 } |
117 } | 117 } |
118 } | 118 } |
119 | 119 |
120 private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod target, TemplateMethod sourceMethod, TemplateMethod castMethod, String unexpectedValueName) { | 120 private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { |
121 CodeTreeBuilder builder = parent.create(); | 121 CodeTreeBuilder builder = parent.create(); |
122 | 122 |
123 boolean castedValues = sourceMethod != castMethod; | 123 boolean castedValues = sourceMethod != targetMethod; |
124 | 124 |
125 builder.startGroup(); | 125 builder.startGroup(); |
126 ExecutableElement method = target.getMethod(); | 126 ExecutableElement method = targetMethod.getMethod(); |
127 if (method == null) { | 127 if (method == null) { |
128 throw new IllegalStateException("Cannot call synthtetic operation methods."); | 128 throw new IllegalStateException("Cannot call synthetic operation methods."); |
129 } | 129 } |
130 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); | 130 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); |
131 NodeData node = (NodeData) castMethod.getTemplate(); | 131 NodeData node = (NodeData) targetMethod.getTemplate(); |
132 TypeSystemData typeSystem = node.getTypeSystem(); | 132 TypeSystemData typeSystem = node.getTypeSystem(); |
133 | 133 |
134 boolean accessible = target.canBeAccessedByInstanceOf(node.getNodeType()); | 134 boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); |
135 if (accessible) { | 135 if (accessible) { |
136 if (builder.findMethod().getModifiers().contains(STATIC)) { | 136 if (builder.findMethod().getModifiers().contains(STATIC)) { |
137 builder.string(THIS_NODE_LOCAL_VAR_NAME); | 137 if (method.getModifiers().contains(STATIC)) { |
138 builder.type(targetClass.asType()); | |
139 } else { | |
140 builder.string(THIS_NODE_LOCAL_VAR_NAME); | |
141 } | |
138 } else { | 142 } else { |
139 builder.string("super"); | 143 builder.string("super"); |
140 } | 144 } |
141 } else { | 145 } else { |
142 if (method.getModifiers().contains(STATIC)) { | 146 if (method.getModifiers().contains(STATIC)) { |
143 builder.type(targetClass.asType()); | 147 builder.type(targetClass.asType()); |
144 } else { | 148 } else { |
145 ActualParameter parameter = null; | 149 ActualParameter parameter = null; |
146 for (ActualParameter searchParameter : target.getParameters()) { | 150 for (ActualParameter searchParameter : targetMethod.getParameters()) { |
147 if (!searchParameter.getSpecification().isOptional()) { | 151 if (searchParameter.getSpecification().isSignature()) { |
148 parameter = searchParameter; | 152 parameter = searchParameter; |
149 break; | 153 break; |
150 } | 154 } |
151 } | 155 } |
152 assert parameter != null; | 156 assert parameter != null; |
170 } | 174 } |
171 } | 175 } |
172 builder.string("."); | 176 builder.string("."); |
173 builder.startCall(method.getSimpleName().toString()); | 177 builder.startCall(method.getSimpleName().toString()); |
174 | 178 |
175 for (ActualParameter targetParameter : castMethod.getParameters()) { | 179 for (ActualParameter targetParameter : targetMethod.getParameters()) { |
176 ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); | 180 ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); |
177 if (valueParameter == null) { | 181 if (valueParameter == null) { |
178 continue; | 182 valueParameter = targetParameter; |
179 } | 183 } |
180 TypeData targetType = targetParameter.getActualTypeData(typeSystem); | 184 TypeData targetType = targetParameter.getActualTypeData(typeSystem); |
181 | 185 |
182 if (targetParameter.isImplicit() || valueParameter.isImplicit()) { | 186 if (targetParameter.isImplicit() || valueParameter.isImplicit()) { |
183 continue; | 187 continue; |
255 body.startGroup(); | 259 body.startGroup(); |
256 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); | 260 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); |
257 body.string(".").startCall(methodName); | 261 body.string(".").startCall(methodName); |
258 } | 262 } |
259 | 263 |
260 private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization, | 264 private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, |
261 CodeTree guardedStatements, CodeTree elseStatements) { | 265 CodeTree guardedStatements, CodeTree elseStatements) { |
262 | 266 |
267 NodeData node = targetSpecialization.getNode(); | |
263 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 268 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
264 CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization); | 269 CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization); |
265 CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization); | 270 CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); |
271 | |
272 Set<String> valuesNeedsCast; | |
273 if (castValues) { | |
274 // cast all | |
275 valuesNeedsCast = null; | |
276 } else { | |
277 // find out which values needs a cast | |
278 valuesNeedsCast = new HashSet<>(); | |
279 for (GuardData guard : targetSpecialization.getGuards()) { | |
280 for (ActualParameter parameter : guard.getParameters()) { | |
281 NodeFieldData field = node.findField(parameter.getSpecification().getName()); | |
282 if (field == null) { | |
283 continue; | |
284 } | |
285 TypeData typeData = parameter.getActualTypeData(node.getTypeSystem()); | |
286 if (typeData != null && !typeData.isGeneric()) { | |
287 valuesNeedsCast.add(parameter.getLocalName()); | |
288 } | |
289 } | |
290 } | |
291 } | |
266 | 292 |
267 int ifCount = 0; | 293 int ifCount = 0; |
268 | 294 |
269 if (implicitGuards != null) { | 295 if (implicitGuards != null) { |
270 builder.startIf(); | 296 builder.startIf(); |
272 builder.end(); | 298 builder.end(); |
273 builder.startBlock(); | 299 builder.startBlock(); |
274 ifCount++; | 300 ifCount++; |
275 } | 301 } |
276 | 302 |
277 if (explicitGuards != null || !onSpecialization) { | 303 builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization)); |
278 builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization)); | |
279 } | |
280 | 304 |
281 if (explicitGuards != null) { | 305 if (explicitGuards != null) { |
282 builder.startIf(); | 306 builder.startIf(); |
283 builder.tree(explicitGuards); | 307 builder.tree(explicitGuards); |
284 builder.end(); | 308 builder.end(); |
307 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; | 331 String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; |
308 if (guardedSpecialization.getGuards().size() > 0) { | 332 if (guardedSpecialization.getGuards().size() > 0) { |
309 // Explicitly specified guards | 333 // Explicitly specified guards |
310 for (GuardData guard : guardedSpecialization.getGuards()) { | 334 for (GuardData guard : guardedSpecialization.getGuards()) { |
311 builder.string(andOperator); | 335 builder.string(andOperator); |
312 builder.tree(createTemplateMethodCall(parent, guard, valueSpecialization, guardedSpecialization, null)); | 336 builder.tree(createTemplateMethodCall(parent, valueSpecialization, guard, null)); |
313 andOperator = " && "; | 337 andOperator = " && "; |
314 } | 338 } |
315 } | 339 } |
316 | 340 |
317 return builder.isEmpty() ? null : builder.getRoot(); | 341 return builder.isEmpty() ? null : builder.getRoot(); |
318 } | 342 } |
319 | 343 |
320 private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { | 344 private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { |
321 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 345 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
322 // Implict guards based on method signature | 346 // Implict guards based on method signature |
323 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { | 347 for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { |
324 NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); | 348 NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); |
325 if (field == null || field.getKind() == FieldKind.FIELD) { | 349 if (field == null || field.getKind() == FieldKind.FIELD) { |
326 continue; | 350 continue; |
327 } | 351 } |
328 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); | 352 ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); |
353 | |
354 if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { | |
355 continue; | |
356 } | |
329 | 357 |
330 CodeTree cast = createCast(parent, field, valueParam, guardedParam); | 358 CodeTree cast = createCast(parent, field, valueParam, guardedParam); |
331 if (cast == null) { | 359 if (cast == null) { |
332 continue; | 360 continue; |
333 } | 361 } |
941 | 969 |
942 private CodeExecutableElement createSpecializeMethod(NodeData node) { | 970 private CodeExecutableElement createSpecializeMethod(NodeData node) { |
943 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); | 971 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); |
944 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); | 972 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); |
945 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); | 973 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); |
946 addInternalValueParameters(method, node.getGenericSpecialization(), false); | 974 addInternalValueParameters(method, node.getGenericSpecialization(), true); |
947 | 975 |
948 CodeTreeBuilder body = method.createBuilder(); | 976 CodeTreeBuilder body = method.createBuilder(); |
949 body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); | 977 body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); |
950 | 978 |
951 for (int i = 1; i < node.getSpecializations().size(); i++) { | 979 for (int i = 1; i < node.getSpecializations().size(); i++) { |
955 CodeTreeBuilder guarded = new CodeTreeBuilder(body); | 983 CodeTreeBuilder guarded = new CodeTreeBuilder(body); |
956 guarded.startReturn().startNew(nodeSpecializationClassName(specialization)); | 984 guarded.startReturn().startNew(nodeSpecializationClassName(specialization)); |
957 guarded.string(THIS_NODE_LOCAL_VAR_NAME); | 985 guarded.string(THIS_NODE_LOCAL_VAR_NAME); |
958 guarded.end().end(); | 986 guarded.end().end(); |
959 | 987 |
960 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); | 988 body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded.getRoot(), null)); |
961 } | 989 } |
962 body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); | 990 body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); |
963 | 991 |
964 return method; | 992 return method; |
965 } | 993 } |
1011 nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); | 1039 nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); |
1012 nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); | 1040 nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); |
1013 addInternalValueParameterNames(nextBuilder, next, null, true, true); | 1041 addInternalValueParameterNames(nextBuilder, next, null, true, true); |
1014 nextBuilder.end().end(); | 1042 nextBuilder.end().end(); |
1015 | 1043 |
1016 invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, nextBuilder.getRoot()); | 1044 invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); |
1017 } | 1045 } |
1018 | 1046 |
1019 builder.tree(invokeMethod); | 1047 builder.tree(invokeMethod); |
1020 | 1048 |
1021 if (next != null) { | 1049 if (next != null) { |
1030 | 1058 |
1031 if (specialization.getMethod() == null) { | 1059 if (specialization.getMethod() == null) { |
1032 emitEncounteredSynthetic(builder); | 1060 emitEncounteredSynthetic(builder); |
1033 } else { | 1061 } else { |
1034 builder.startReturn(); | 1062 builder.startReturn(); |
1035 builder.tree(createTemplateMethodCall(builder, specialization, specialization.getNode().getGenericSpecialization(), specialization, null)); | 1063 builder.tree(createTemplateMethodCall(builder, specialization.getNode().getGenericSpecialization(), specialization, null)); |
1036 builder.end(); // return | 1064 builder.end(); // return |
1037 } | 1065 } |
1038 | 1066 |
1039 if (!specialization.getExceptions().isEmpty()) { | 1067 if (!specialization.getExceptions().isEmpty()) { |
1040 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 1068 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
1200 SpecializationData next = specialization.findNextSpecialization(); | 1228 SpecializationData next = specialization.findNextSpecialization(); |
1201 CodeTree returnSpecialized = null; | 1229 CodeTree returnSpecialized = null; |
1202 if (next != null) { | 1230 if (next != null) { |
1203 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); | 1231 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); |
1204 } | 1232 } |
1205 builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized)); | 1233 builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); |
1206 } | 1234 } |
1207 | 1235 |
1208 private CodeTree createDeoptimize(CodeTreeBuilder parent) { | 1236 private CodeTree createDeoptimize(CodeTreeBuilder parent) { |
1209 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1237 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1210 builder.startStatement(); | 1238 builder.startStatement(); |
1223 builder.startCall("replace"); | 1251 builder.startCall("replace"); |
1224 if (node.needsRewrites(getContext())) { | 1252 if (node.needsRewrites(getContext())) { |
1225 builder.startCall(factoryClassName(node), "specialize"); | 1253 builder.startCall(factoryClassName(node), "specialize"); |
1226 builder.string("this"); | 1254 builder.string("this"); |
1227 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); | 1255 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); |
1228 addInternalValueParameterNames(builder, specialization, null, false, true); | 1256 addInternalValueParameterNames(builder, specialization, null, true, true); |
1229 builder.end(); // call replace, call specialize | 1257 builder.end(); // call replace, call specialize |
1230 } else { | 1258 } else { |
1231 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); | 1259 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); |
1232 } | 1260 } |
1233 builder.end().end(); | 1261 builder.end().end(); |
1261 builder.string("this"); | 1289 builder.string("this"); |
1262 addInternalValueParameterNames(builder, specialization, null, true, true); | 1290 addInternalValueParameterNames(builder, specialization, null, true, true); |
1263 builder.end().end(); | 1291 builder.end().end(); |
1264 } else { | 1292 } else { |
1265 builder.startReturn(); | 1293 builder.startReturn(); |
1266 builder.tree(createTemplateMethodCall(builder, specialization, specialization, specialization, null)); | 1294 builder.tree(createTemplateMethodCall(builder, specialization, specialization, null)); |
1267 builder.end(); // return | 1295 builder.end(); // return |
1268 } | 1296 } |
1269 | 1297 |
1270 if (!specialization.getExceptions().isEmpty()) { | 1298 if (!specialization.getExceptions().isEmpty()) { |
1271 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 1299 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
1292 } | 1320 } |
1293 | 1321 |
1294 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { | 1322 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { |
1295 for (TemplateMethod listener : node.getSpecializationListeners()) { | 1323 for (TemplateMethod listener : node.getSpecializationListeners()) { |
1296 builder.startStatement(); | 1324 builder.startStatement(); |
1297 builder.tree(createTemplateMethodCall(builder, listener, listener, listener, null)); | 1325 builder.tree(createTemplateMethodCall(builder, listener, listener, null)); |
1298 builder.end(); // statement | 1326 builder.end(); // statement |
1299 } | 1327 } |
1300 } | 1328 } |
1301 | 1329 |
1302 private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { | 1330 private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { |
1388 } | 1416 } |
1389 | 1417 |
1390 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); | 1418 builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); |
1391 ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); | 1419 ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); |
1392 | 1420 |
1393 builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); | 1421 builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); |
1394 | 1422 |
1395 builder.end(); // statement | 1423 builder.end(); // statement |
1396 | 1424 |
1397 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); | 1425 builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); |
1398 builder.startIf().string(shortCircuitParam.getLocalName()).end(); | 1426 builder.startIf().string(shortCircuitParam.getLocalName()).end(); |
1441 emitSpecializationListeners(builder, specialization.getNode()); | 1469 emitSpecializationListeners(builder, specialization.getNode()); |
1442 | 1470 |
1443 builder.startStatement(); | 1471 builder.startStatement(); |
1444 builder.startCall("replace"); | 1472 builder.startCall("replace"); |
1445 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); | 1473 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); |
1446 addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true); | 1474 addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, true, true); |
1447 builder.end(); | 1475 builder.end(); |
1448 builder.end(); // call replace | 1476 builder.end(); // call replace |
1449 builder.end(); // statement | 1477 builder.end(); // statement |
1450 | 1478 |
1451 String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); | 1479 String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); |