comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 7846:91cc98eae8ee

Refactor guard creation methods are not flexible enough to handle two if guards.
author Christian Humer <christian.humer@gmail.com>
date Tue, 19 Feb 2013 14:29:12 +0100
parents 0110e781b6fa
children 06a7cd6aaf00
comparison
equal deleted inserted replaced
7845:0110e781b6fa 7846:91cc98eae8ee
67 return name; 67 return name;
68 } 68 }
69 69
70 private static String specializationId(SpecializationData specialization) { 70 private static String specializationId(SpecializationData specialization) {
71 String name = ""; 71 String name = "";
72 if (specialization.getNode().getSpecializations().length > 1) { 72 NodeData node = specialization.getNode();
73 if (node.getSpecializations().length > 1) {
73 name = specialization.getMethodName(); 74 name = specialization.getMethodName();
74 if (name.startsWith("do")) { 75 if (name.startsWith("do")) {
75 name = name.substring(2); 76 name = name.substring(2);
76 } 77 }
77 } 78 }
190 body.startGroup(); 191 body.startGroup();
191 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); 192 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
192 body.string(".").startCall(methodName); 193 body.string(".").startCall(methodName);
193 } 194 }
194 195
195 private static String emitExplicitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, 196 private static CodeTree createGuardAndCast(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization,
197 boolean onSpecialization, CodeTree guardedStatements, CodeTree elseStatements) {
198
199 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
200 CodeTree implicitGuards = createImplicitGuards(context, parent, prefix, valueSpecialization, guardedSpecialization);
201 CodeTree explicitGuards = createExplicitGuards(context, parent, implicitGuards == null ? prefix : null, valueSpecialization, guardedSpecialization, onSpecialization);
202
203 int ifCount = 0;
204
205 if (implicitGuards != null) {
206 builder.startIf();
207 builder.tree(implicitGuards);
208 builder.end();
209 builder.startBlock();
210 ifCount++;
211 }
212
213 if (explicitGuards != null) {
214 builder.startIf();
215 builder.tree(explicitGuards);
216 builder.end();
217 builder.startBlock();
218 ifCount++;
219 }
220
221 if (implicitGuards == null && explicitGuards == null && prefix != null && !prefix.isEmpty()) {
222 builder.startIf().string(prefix).end().startBlock();
223 ifCount++;
224 }
225
226 builder.tree(guardedStatements);
227
228 builder.end(ifCount);
229 if (ifCount > 0 && elseStatements != null) {
230 builder.startElseBlock();
231 builder.tree(elseStatements);
232 builder.end();
233 }
234
235 return builder.getRoot();
236 }
237
238 private static CodeTree createExplicitGuards(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization,
196 boolean onSpecialization) { 239 boolean onSpecialization) {
197 String andOperator = prefix; 240 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
241 String andOperator = (prefix != null && !prefix.isEmpty()) ? (prefix + " && ") : "";
198 if (guardedSpecialization.getGuards().length > 0) { 242 if (guardedSpecialization.getGuards().length > 0) {
199 // Explicitly specified guards 243 // Explicitly specified guards
200 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { 244 for (SpecializationGuardData guard : guardedSpecialization.getGuards()) {
201 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { 245 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) {
202 body.string(andOperator); 246 builder.string(andOperator);
203 247
204 startCallOperationMethod(body, guard.getGuardDeclaration()); 248 startCallOperationMethod(builder, guard.getGuardDeclaration());
205 addValueParameterNamesWithCasts(context, body, valueSpecialization, guardedSpecialization); 249 addValueParameterNamesWithCasts(context, builder, valueSpecialization, guardedSpecialization);
206 250
207 body.end().end(); // call 251 builder.end().end(); // call
208 andOperator = " && "; 252 andOperator = " && ";
209 } 253 }
210 } 254 }
211 } 255 }
212 return andOperator; 256
213 } 257 return builder.isEmpty() ? null : builder.getRoot();
214 258 }
215 private static String emitImplicitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { 259
260 private static CodeTree createImplicitGuards(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
216 NodeData node = guardedSpecialization.getNode(); 261 NodeData node = guardedSpecialization.getNode();
217 TypeSystemData typeSystem = node.getTypeSystem(); 262 TypeSystemData typeSystem = node.getTypeSystem();
218 263
264 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
219 // Implict guards based on method signature 265 // Implict guards based on method signature
220 String andOperator = prefix; 266 String andOperator = (prefix != null && !prefix.isEmpty()) ? (prefix + " && ") : "";
221 for (NodeFieldData field : node.getFields()) { 267 for (NodeFieldData field : node.getFields()) {
222 ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); 268 ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName());
223 ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); 269 ActualParameter valueParam = valueSpecialization.findParameter(field.getName());
224 270
225 TypeData guardedType = guardedParam.getActualTypeData(typeSystem); 271 TypeData guardedType = guardedParam.getActualTypeData(typeSystem);
227 273
228 if (guardedType.equalsType(valueType) || guardedType.isGeneric()) { 274 if (guardedType.equalsType(valueType) || guardedType.isGeneric()) {
229 continue; 275 continue;
230 } 276 }
231 277
232 body.string(andOperator); 278 builder.string(andOperator);
233 279
234 body.startGroup(); 280 builder.startGroup();
235 281
236 if (field.isShortCircuit()) { 282 if (field.isShortCircuit()) {
237 ActualParameter shortCircuit = guardedSpecialization.getPreviousParam(guardedParam); 283 ActualParameter shortCircuit = guardedSpecialization.getPreviousParam(guardedParam);
238 body.string("("); 284 builder.string("(");
239 body.string("!").string(valueName(guardedSpecialization, shortCircuit)); 285 builder.string("!").string(valueName(guardedSpecialization, shortCircuit));
240 body.string(" || "); 286 builder.string(" || ");
241 } 287 }
242 288
243 startCallTypeSystemMethod(context, body, guardedSpecialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(guardedType)); 289 startCallTypeSystemMethod(context, builder, guardedSpecialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(guardedType));
244 body.string(valueName(guardedSpecialization, guardedParam)); 290 builder.string(valueName(guardedSpecialization, guardedParam));
245 body.end().end(); // call 291 builder.end().end(); // call
246 292
247 if (field.isShortCircuit()) { 293 if (field.isShortCircuit()) {
248 body.string(")"); 294 builder.string(")");
249 } 295 }
250 296
251 body.end(); // group 297 builder.end(); // group
252 andOperator = " && "; 298 andOperator = " && ";
253 } 299 }
254 return andOperator; 300
301 return builder.isEmpty() ? null : builder.getRoot();
255 } 302 }
256 303
257 @Override 304 @Override
258 protected void createChildren(NodeData node) { 305 protected void createChildren(NodeData node) {
259 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); 306 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
466 513
467 for (int i = 1; i < node.getSpecializations().length; i++) { 514 for (int i = 1; i < node.getSpecializations().length; i++) {
468 SpecializationData specialization = node.getSpecializations()[i]; 515 SpecializationData specialization = node.getSpecializations()[i];
469 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); 516 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end();
470 517
471 if (specialization.isGeneric()) { 518 CodeTreeBuilder guarded = new CodeTreeBuilder(body);
472 body.startIf().string("allowed").end().startBlock(); 519 guarded.startReturn().startNew(nodeClassName(specialization));
473 } else { 520 guarded.string(THIS_NODE_LOCAL_VAR_NAME);
474 body.startIf().string("allowed"); 521 guarded.end().end();
475 String prefix = " && "; 522
476 prefix = emitImplicitGuards(getContext(), body, prefix, node.getGenericSpecialization(), specialization); 523 body.tree(createGuardAndCast(getContext(), body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null));
477 emitExplicitGuards(getContext(), body, prefix, node.getGenericSpecialization(), specialization, true);
478 body.end().startBlock();
479 }
480 body.startReturn().startNew(nodeClassName(specialization));
481 body.string(THIS_NODE_LOCAL_VAR_NAME);
482 body.end().end();
483 body.end(); // block
484 } 524 }
485 body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); 525 body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
486 526
487 return method; 527 return method;
488 } 528 }
522 return Arrays.asList(method); 562 return Arrays.asList(method);
523 } 563 }
524 } 564 }
525 565
526 private void emitGeneratedGenericSpecialization(CodeTreeBuilder builder, SpecializationData current, SpecializationData next) { 566 private void emitGeneratedGenericSpecialization(CodeTreeBuilder builder, SpecializationData current, SpecializationData next) {
567 CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder);
568 emitInvokeDoMethod(invokeMethodBuilder, current, 0);
569 CodeTree invokeMethod = invokeMethodBuilder.getRoot();
570
527 if (next != null) { 571 if (next != null) {
528 builder.startIf(); 572 invokeMethod = createGuardAndCast(getContext(), builder, "", current.getNode().getGenericSpecialization(), current, false, invokeMethod, null);
529 String prefix = emitImplicitGuards(context, builder, "", current.getNode().getGenericSpecialization(), current); 573 }
530 emitExplicitGuards(context, builder, prefix, current.getNode().getGenericSpecialization(), current, false); 574
531 builder.end().startBlock(); 575 builder.tree(invokeMethod);
532 }
533
534 emitInvokeDoMethod(builder, current, 0);
535 576
536 if (next != null) { 577 if (next != null) {
537 builder.end(); 578 builder.end();
538 579
539 builder.startReturn().startCall(generatedGenericMethodName(next)); 580 builder.startReturn().startCall(generatedGenericMethodName(next));
697 builder.end().end(); 738 builder.end().end();
698 return builder.getRoot(); 739 return builder.getRoot();
699 } 740 }
700 741
701 private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) { 742 private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) {
743 if (specialization.isUninitialized()) {
744 builder.tree(createDeoptimize(builder));
745 }
746
747 builder.tree(createExecuteChildren(builder, specialization));
748
749 if (specialization.isUninitialized()) {
750 builder.tree(createSpecializeCall(builder, specialization));
751 }
752
753 CodeTree executeNode = createExecute(builder, specialization);
754
755 SpecializationData next = specialization.findNextSpecialization();
756 CodeTree returnSpecialized = null;
757 if (next != null) {
758 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null);
759 }
760 builder.tree(createGuardAndCast(context, builder, "", specialization, specialization, false, executeNode, returnSpecialized));
761 }
762
763 private CodeTree createDeoptimize(CodeTreeBuilder parent) {
764 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
765 builder.startStatement();
766 builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
767 builder.end();
768 return builder.getRoot();
769 }
770
771 private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) {
702 NodeData node = specialization.getNode(); 772 NodeData node = specialization.getNode();
703 TypeSystemData typeSystem = node.getTypeSystem(); 773
704 774 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
705 if (specialization.isUninitialized()) { 775 emitSpecializationListeners(builder, node);
706 builder.startStatement(); 776
707 builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end(); 777 builder.startStatement();
708 builder.end(); 778 builder.startCall("replace");
709 } 779 if (node.needsRewrites(getContext())) {
710 780 builder.startCall(factoryClassName(node), "specialize");
711 for (NodeFieldData field : node.getFields()) { 781 builder.string("this");
712 if (field.getExecutionKind() == ExecutionKind.IGNORE) { 782 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType());
713 continue; 783 addValueParameterNames(builder, specialization, null, false);
714 } 784 builder.end(); // call replace, call specialize
715 785 } else {
716 ActualParameter parameterType = specialization.findParameter(field.getName()); 786 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
717 787 }
718 if (parameterType.getActualTypeData(typeSystem).isGeneric()) { 788 builder.end().end();
719 buildGenericValueExecute(builder, specialization, field, null); 789 return builder.getRoot();
720 } else { 790 }
721 buildSpecializedValueExecute(builder, specialization, field); 791
722 } 792 private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) {
723 } 793 NodeData node = specialization.getNode();
724 794 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
725 if (specialization.hasDynamicGuards()) {
726 builder.startIf();
727
728 String prefix = emitImplicitGuards(getContext(), builder, "", specialization, specialization);
729 emitExplicitGuards(getContext(), builder, prefix, specialization, specialization, false);
730 builder.end().startBlock();
731 }
732
733 if (specialization.getExceptions().length > 0) { 795 if (specialization.getExceptions().length > 0) {
734 builder.startTryBlock(); 796 builder.startTryBlock();
735 }
736
737 if (specialization.isUninitialized()) {
738 emitSpecializationListeners(builder, node);
739
740 builder.startStatement();
741 builder.startCall("replace");
742 if (node.needsRewrites(getContext())) {
743 builder.startCall(factoryClassName(node), "specialize");
744 builder.string("this");
745 builder.typeLiteral(builder.getRoot().getEnclosingClass().asType());
746 addValueParameterNames(builder, specialization, null, false);
747 builder.end(); // call replace, call specialize
748 } else {
749 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
750 }
751 builder.end().end();
752 } 797 }
753 798
754 if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { 799 if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) {
755 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); 800 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null));
756 builder.string("this"); 801 builder.string("this");
770 } 815 }
771 816
772 if (specialization.getExceptions().length > 0) { 817 if (specialization.getExceptions().length > 0) {
773 for (SpecializationThrowsData exception : specialization.getExceptions()) { 818 for (SpecializationThrowsData exception : specialization.getExceptions()) {
774 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); 819 builder.end().startCatchBlock(exception.getJavaClass(), "ex");
775 emitReturnSpecializeAndExecute(builder, exception.getTransitionTo(), null); 820 builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null));
776 } 821 }
777 builder.end(); 822 builder.end();
778 } 823 }
779 if (specialization.hasDynamicGuards()) { 824 return builder.getRoot();
780 builder.end().startElseBlock(); 825 }
781 emitReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), null); 826
782 builder.end(); 827 private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) {
783 } 828 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
829 for (NodeFieldData field : specialization.getNode().getFields()) {
830 if (field.getExecutionKind() == ExecutionKind.IGNORE) {
831 continue;
832 }
833
834 ActualParameter parameterType = specialization.findParameter(field.getName());
835
836 if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) {
837 buildGenericValueExecute(builder, specialization, field, null);
838 } else {
839 buildSpecializedValueExecute(builder, specialization, field);
840 }
841 }
842 return builder.getRoot();
784 } 843 }
785 844
786 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { 845 private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
787 for (TemplateMethod listener : node.getSpecializationListeners()) { 846 for (TemplateMethod listener : node.getSpecializationListeners()) {
788 builder.startStatement(); 847 builder.startStatement();
864 buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field); 923 buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field);
865 } else if (exField == field) { 924 } else if (exField == field) {
866 execute = true; 925 execute = true;
867 } 926 }
868 } 927 }
869 emitReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification()); 928 builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification()));
870 builder.end(); // catch block 929 builder.end(); // catch block
871 } 930 }
872 931
873 endShortCircuit(builder, shortCircuit); 932 endShortCircuit(builder, shortCircuit);
874 builder.newLine(); 933 builder.newLine();
912 if (shortCircuit) { 971 if (shortCircuit) {
913 builder.end(); 972 builder.end();
914 } 973 }
915 } 974 }
916 975
917 private void emitReturnSpecializeAndExecute(CodeTreeBuilder builder, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { 976 private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
918 CodeTreeBuilder specializeCall = CodeTreeBuilder.createBuilder(); 977 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
919 specializeCall.startCall("specializeAndExecute"); 978 specializeCall.startCall("specializeAndExecute");
920 specializeCall.string(nodeClassName(nextSpecialization) + ".class"); 979 specializeCall.string(nodeClassName(nextSpecialization) + ".class");
921 addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true); 980 addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true);
922 specializeCall.end().end(); 981 specializeCall.end().end();
923 982
983 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
924 builder.startReturn(); 984 builder.startReturn();
925 builder.tree(specializeCall.getRoot()); 985 builder.tree(specializeCall.getRoot());
926 builder.end(); 986 builder.end();
987 return builder.getRoot();
927 } 988 }
928 989
929 private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) { 990 private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) {
930 NodeData node = specialization.getNode(); 991 NodeData node = specialization.getNode();
931 TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); 992 TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem());
940 addValueParameters(method, specialization.getNode().getGenericSpecialization(), true); 1001 addValueParameters(method, specialization.getNode().getGenericSpecialization(), true);
941 clazz.add(method); 1002 clazz.add(method);
942 1003
943 CodeTreeBuilder builder = method.createBuilder(); 1004 CodeTreeBuilder builder = method.createBuilder();
944 1005
945 builder.startStatement(); 1006 builder.tree(createDeoptimize(builder));
946 builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
947 builder.end();
948
949 emitSpecializationListeners(builder, specialization.getNode()); 1007 emitSpecializationListeners(builder, specialization.getNode());
950 1008
951 builder.startStatement(); 1009 builder.startStatement();
952 builder.startCall("replace"); 1010 builder.startCall("replace");
953 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); 1011 builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState");