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());