Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 16755:bd28da642eea
Truffle-DSL: Several new features implemented:
Implementation of a new code generation layout which shares code between generated nodes.
Declaration order of specializations is now used as specialization order.
Specializations do no longer perform fallthrough on respecialization, they now always respecialize from the first specialization.
Implemented support for contains relations between specializations.
Improved reachability error messages.
Preliminary support for @Implies.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 11 Aug 2014 15:53:05 +0200 |
parents | 4f397be8f424 |
children |
comparison
equal
deleted
inserted
replaced
16754:55fd5be68a52 | 16755:bd28da642eea |
---|---|
33 | 33 |
34 import com.oracle.truffle.api.dsl.*; | 34 import com.oracle.truffle.api.dsl.*; |
35 import com.oracle.truffle.api.nodes.*; | 35 import com.oracle.truffle.api.nodes.*; |
36 import com.oracle.truffle.dsl.processor.*; | 36 import com.oracle.truffle.dsl.processor.*; |
37 import com.oracle.truffle.dsl.processor.ast.*; | 37 import com.oracle.truffle.dsl.processor.ast.*; |
38 import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror; | |
38 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; | 39 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; |
39 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; | 40 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; |
40 import com.oracle.truffle.dsl.processor.template.*; | 41 import com.oracle.truffle.dsl.processor.template.*; |
41 import com.oracle.truffle.dsl.processor.typesystem.*; | 42 import com.oracle.truffle.dsl.processor.typesystem.*; |
42 | 43 |
43 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { | 44 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { |
44 | 45 |
45 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; | 46 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; |
46 | 47 |
47 private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; | 48 private static final String EXECUTE_CHAINED = "executeChained0"; |
48 private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; | 49 private static final String SPECIALIZE = "specialize0"; |
49 private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0"; | 50 private static final String DSLSHARE_REWRITE = "rewrite"; |
50 | 51 private static final String DSLSHARE_FIND_ROOT = "findRoot"; |
51 private static final String UPDATE_TYPES_NAME = "updateTypes"; | 52 private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic"; |
52 private static final String COPY_WITH_CONSTRUCTOR_NAME = "copyWithConstructor"; | 53 private static final String EXECUTE_UNINITIALIZED = "executeUninitialized0"; |
53 private static final String CREATE_SPECIALIZATION_NAME = "createSpecialization"; | 54 private static final String REWRITE = "rewrite0"; |
54 | 55 private static final String CREATE_INFO = "createInfo0"; |
55 public NodeCodeGenerator(ProcessorContext context) { | 56 private static final String CONTAINS_FALLBACK = "containsFallback"; |
56 super(context); | 57 |
57 } | 58 private static final String FACTORY_METHOD_NAME = "create0"; |
59 private static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY"; | |
60 | |
61 private static final String METADATA_FIELD_NAME = "METADATA"; | |
58 | 62 |
59 private TypeMirror getUnexpectedValueException() { | 63 private TypeMirror getUnexpectedValueException() { |
60 return getContext().getTruffleTypes().getUnexpectedValueException(); | 64 return getContext().getTruffleTypes().getUnexpectedValueException(); |
61 } | 65 } |
62 | 66 |
90 | 94 |
91 private static String implicitTypeName(ActualParameter param) { | 95 private static String implicitTypeName(ActualParameter param) { |
92 return param.getLocalName() + "ImplicitType"; | 96 return param.getLocalName() + "ImplicitType"; |
93 } | 97 } |
94 | 98 |
95 private static String polymorphicTypeName(ActualParameter param) { | 99 private static String polymorphicTypeName(NodeExecutionData param) { |
96 return param.getLocalName() + "PolymorphicType"; | 100 return param.getName() + "PolymorphicType"; |
97 } | 101 } |
98 | 102 |
99 private static String valueName(ActualParameter param) { | 103 private static String valueName(ActualParameter param) { |
100 return param.getLocalName(); | 104 return param.getLocalName(); |
101 } | 105 } |
144 | 148 |
145 method.addParameter(new CodeVariableElement(parameter.getType(), name)); | 149 method.addParameter(new CodeVariableElement(parameter.getType(), name)); |
146 } | 150 } |
147 } | 151 } |
148 | 152 |
149 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, | 153 private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, |
150 Map<String, String> customNames) { | 154 Map<String, String> customNames) { |
151 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { | 155 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { |
152 builder.string("frameValue"); | 156 builder.string("frameValue"); |
153 } | 157 } |
154 for (ActualParameter parameter : specialization.getParameters()) { | 158 for (ActualParameter parameter : specialization.getParameters()) { |
173 builder.string(valueName(parameter)); | 177 builder.string(valueName(parameter)); |
174 } | 178 } |
175 } | 179 } |
176 } | 180 } |
177 | 181 |
178 private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { | 182 private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { |
179 if (!sourceParameter.getSpecification().isSignature()) { | 183 if (!sourceParameter.getSpecification().isSignature()) { |
180 return valueName(targetParameter); | 184 return valueName(targetParameter); |
181 } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { | 185 } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { |
182 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { | 186 if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) { |
183 return castValueName(targetParameter); | 187 return castValueName(targetParameter); |
184 } | 188 } |
185 } | 189 } |
186 return valueName(targetParameter); | 190 return valueName(targetParameter); |
187 } | 191 } |
188 | 192 |
189 private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, | 193 private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, |
190 String... customSignatureValueNames) { | 194 String... customSignatureValueNames) { |
191 CodeTreeBuilder builder = parent.create(); | 195 CodeTreeBuilder builder = parent.create(); |
192 | 196 |
193 boolean castedValues = sourceMethod != targetMethod; | 197 boolean castedValues = sourceMethod != targetMethod; |
194 | 198 |
199 } | 203 } |
200 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); | 204 TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); |
201 NodeData node = (NodeData) targetMethod.getTemplate(); | 205 NodeData node = (NodeData) targetMethod.getTemplate(); |
202 | 206 |
203 if (target == null) { | 207 if (target == null) { |
204 boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); | 208 boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); |
205 if (accessible) { | 209 if (accessible) { |
206 if (builder.findMethod().getModifiers().contains(STATIC)) { | 210 if (builder.findMethod().getModifiers().contains(STATIC)) { |
207 if (method.getModifiers().contains(STATIC)) { | 211 if (method.getModifiers().contains(STATIC)) { |
208 builder.type(targetClass.asType()); | 212 builder.type(targetClass.asType()); |
209 } else { | 213 } else { |
274 } | 278 } |
275 builder.string(targetParameter.getSpecification().getName()); | 279 builder.string(targetParameter.getSpecification().getName()); |
276 builder.end(); | 280 builder.end(); |
277 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { | 281 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { |
278 builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); | 282 builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); |
279 } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) { | 283 } else if (!Utils.needsCastTo(valueType, targetType)) { |
280 builder.startGroup(); | 284 builder.startGroup(); |
281 builder.string(valueName(targetParameter)); | 285 builder.string(valueName(targetParameter)); |
282 builder.end(); | 286 builder.end(); |
283 } else { | 287 } else { |
284 builder.string(castValueName(targetParameter)); | 288 builder.string(castValueName(targetParameter)); |
295 String name = Utils.firstLetterUpperCase(nodeid); | 299 String name = Utils.firstLetterUpperCase(nodeid); |
296 name += "BaseNode"; | 300 name += "BaseNode"; |
297 return name; | 301 return name; |
298 } | 302 } |
299 | 303 |
300 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { | 304 private static CodeTree createCallTypeSystemMethod(CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { |
301 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 305 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
302 startCallTypeSystemMethod(context, builder, node.getTypeSystem(), methodName); | 306 startCallTypeSystemMethod(builder, node.getTypeSystem(), methodName); |
303 for (CodeTree arg : args) { | 307 for (CodeTree arg : args) { |
304 builder.tree(arg); | 308 builder.tree(arg); |
305 } | 309 } |
306 builder.end().end(); | 310 builder.end().end(); |
307 return builder.getRoot(); | 311 return builder.getRoot(); |
308 } | 312 } |
309 | 313 |
310 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { | 314 private static void startCallTypeSystemMethod(CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { |
311 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, typeSystem); | 315 GeneratedTypeMirror typeMirror = new GeneratedTypeMirror(Utils.getPackageName(typeSystem.getTemplateType()), TypeSystemCodeGenerator.typeName(typeSystem)); |
312 assert singleton != null; | |
313 | |
314 body.startGroup(); | 316 body.startGroup(); |
315 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); | 317 body.staticReference(typeMirror, TypeSystemCodeGenerator.singletonName(typeSystem)); |
316 body.string(".").startCall(methodName); | 318 body.string(".").startCall(methodName); |
317 } | 319 } |
318 | 320 |
319 /** | 321 /** |
320 * <pre> | 322 * <pre> |
361 if (executionData != null) { | 363 if (executionData != null) { |
362 if (executionData.isShortCircuit()) { | 364 if (executionData.isShortCircuit()) { |
363 nodes.nullLiteral(); | 365 nodes.nullLiteral(); |
364 arguments.string(valueName(parameter.getPreviousParameter())); | 366 arguments.string(valueName(parameter.getPreviousParameter())); |
365 } | 367 } |
366 nodes.tree(createAccessChild(executionData, null)); | 368 nodes.tree(createAccessChild(executionData, "rootNode")); |
367 arguments.string(valueName(parameter)); | 369 arguments.string(valueName(parameter)); |
368 empty = false; | 370 empty = false; |
369 } | 371 } |
370 } | 372 } |
371 nodes.end(); | 373 nodes.end(); |
372 arguments.end(); | 374 arguments.end(); |
373 | 375 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); |
376 | |
377 builder.declaration(baseClassName(getModel()), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end()); | |
374 builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class)); | 378 builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class)); |
375 builder.string("this"); | 379 builder.string("rootNode"); |
376 builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null); | 380 builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null); |
377 | |
378 builder.tree(nodes.getRoot()); | 381 builder.tree(nodes.getRoot()); |
379 builder.end(); | 382 builder.end(); |
380 if (!empty) { | 383 if (!empty) { |
381 builder.tree(arguments.getRoot()); | 384 builder.tree(arguments.getRoot()); |
382 } | 385 } |
444 List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements()); | 447 List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements()); |
445 getElement().getEnclosedElements().clear(); | 448 getElement().getEnclosedElements().clear(); |
446 | 449 |
447 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); | 450 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); |
448 for (NodeData nodeChild : node.getEnclosingNodes()) { | 451 for (NodeData nodeChild : node.getEnclosingNodes()) { |
449 NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); | 452 NodeCodeGenerator generator = new NodeCodeGenerator(); |
450 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); | 453 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); |
451 } | 454 } |
452 | 455 |
453 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { | 456 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { |
454 NodeFactoryFactory factory = new NodeFactoryFactory(context, childTypes); | 457 NodeFactoryFactory factory = new NodeFactoryFactory(childTypes); |
455 add(factory, node); | 458 add(factory, node); |
456 factory.getElement().getEnclosedElements().addAll(casts); | 459 factory.getElement().getEnclosedElements().addAll(casts); |
457 } | 460 } |
458 } | 461 } |
459 | 462 |
460 protected CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { | 463 private static CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { |
461 if (targetType == null) { | 464 if (targetType == null) { |
462 return value; | 465 return value; |
463 } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) { | 466 } else if (sourceType != null && !sourceType.needsCastTo(targetType)) { |
464 return value; | 467 return value; |
465 } | 468 } |
466 | 469 |
467 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); | 470 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); |
468 String targetMethodName; | 471 String targetMethodName; |
469 if (expect) { | 472 if (expect) { |
470 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); | 473 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); |
471 } else { | 474 } else { |
472 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); | 475 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); |
473 } | 476 } |
474 startCallTypeSystemMethod(getContext(), builder, typeSystem, targetMethodName); | 477 startCallTypeSystemMethod(builder, typeSystem, targetMethodName); |
475 builder.tree(value); | 478 builder.tree(value); |
476 builder.end().end(); | 479 builder.end().end(); |
477 return builder.getRoot(); | 480 return builder.getRoot(); |
478 } | 481 } |
479 | 482 |
480 protected CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { | 483 private static CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { |
481 return createCastType(typeSystem, sourceType, targetType, true, expression); | 484 return createCastType(typeSystem, sourceType, targetType, true, expression); |
482 } | 485 } |
483 | 486 |
484 public CodeTree createDeoptimize(CodeTreeBuilder parent) { | 487 private CodeTree createDeoptimize(CodeTreeBuilder parent) { |
485 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 488 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
486 builder.startStatement(); | 489 builder.startStatement(); |
487 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); | 490 builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); |
488 builder.end(); | 491 builder.end(); |
489 return builder.getRoot(); | 492 return builder.getRoot(); |
492 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { | 495 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { |
493 | 496 |
494 private final Map<NodeData, List<TypeElement>> childTypes; | 497 private final Map<NodeData, List<TypeElement>> childTypes; |
495 private CodeTypeElement generatedNode; | 498 private CodeTypeElement generatedNode; |
496 | 499 |
497 public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) { | 500 public NodeFactoryFactory(Map<NodeData, List<TypeElement>> childElements) { |
498 super(context); | |
499 this.childTypes = childElements; | 501 this.childTypes = childElements; |
500 } | 502 } |
501 | 503 |
502 @Override | 504 @Override |
503 protected CodeTypeElement create(NodeData node) { | 505 protected CodeTypeElement create(NodeData node) { |
504 Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers()); | 506 Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers()); |
507 | |
505 CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); | 508 CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); |
506 if (visibility != null) { | 509 if (visibility != null) { |
507 clazz.getModifiers().add(visibility); | 510 clazz.getModifiers().add(visibility); |
508 } | 511 } |
509 clazz.getModifiers().add(Modifier.FINAL); | 512 clazz.getModifiers().add(Modifier.FINAL); |
510 clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz)); | |
511 return clazz; | 513 return clazz; |
512 } | 514 } |
513 | 515 |
514 @Override | 516 @Override |
515 protected void createChildren(NodeData node) { | 517 protected void createChildren(NodeData node) { |
516 CodeTypeElement clazz = getElement(); | 518 CodeTypeElement clazz = getElement(); |
517 | 519 |
518 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); | 520 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); |
519 | 521 |
520 CodeTypeElement polymorphicNode = null; | |
521 if (node.needsFactory()) { | 522 if (node.needsFactory()) { |
522 NodeBaseFactory factory = new NodeBaseFactory(context); | 523 NodeBaseFactory factory = new NodeBaseFactory(); |
523 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); | 524 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); |
524 generatedNode = factory.getElement(); | 525 generatedNode = factory.getElement(); |
525 | 526 |
526 if (node.needsRewrites(context)) { | |
527 clazz.add(createCreateGenericMethod(node, createVisibility)); | |
528 } | |
529 | |
530 createFactoryMethods(node, clazz, createVisibility); | 527 createFactoryMethods(node, clazz, createVisibility); |
531 | 528 |
532 for (SpecializationData specialization : node.getSpecializations()) { | 529 for (SpecializationData specialization : node.getSpecializations()) { |
533 if (!specialization.isReachable()) { | 530 if (!specialization.isReachable() || specialization.isGeneric()) { |
534 continue; | 531 continue; |
535 } | 532 } |
536 | 533 |
537 if (specialization.isPolymorphic() && node.isPolymorphic()) { | 534 if (specialization.isPolymorphic() && node.isPolymorphic(context)) { |
538 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(getContext(), generatedNode); | 535 PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode); |
539 add(polymorphicFactory, specialization); | 536 add(polymorphicFactory, specialization); |
540 polymorphicNode = polymorphicFactory.getElement(); | |
541 continue; | 537 continue; |
542 } | 538 } |
543 | 539 |
544 add(new SpecializedNodeFactory(context, generatedNode), specialization); | 540 add(new SpecializedNodeFactory(generatedNode), specialization); |
545 } | 541 } |
546 | 542 |
547 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); | 543 TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType()); |
548 clazz.getImplements().add(nodeFactory); | 544 clazz.setSuperClass(nodeFactory); |
545 clazz.add(createNodeFactoryConstructor(node)); | |
549 clazz.add(createCreateNodeMethod(node)); | 546 clazz.add(createCreateNodeMethod(node)); |
550 clazz.add(createGetNodeClassMethod(node)); | 547 // clazz.add(createGetNodeClassMethod(node)); |
551 clazz.add(createGetNodeSignaturesMethod()); | 548 // clazz.add(createGetNodeSignaturesMethod()); |
552 clazz.add(createGetChildrenSignatureMethod(node)); | 549 // clazz.add(createGetChildrenSignatureMethod(node)); |
553 clazz.add(createGetInstanceMethod(node, createVisibility)); | 550 clazz.add(createGetInstanceMethod(node, createVisibility)); |
554 clazz.add(createInstanceConstant(node, clazz.asType())); | 551 clazz.add(createInstanceConstant(node, clazz.asType())); |
555 } | |
556 | |
557 if (polymorphicNode != null) { | |
558 patchParameterType(clazz, UPDATE_TYPES_NAME, generatedNode.asType(), polymorphicNode.asType()); | |
559 } | 552 } |
560 | 553 |
561 for (NodeData childNode : childTypes.keySet()) { | 554 for (NodeData childNode : childTypes.keySet()) { |
562 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { | 555 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { |
563 continue; | 556 continue; |
582 clazz.add(createGetFactories(node)); | 575 clazz.add(createGetFactories(node)); |
583 } | 576 } |
584 | 577 |
585 } | 578 } |
586 | 579 |
587 private void patchParameterType(CodeTypeElement enclosingClass, String methodName, TypeMirror originalType, TypeMirror newType) { | 580 private Element createNodeFactoryConstructor(NodeData node) { |
588 for (TypeElement enclosedType : ElementFilter.typesIn(enclosingClass.getEnclosedElements())) { | 581 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node)); |
589 CodeTypeElement type = (CodeTypeElement) enclosedType; | |
590 ExecutableElement method = type.getMethod(methodName); | |
591 for (VariableElement v : method.getParameters()) { | |
592 CodeVariableElement var = (CodeVariableElement) v; | |
593 if (Utils.typeEquals(var.getType(), originalType)) { | |
594 var.setType(newType); | |
595 } | |
596 } | |
597 } | |
598 } | |
599 | |
600 private CodeExecutableElement createGetNodeClassMethod(NodeData node) { | |
601 TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); | |
602 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); | |
603 CodeTreeBuilder builder = method.createBuilder(); | 582 CodeTreeBuilder builder = method.createBuilder(); |
604 builder.startReturn().typeLiteral(node.getNodeType()).end(); | 583 builder.startStatement(); |
605 return method; | 584 builder.startCall("super"); |
606 } | 585 |
607 | 586 // node type |
608 private CodeExecutableElement createGetNodeSignaturesMethod() { | 587 builder.typeLiteral(node.getNodeType()); |
609 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); | 588 |
610 TypeMirror classType = getContext().getType(Class.class); | 589 // execution signature |
611 TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); | 590 builder.startGroup(); |
612 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); | 591 if (node.getChildExecutions().isEmpty()) { |
613 CodeTreeBuilder builder = method.createBuilder(); | 592 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); |
614 builder.startReturn(); | 593 } else { |
615 builder.startStaticCall(getContext().getType(Arrays.class), "asList"); | 594 builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null); |
595 for (NodeExecutionData execution : node.getChildExecutions()) { | |
596 builder.typeLiteral(execution.getNodeType()); | |
597 } | |
598 builder.end(); | |
599 } | |
600 builder.end(); | |
601 | |
602 // node signatures | |
603 builder.startGroup(); | |
604 builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null); | |
616 List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType()); | 605 List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType()); |
617 for (ExecutableElement constructor : constructors) { | 606 for (ExecutableElement constructor : constructors) { |
618 builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); | 607 builder.startGroup(); |
608 if (constructor.getParameters().isEmpty()) { | |
609 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); | |
610 } else { | |
611 builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null); | |
612 for (VariableElement var : constructor.getParameters()) { | |
613 builder.typeLiteral(var.asType()); | |
614 } | |
615 builder.end(); | |
616 } | |
617 builder.end(); | |
619 } | 618 } |
620 builder.end(); | 619 builder.end(); |
621 builder.end(); | 620 builder.end(); |
621 | |
622 builder.end().end().end(); | |
622 return method; | 623 return method; |
623 } | |
624 | |
625 private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) { | |
626 Types types = getContext().getEnvironment().getTypeUtils(); | |
627 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); | |
628 TypeMirror classType = getContext().getType(Class.class); | |
629 TypeMirror nodeType = getContext().getTruffleTypes().getNode(); | |
630 TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null); | |
631 classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); | |
632 TypeMirror returnType = Utils.getDeclaredType(listType, classType); | |
633 | |
634 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); | |
635 CodeTreeBuilder builder = method.createBuilder(); | |
636 | |
637 List<TypeMirror> signatureTypes = new ArrayList<>(); | |
638 assert !node.getSpecializations().isEmpty(); | |
639 SpecializationData data = node.getSpecializations().get(0); | |
640 | |
641 for (ActualParameter parameter : data.getSignatureParameters()) { | |
642 signatureTypes.add(parameter.getSpecification().getExecution().getNodeType()); | |
643 } | |
644 | |
645 builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end(); | |
646 return method; | |
647 } | |
648 | |
649 private CodeTree createAsList(CodeTreeBuilder parent, List<TypeMirror> types, TypeMirror elementClass) { | |
650 CodeTreeBuilder builder = parent.create(); | |
651 builder.startGroup(); | |
652 builder.type(getContext().getType(Arrays.class)); | |
653 builder.string(".<").type(elementClass).string(">"); | |
654 builder.startCall("asList"); | |
655 for (TypeMirror typeMirror : types) { | |
656 builder.typeLiteral(typeMirror); | |
657 } | |
658 builder.end().end(); | |
659 return builder.getRoot(); | |
660 } | 624 } |
661 | 625 |
662 private CodeExecutableElement createCreateNodeMethod(NodeData node) { | 626 private CodeExecutableElement createCreateNodeMethod(NodeData node) { |
663 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); | 627 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); |
664 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); | 628 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); |
834 CodeTreeBuilder body = method.createBuilder(); | 798 CodeTreeBuilder body = method.createBuilder(); |
835 body.startReturn(); | 799 body.startReturn(); |
836 if (node.getSpecializations().isEmpty()) { | 800 if (node.getSpecializations().isEmpty()) { |
837 body.nullLiteral(); | 801 body.nullLiteral(); |
838 } else { | 802 } else { |
839 body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), CREATE_SPECIALIZATION_NAME); | 803 body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME); |
840 for (VariableElement var : method.getParameters()) { | 804 for (VariableElement var : method.getParameters()) { |
841 body.string(var.getSimpleName().toString()); | 805 body.string(var.getSimpleName().toString()); |
842 } | 806 } |
843 body.end(); | 807 body.end(); |
844 } | 808 } |
845 body.end(); | 809 body.end(); |
846 return method; | 810 return method; |
847 } | 811 } |
848 | 812 |
849 private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) { | |
850 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric"); | |
851 if (visibility != null) { | |
852 method.getModifiers().add(visibility); | |
853 } | |
854 method.getModifiers().add(Modifier.STATIC); | |
855 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); | |
856 | |
857 CodeTreeBuilder body = method.createBuilder(); | |
858 | |
859 SpecializationData found = null; | |
860 List<SpecializationData> specializations = node.getSpecializations(); | |
861 for (int i = 0; i < specializations.size(); i++) { | |
862 if (specializations.get(i).isReachable()) { | |
863 found = specializations.get(i); | |
864 } | |
865 } | |
866 | |
867 if (found == null) { | |
868 body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); | |
869 } else { | |
870 body.startReturn().startCall(nodeSpecializationClassName(found), CREATE_SPECIALIZATION_NAME).startGroup().string(THIS_NODE_LOCAL_VAR_NAME).end().end().end(); | |
871 } | |
872 return method; | |
873 } | |
874 } | 813 } |
875 | 814 |
876 private class NodeBaseFactory extends ClassElementFactory<SpecializationData> { | 815 private class NodeBaseFactory extends ClassElementFactory<SpecializationData> { |
877 | |
878 public NodeBaseFactory(ProcessorContext context) { | |
879 super(context); | |
880 } | |
881 | 816 |
882 @Override | 817 @Override |
883 protected CodeTypeElement create(SpecializationData specialization) { | 818 protected CodeTypeElement create(SpecializationData specialization) { |
884 NodeData node = specialization.getNode(); | 819 NodeData node = specialization.getNode(); |
885 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); | 820 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); |
821 clazz.getImplements().add(context.getTruffleTypes().getDslNode()); | |
886 | 822 |
887 for (NodeChildData child : node.getChildren()) { | 823 for (NodeChildData child : node.getChildren()) { |
888 clazz.add(createChildField(child)); | 824 clazz.add(createChildField(child)); |
889 | 825 |
890 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { | 826 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { |
926 CodeTypeElement clazz = getElement(); | 862 CodeTypeElement clazz = getElement(); |
927 | 863 |
928 SpecializationGroup rootGroup = createSpecializationGroups(node); | 864 SpecializationGroup rootGroup = createSpecializationGroups(node); |
929 | 865 |
930 if (node.needsRewrites(context)) { | 866 if (node.needsRewrites(context)) { |
931 if (node.isPolymorphic()) { | 867 if (node.isPolymorphic(context)) { |
932 | 868 |
933 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); | 869 CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); |
934 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); | 870 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); |
935 clazz.add(var); | 871 clazz.add(var); |
936 | 872 |
937 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); | 873 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); |
938 clazz.add(genericCachedExecute); | 874 clazz.add(genericCachedExecute); |
939 | 875 |
940 getElement().add(createUpdateTypes(clazz.asType())); | |
941 } | 876 } |
942 | 877 |
943 for (CodeExecutableElement method : createImplicitChildrenAccessors()) { | 878 for (CodeExecutableElement method : createImplicitChildrenAccessors()) { |
944 clazz.add(method); | 879 clazz.add(method); |
945 } | 880 } |
946 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); | |
947 clazz.add(createInfoMessage(node)); | 881 clazz.add(createInfoMessage(node)); |
948 } | 882 clazz.add(createMonomorphicRewrite()); |
949 | 883 clazz.add(createCreateSpecializationMethod(node, rootGroup)); |
950 if (needsInvokeCopyConstructorMethod()) { | 884 } |
951 clazz.add(createCopy(clazz.asType(), null)); | 885 |
952 } | 886 clazz.add(createAdoptChildren0()); |
953 | 887 clazz.add(createGetMetadata0(true)); |
954 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { | 888 clazz.add(createUpdateTypes0()); |
955 clazz.add(createGenericExecute(node, rootGroup)); | 889 clazz.add(createGetNext()); |
956 } | 890 } |
957 } | 891 |
958 | 892 private Element createGetNext() { |
959 protected boolean needsInvokeCopyConstructorMethod() { | 893 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0"); |
960 return getModel().getNode().isPolymorphic(); | 894 CodeTreeBuilder builder = method.createBuilder(); |
961 } | 895 NodeData node = getModel().getNode(); |
962 | 896 |
963 protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) { | 897 if (node.isPolymorphic(context)) { |
964 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, COPY_WITH_CONSTRUCTOR_NAME); | 898 builder.startReturn().string("next0").end(); |
965 if (specialization == null) { | |
966 method.getModifiers().add(ABSTRACT); | |
967 } else { | 899 } else { |
900 builder.returnNull(); | |
901 } | |
902 | |
903 return method; | |
904 } | |
905 | |
906 protected final CodeExecutableElement createUpdateTypes0() { | |
907 ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); | |
908 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0"); | |
909 method.getParameters().add(new CodeVariableElement(classArray, "types")); | |
910 | |
911 if (getModel().isPolymorphic()) { | |
968 CodeTreeBuilder builder = method.createBuilder(); | 912 CodeTreeBuilder builder = method.createBuilder(); |
969 builder.startReturn(); | 913 |
970 builder.startNew(getElement().asType()); | 914 int index = 0; |
971 builder.string("this"); | 915 for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) { |
972 for (ActualParameter param : getImplicitTypeParameters(specialization)) { | 916 String fieldName = polymorphicTypeName(execution); |
973 builder.string(implicitTypeName(param)); | 917 |
974 } | 918 builder.startStatement(); |
975 builder.end().end(); | 919 builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]"); |
976 } | 920 builder.end(); |
921 index++; | |
922 } | |
923 } | |
924 | |
925 return method; | |
926 } | |
927 | |
928 protected final CodeExecutableElement createGetMetadata0(boolean empty) { | |
929 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0"); | |
930 if (empty) { | |
931 method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end(); | |
932 } else { | |
933 method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end(); | |
934 } | |
935 return method; | |
936 } | |
937 | |
938 private CodeExecutableElement createAdoptChildren0() { | |
939 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0"); | |
940 method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other")); | |
941 method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext")); | |
942 NodeData node = getModel().getNode(); | |
943 CodeTreeBuilder builder = method.createBuilder(); | |
944 List<NodeExecutionData> executions = node.getChildExecutions(); | |
945 | |
946 if (executions.size() > 0) { | |
947 builder.startIf().string("other == null").end().startBlock(); | |
948 for (NodeExecutionData execution : executions) { | |
949 builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end(); | |
950 } | |
951 builder.end().startElseBlock(); | |
952 | |
953 String access; | |
954 if (executions.size() > 1) { | |
955 builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other")); | |
956 access = "otherCast"; | |
957 } else { | |
958 assert executions.size() == 1; | |
959 access = "((" + baseClassName(node) + ") other)"; | |
960 } | |
961 for (NodeExecutionData execution : executions) { | |
962 builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end(); | |
963 } | |
964 | |
965 builder.end(); | |
966 } | |
967 | |
968 if (getModel().getNode().isPolymorphic(context)) { | |
969 builder.startIf().string("newNext == null").end().startBlock(); | |
970 builder.statement("this.next0 = null"); | |
971 builder.end().startElseBlock(); | |
972 builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext"); | |
973 builder.end(); | |
974 } | |
975 | |
977 return method; | 976 return method; |
978 } | 977 } |
979 | 978 |
980 private List<CodeExecutableElement> createImplicitChildrenAccessors() { | 979 private List<CodeExecutableElement> createImplicitChildrenAccessors() { |
981 NodeData node = getModel().getNode(); | 980 NodeData node = getModel().getNode(); |
1033 builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); | 1032 builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); |
1034 return builder.getRoot(); | 1033 return builder.getRoot(); |
1035 } | 1034 } |
1036 | 1035 |
1037 private Element createInfoMessage(NodeData node) { | 1036 private Element createInfoMessage(NodeData node) { |
1038 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0"); | 1037 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO); |
1039 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); | 1038 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); |
1040 addInternalValueParameters(method, node.getGenericSpecialization(), false, false); | 1039 addInternalValueParameters(method, node.getGenericSpecialization(), false, false); |
1041 | 1040 |
1042 CodeTreeBuilder builder = method.createBuilder(); | 1041 CodeTreeBuilder builder = method.createBuilder(); |
1043 | 1042 |
1089 | 1088 |
1090 return method; | 1089 return method; |
1091 } | 1090 } |
1092 | 1091 |
1093 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { | 1092 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { |
1094 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME); | 1093 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED); |
1095 addInternalValueParameters(cachedExecute, polymorph, true, false); | 1094 addInternalValueParameters(cachedExecute, polymorph, true, false); |
1096 | 1095 |
1097 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); | 1096 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); |
1098 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); | 1097 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); |
1099 if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { | 1098 if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { |
1118 sourceSectionConstructor = constructor; | 1117 sourceSectionConstructor = constructor; |
1119 } | 1118 } |
1120 } | 1119 } |
1121 } | 1120 } |
1122 if (node.needsRewrites(getContext())) { | 1121 if (node.needsRewrites(getContext())) { |
1123 clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()), sourceSectionConstructor)); | 1122 ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType()); |
1123 clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor)); | |
1124 } | 1124 } |
1125 } | 1125 } |
1126 | 1126 |
1127 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { | 1127 private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { |
1128 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); | 1128 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); |
1143 } | 1143 } |
1144 builder.end().end(); | 1144 builder.end().end(); |
1145 } | 1145 } |
1146 | 1146 |
1147 for (VariableElement var : type.getFields()) { | 1147 for (VariableElement var : type.getFields()) { |
1148 if (var.getModifiers().contains(STATIC)) { | |
1149 continue; | |
1150 } | |
1148 NodeChildData child = node.findChild(var.getSimpleName().toString()); | 1151 NodeChildData child = node.findChild(var.getSimpleName().toString()); |
1149 | 1152 |
1150 if (child != null) { | 1153 if (child != null) { |
1151 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); | 1154 method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); |
1152 } else { | 1155 } else { |
1185 } else if (sourceSectionConstructor != null) { | 1188 } else if (sourceSectionConstructor != null) { |
1186 builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); | 1189 builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); |
1187 } | 1190 } |
1188 | 1191 |
1189 for (VariableElement var : type.getFields()) { | 1192 for (VariableElement var : type.getFields()) { |
1190 builder.startStatement(); | 1193 if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) { |
1194 continue; | |
1195 } | |
1191 final String varName = var.getSimpleName().toString(); | 1196 final String varName = var.getSimpleName().toString(); |
1192 final TypeMirror varType = var.asType(); | 1197 final TypeMirror varType = var.asType(); |
1193 | 1198 if (Utils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) { |
1194 String copyAccess = "copy." + varName; | 1199 CodeTree size = builder.create().string("copy.", varName, ".length").getRoot(); |
1195 if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) { | 1200 builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end(); |
1196 copyAccess += ".clone()"; | 1201 } else { |
1197 } | 1202 builder.startStatement().string("this.", varName, " = copy.", varName).end(); |
1198 CodeTree init = CodeTreeBuilder.singleString(copyAccess); | 1203 } |
1199 builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end(); | |
1200 } | 1204 } |
1201 | 1205 |
1202 return method; | 1206 return method; |
1203 } | 1207 } |
1204 | 1208 |
1223 | 1227 |
1224 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); | 1228 var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); |
1225 return var; | 1229 return var; |
1226 } | 1230 } |
1227 | 1231 |
1228 private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) { | |
1229 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); | |
1230 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_SPECIALIZE_NAME); | |
1231 method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState")); | |
1232 addInternalValueParameters(method, node.getGenericSpecialization(), true, false); | |
1233 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); | |
1234 | |
1235 CodeTreeBuilder builder = method.createBuilder(); | |
1236 builder.startStatement(); | |
1237 builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); | |
1238 builder.end(); | |
1239 | |
1240 String currentNode = "this"; | |
1241 for (SpecializationData specialization : node.getSpecializations()) { | |
1242 if (!specialization.getExceptions().isEmpty()) { | |
1243 currentNode = "current"; | |
1244 builder.declaration(baseClassName(node), currentNode, "this"); | |
1245 break; | |
1246 } | |
1247 } | |
1248 | |
1249 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); | |
1250 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, null); | |
1251 builder.end().end(); | |
1252 | |
1253 final String currentNodeVar = currentNode; | |
1254 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() { | |
1255 | |
1256 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | |
1257 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); | |
1258 } | |
1259 }, null, false, true, false)); | |
1260 | |
1261 boolean firstUnreachable = true; | |
1262 for (SpecializationData current : node.getSpecializations()) { | |
1263 if (current.isReachable()) { | |
1264 continue; | |
1265 } | |
1266 if (firstUnreachable) { | |
1267 emitEncounteredSynthetic(builder, current); | |
1268 firstUnreachable = false; | |
1269 } | |
1270 } | |
1271 emitUnreachableSpecializations(builder, node); | |
1272 | |
1273 return method; | |
1274 } | |
1275 | |
1276 private SpecializationGroup createSpecializationGroups(final NodeData node) { | 1232 private SpecializationGroup createSpecializationGroups(final NodeData node) { |
1277 List<SpecializationData> specializations = node.getSpecializations(); | 1233 List<SpecializationData> specializations = node.getSpecializations(); |
1278 List<SpecializationData> filteredSpecializations = new ArrayList<>(); | 1234 List<SpecializationData> filteredSpecializations = new ArrayList<>(); |
1279 for (SpecializationData current : specializations) { | 1235 for (SpecializationData current : specializations) { |
1280 if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { | 1236 if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { |
1284 } | 1240 } |
1285 | 1241 |
1286 return SpecializationGroup.create(filteredSpecializations); | 1242 return SpecializationGroup.create(filteredSpecializations); |
1287 } | 1243 } |
1288 | 1244 |
1289 private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) { | 1245 protected final CodeExecutableElement createExecuteUninitialized() { |
1290 TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); | 1246 NodeData node = getModel().getNode(); |
1291 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_GENERIC_NAME); | 1247 SpecializationData generic = node.getGenericSpecialization(); |
1292 | 1248 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED); |
1249 addInternalValueParameters(method, generic, true, false); | |
1250 CodeTreeBuilder builder = method.createBuilder(); | |
1251 | |
1252 CodeTreeBuilder createSpecializationCall = builder.create(); | |
1253 createSpecializationCall.startCall(SPECIALIZE); | |
1254 addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null); | |
1255 createSpecializationCall.end(); | |
1256 builder.declaration(baseClassName(node), "newNode", createSpecializationCall); | |
1257 | |
1258 if (generic.isReachable()) { | |
1259 builder.startIf().string("newNode == null").end().startBlock(); | |
1260 | |
1261 builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock(); | |
1262 builder.statement("containsFallback = true"); | |
1263 builder.end(); | |
1264 builder.tree(createGenericInvoke(builder, generic, generic)); | |
1265 builder.end(); | |
1266 builder.startElseBlock(); | |
1267 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); | |
1268 } | |
1269 | |
1270 builder.startReturn(); | |
1271 builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end(); | |
1272 builder.string(".").startCall(EXECUTE_CHAINED); | |
1273 addInternalValueParameterNames(builder, generic, generic, null, true, null); | |
1274 builder.end(); | |
1275 builder.end(); | |
1276 | |
1277 if (generic.isReachable()) { | |
1278 builder.end(); | |
1279 } | |
1280 | |
1281 return method; | |
1282 } | |
1283 | |
1284 private CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) { | |
1285 CodeTreeBuilder builder = parent.create(); | |
1286 builder.startCall(CREATE_INFO).string(reason); | |
1287 addInternalValueParameterNames(builder, specialization, specialization, null, false, null); | |
1288 builder.end(); | |
1289 return builder.getRoot(); | |
1290 } | |
1291 | |
1292 private CodeExecutableElement createMonomorphicRewrite() { | |
1293 NodeData node = getModel().getNode(); | |
1294 | |
1295 SpecializationData generic = node.getGenericSpecialization(); | |
1296 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE); | |
1297 addInternalValueParameters(method, generic, true, false); | |
1298 method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); | |
1299 | |
1300 CodeTreeBuilder builder = method.createBuilder(); | |
1301 | |
1302 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end(); | |
1303 String baseClassName = baseClassName(getModel().getNode()); | |
1304 CodeTreeBuilder createSpecializationCall = builder.create(); | |
1305 createSpecializationCall.startCall(SPECIALIZE); | |
1306 addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null); | |
1307 createSpecializationCall.end(); | |
1308 builder.declaration(baseClassName, "newNode", createSpecializationCall); | |
1309 | |
1310 builder.startIf().string("newNode == null").end().startBlock(); | |
1311 builder.startStatement(); | |
1312 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); | |
1313 builder.string("newNode = ").startNew(uninitializedName).string("this").end(); | |
1314 builder.end(); | |
1315 if (node.isFallbackReachable()) { | |
1316 builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end(); | |
1317 } | |
1318 builder.end(); | |
1319 | |
1320 builder.startStatement(); | |
1321 builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason")); | |
1322 builder.end(); | |
1323 | |
1324 builder.declaration(baseClassName, "returnNode", | |
1325 builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot()); | |
1326 builder.startIf().string("returnNode == null").end().startBlock(); | |
1327 builder.tree(createRewritePolymorphic(builder, node, "this")); | |
1328 builder.end(); | |
1329 | |
1330 builder.startReturn(); | |
1331 builder.startCall("returnNode", EXECUTE_CHAINED); | |
1332 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null); | |
1333 builder.end(); | |
1334 builder.end(); | |
1335 | |
1336 return method; | |
1337 } | |
1338 | |
1339 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) { | |
1340 String polyClassName = nodePolymorphicClassName(node); | |
1341 CodeTreeBuilder builder = parent.create(); | |
1342 | |
1343 builder.startStatement().string("returnNode = "); | |
1344 builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC); | |
1345 builder.string("this"); | |
1346 builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().getRoot()); | |
1347 builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().getRoot()); | |
1348 builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end(); | |
1349 builder.string("newNode"); | |
1350 builder.string("message"); | |
1351 builder.end(); | |
1352 builder.end(); | |
1353 | |
1354 return builder.getRoot(); | |
1355 } | |
1356 | |
1357 private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) { | |
1358 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(Utils.getPackageName(node.getTemplateType()), baseClassName(node)), | |
1359 SPECIALIZE); | |
1293 if (!node.needsFrame(getContext())) { | 1360 if (!node.needsFrame(getContext())) { |
1294 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); | 1361 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); |
1295 } | 1362 } |
1363 | |
1296 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false); | 1364 addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false); |
1297 final CodeTreeBuilder builder = method.createBuilder(); | 1365 final CodeTreeBuilder builder = method.createBuilder(); |
1298 | 1366 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock<SpecializationData>() { |
1299 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() { | |
1300 | 1367 |
1301 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 1368 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
1302 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); | 1369 return createCreateSpecializationMethodBody0(builder, current); |
1303 } | 1370 } |
1304 }, null, false, true, false)); | 1371 }, null, false, true, false, true)); |
1305 | 1372 |
1306 emitUnreachableSpecializations(builder, node); | 1373 emitUnreachableSpecializations(builder, node); |
1307 | 1374 |
1308 return method; | 1375 return method; |
1376 } | |
1377 | |
1378 protected CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current) { | |
1379 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
1380 if (current.isGeneric()) { | |
1381 builder.startReturn().nullLiteral().end(); | |
1382 } else { | |
1383 String className = nodeSpecializationClassName(current); | |
1384 if (!current.getExcludedBy().isEmpty()) { | |
1385 builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded"); | |
1386 builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end(); | |
1387 builder.startBlock(); | |
1388 } | |
1389 | |
1390 if (current.getNode().getGenericSpecialization().isReachable()) { | |
1391 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); | |
1392 } | |
1393 builder.startReturn(); | |
1394 builder.cast(baseClassName(getModel().getNode())); | |
1395 builder.startGroup().startCall(className, FACTORY_METHOD_NAME).string("this"); | |
1396 for (ActualParameter param : current.getSignatureParameters()) { | |
1397 NodeChildData child = param.getSpecification().getExecution().getChild(); | |
1398 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); | |
1399 if (types.size() > 1) { | |
1400 builder.string(implicitTypeName(param)); | |
1401 } | |
1402 } | |
1403 builder.end().end(); | |
1404 builder.end(); | |
1405 | |
1406 if (!current.getExcludedBy().isEmpty()) { | |
1407 builder.end(); | |
1408 } | |
1409 } | |
1410 return builder.getRoot(); | |
1411 | |
1309 } | 1412 } |
1310 | 1413 |
1311 private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { | 1414 private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { |
1312 for (SpecializationData current : node.getSpecializations()) { | 1415 for (SpecializationData current : node.getSpecializations()) { |
1313 if (current.isReachable()) { | 1416 if (current.isReachable()) { |
1315 } | 1418 } |
1316 builder.string("// unreachable ").string(current.getId()).newLine(); | 1419 builder.string("// unreachable ").string(current.getId()).newLine(); |
1317 } | 1420 } |
1318 } | 1421 } |
1319 | 1422 |
1320 protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, | 1423 protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock<SpecializationData> guardedblock, |
1321 final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts) { | 1424 final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) { |
1322 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() { | 1425 return guard(outerParent, source, group, new CodeBlock<Integer>() { |
1323 | 1426 |
1324 public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { | 1427 public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { |
1325 CodeTreeBuilder builder = parent.create(); | 1428 CodeTreeBuilder builder = parent.create(); |
1326 | 1429 |
1327 if (group.getSpecialization() != null) { | 1430 if (group.getSpecialization() != null) { |
1329 | 1432 |
1330 assert group.getChildren().isEmpty() : "missed a specialization"; | 1433 assert group.getChildren().isEmpty() : "missed a specialization"; |
1331 | 1434 |
1332 } else { | 1435 } else { |
1333 for (SpecializationGroup childGroup : group.getChildren()) { | 1436 for (SpecializationGroup childGroup : group.getChildren()) { |
1334 builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions, typedCasts)); | 1437 builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly)); |
1335 } | 1438 } |
1336 } | 1439 } |
1337 | 1440 |
1338 return builder.getRoot(); | 1441 return builder.getRoot(); |
1339 } | 1442 } |
1340 }, elseBlock, forceElse, emitAssumptions, typedCasts); | 1443 }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly); |
1341 } | 1444 } |
1342 | 1445 |
1343 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, | 1446 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, boolean forceElse, |
1344 boolean forceElse, boolean emitAssumptions, boolean typedCasts) { | 1447 boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) { |
1345 CodeTreeBuilder builder = parent.create(); | 1448 CodeTreeBuilder builder = parent.create(); |
1346 | 1449 |
1347 int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions, typedCasts); | 1450 int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly); |
1348 | 1451 |
1349 if (isReachableGroup(group, ifCount, checkMinimumState)) { | 1452 if (isReachableGroup(group, ifCount)) { |
1350 builder.tree(bodyBlock.create(builder, ifCount)); | 1453 builder.tree(bodyBlock.create(builder, ifCount)); |
1351 } | 1454 } |
1352 | 1455 |
1353 builder.end(ifCount); | 1456 builder.end(ifCount); |
1354 | 1457 |
1359 } | 1462 } |
1360 | 1463 |
1361 return builder.getRoot(); | 1464 return builder.getRoot(); |
1362 } | 1465 } |
1363 | 1466 |
1364 private boolean isReachableGroup(SpecializationGroup group, int ifCount, boolean checkMinimumState) { | 1467 private boolean isReachableGroup(SpecializationGroup group, int ifCount) { |
1365 if (ifCount != 0) { | 1468 if (ifCount != 0) { |
1366 return true; | 1469 return true; |
1367 } | 1470 } |
1368 SpecializationGroup previous = group.getPreviousGroup(); | 1471 SpecializationGroup previous = group.getPreviousGroup(); |
1369 if (previous == null || previous.findElseConnectableGuards(checkMinimumState).isEmpty()) { | 1472 if (previous == null || previous.findElseConnectableGuards().isEmpty()) { |
1370 return true; | 1473 return true; |
1371 } | 1474 } |
1372 | 1475 |
1373 /* | 1476 /* |
1374 * Hacky else case. In this case the specialization is not reachable due to previous | 1477 * Hacky else case. In this case the specialization is not reachable due to previous |
1375 * else branch. This is only true if the minimum state is not checked. | 1478 * else branch. This is only true if the minimum state is not checked. |
1376 */ | 1479 */ |
1377 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && !checkMinimumState && | 1480 if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && |
1378 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { | 1481 (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { |
1379 return false; | 1482 return false; |
1380 } | 1483 } |
1381 | 1484 |
1382 return true; | 1485 return true; |
1383 } | 1486 } |
1384 | 1487 |
1385 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions, boolean typedCasts) { | 1488 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) { |
1386 NodeData node = source.getNode(); | 1489 NodeData node = source.getNode(); |
1387 | 1490 |
1388 CodeTreeBuilder guardsBuilder = builder.create(); | 1491 CodeTreeBuilder guardsBuilder = builder.create(); |
1389 CodeTreeBuilder castBuilder = builder.create(); | 1492 CodeTreeBuilder castBuilder = builder.create(); |
1390 CodeTreeBuilder guardsCastBuilder = builder.create(); | 1493 CodeTreeBuilder guardsCastBuilder = builder.create(); |
1391 | 1494 |
1392 String guardsAnd = ""; | 1495 String guardsAnd = ""; |
1393 String guardsCastAnd = ""; | 1496 String guardsCastAnd = ""; |
1394 | |
1395 boolean minimumState = checkMinimumState; | |
1396 if (minimumState) { | |
1397 int groupMaxIndex = group.getUncheckedSpecializationIndex(); | |
1398 | |
1399 if (groupMaxIndex > -1) { | |
1400 guardsBuilder.string(guardsAnd); | |
1401 guardsBuilder.string("minimumState < " + groupMaxIndex); | |
1402 guardsAnd = " && "; | |
1403 } | |
1404 } | |
1405 | 1497 |
1406 if (emitAssumptions) { | 1498 if (emitAssumptions) { |
1407 for (String assumption : group.getAssumptions()) { | 1499 for (String assumption : group.getAssumptions()) { |
1408 guardsBuilder.string(guardsAnd); | 1500 guardsBuilder.string(guardsAnd); |
1409 guardsBuilder.string("this"); | 1501 guardsBuilder.string("this"); |
1434 guardsBuilder.string(guardsAnd); | 1526 guardsBuilder.string(guardsAnd); |
1435 guardsBuilder.tree(implicitGuard); | 1527 guardsBuilder.tree(implicitGuard); |
1436 guardsAnd = " && "; | 1528 guardsAnd = " && "; |
1437 } | 1529 } |
1438 | 1530 |
1439 CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); | 1531 CodeTree implicitGetType = null; |
1440 if (cast != null) { | 1532 if (castForGuardsOnly) { |
1441 castBuilder.tree(cast); | 1533 implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType()); |
1442 } | 1534 } |
1443 } | 1535 |
1444 List<GuardData> elseGuards = group.findElseConnectableGuards(checkMinimumState); | 1536 boolean performCast = true; |
1445 | 1537 if (castForGuardsOnly) { |
1446 for (GuardData guard : group.getGuards()) { | 1538 // if cast for guards we just cast if the type guard is used inside a guard. |
1539 performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard); | |
1540 } | |
1541 | |
1542 if (performCast) { | |
1543 CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts); | |
1544 if (cast != null) { | |
1545 castBuilder.tree(cast); | |
1546 } | |
1547 } | |
1548 if (implicitGetType != null) { | |
1549 castBuilder.tree(implicitGetType); | |
1550 } | |
1551 } | |
1552 List<GuardExpression> elseGuards = group.findElseConnectableGuards(); | |
1553 | |
1554 for (GuardExpression guard : group.getGuards()) { | |
1447 if (elseGuards.contains(guard)) { | 1555 if (elseGuards.contains(guard)) { |
1448 continue; | 1556 continue; |
1449 } | 1557 } |
1450 | 1558 |
1451 if (needsTypeGuard(source, group, guard)) { | 1559 if (needsTypeGuard(source, group, guard)) { |
1461 builder.tree(castBuilder.getRoot()); | 1569 builder.tree(castBuilder.getRoot()); |
1462 ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards); | 1570 ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards); |
1463 return ifCount; | 1571 return ifCount; |
1464 } | 1572 } |
1465 | 1573 |
1466 private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardData> elseGuard) { | 1574 private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardExpression> elseGuard) { |
1467 int newIfCount = ifCount; | 1575 int newIfCount = ifCount; |
1468 | 1576 |
1469 if (!conditionBuilder.isEmpty()) { | 1577 if (!conditionBuilder.isEmpty()) { |
1470 if (ifCount == 0 && !elseGuard.isEmpty()) { | 1578 if (ifCount == 0 && !elseGuard.isEmpty()) { |
1471 builder.startElseIf(); | 1579 builder.startElseIf(); |
1480 newIfCount++; | 1588 newIfCount++; |
1481 } | 1589 } |
1482 return newIfCount; | 1590 return newIfCount; |
1483 } | 1591 } |
1484 | 1592 |
1485 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardData guard) { | 1593 private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) { |
1486 int signatureIndex = 0; | 1594 int signatureIndex = 0; |
1487 for (ActualParameter parameter : guard.getParameters()) { | 1595 for (ActualParameter parameter : guard.getResolvedGuard().getParameters()) { |
1488 if (!parameter.getSpecification().isSignature()) { | 1596 if (!parameter.getSpecification().isSignature()) { |
1489 continue; | 1597 continue; |
1490 } | 1598 } |
1491 | 1599 |
1492 TypeGuard typeGuard = group.findTypeGuard(signatureIndex); | 1600 TypeGuard typeGuard = group.findTypeGuard(signatureIndex); |
1496 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); | 1604 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); |
1497 if (sourceParameter == null) { | 1605 if (sourceParameter == null) { |
1498 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); | 1606 sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); |
1499 } | 1607 } |
1500 | 1608 |
1501 if (Utils.needsCastTo(getContext(), sourceParameter.getType(), requiredType.getPrimitiveType())) { | 1609 if (Utils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) { |
1502 return true; | 1610 return true; |
1503 } | 1611 } |
1504 } | 1612 } |
1505 | 1613 |
1506 signatureIndex++; | 1614 signatureIndex++; |
1513 | 1621 |
1514 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1622 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1515 | 1623 |
1516 TypeData sourceType = source.getTypeSystemType(); | 1624 TypeData sourceType = source.getTypeSystemType(); |
1517 | 1625 |
1518 if (!sourceType.needsCastTo(getContext(), targetType)) { | 1626 if (!sourceType.needsCastTo(targetType)) { |
1519 return null; | 1627 return null; |
1520 } | 1628 } |
1521 | 1629 |
1522 builder.startGroup(); | 1630 builder.startGroup(); |
1523 | 1631 |
1539 } | 1647 } |
1540 } else { | 1648 } else { |
1541 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); | 1649 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); |
1542 } | 1650 } |
1543 | 1651 |
1544 startCallTypeSystemMethod(getContext(), builder, node.getTypeSystem(), castMethodName); | 1652 startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName); |
1545 builder.string(valueName(source)); | 1653 builder.string(valueName(source)); |
1546 if (castTypeName != null) { | 1654 if (castTypeName != null) { |
1547 builder.string(castTypeName); | 1655 builder.string(castTypeName); |
1548 } | 1656 } |
1549 builder.end().end(); // call | 1657 builder.end().end(); // call |
1556 | 1664 |
1557 return builder.getRoot(); | 1665 return builder.getRoot(); |
1558 } | 1666 } |
1559 | 1667 |
1560 // TODO merge redundancies with #createTypeGuard | 1668 // TODO merge redundancies with #createTypeGuard |
1561 private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { | 1669 private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) { |
1562 NodeData node = execution.getChild().getNodeData(); | 1670 NodeData node = execution.getChild().getNodeData(); |
1563 TypeData sourceType = source.getTypeSystemType(); | 1671 TypeData sourceType = source.getTypeSystemType(); |
1564 | 1672 |
1565 if (!sourceType.needsCastTo(getContext(), targetType)) { | 1673 if (!sourceType.needsCastTo(targetType)) { |
1566 return null; | 1674 return null; |
1567 } | 1675 } |
1568 | 1676 |
1569 CodeTree condition = null; | 1677 CodeTree condition = null; |
1570 if (execution.isShortCircuit()) { | 1678 if (execution.isShortCircuit()) { |
1589 args.add(CodeTreeBuilder.singleString(valueName(source))); | 1697 args.add(CodeTreeBuilder.singleString(valueName(source))); |
1590 if (castTypeName != null) { | 1698 if (castTypeName != null) { |
1591 args.add(CodeTreeBuilder.singleString(castTypeName)); | 1699 args.add(CodeTreeBuilder.singleString(castTypeName)); |
1592 } | 1700 } |
1593 | 1701 |
1594 CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, args.toArray(new CodeTree[0])); | 1702 CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0])); |
1595 | 1703 |
1596 CodeTreeBuilder builder = parent.create(); | 1704 CodeTreeBuilder builder = parent.create(); |
1597 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); | 1705 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast)); |
1598 if (checkMinimumState && types.size() > 1) { | 1706 |
1599 CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); | 1707 return builder.getRoot(); |
1708 } | |
1709 | |
1710 private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType) { | |
1711 CodeTree condition = null; | |
1712 if (execution.isShortCircuit()) { | |
1713 ActualParameter shortCircuit = source.getPreviousParameter(); | |
1714 assert shortCircuit != null; | |
1715 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); | |
1716 } | |
1717 | |
1718 CodeTreeBuilder builder = parent.create(); | |
1719 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); | |
1720 if (types.size() > 1) { | |
1721 CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType), | |
1722 CodeTreeBuilder.singleString(valueName(source))); | |
1600 builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); | 1723 builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); |
1601 } | 1724 } |
1602 | |
1603 return builder.getRoot(); | 1725 return builder.getRoot(); |
1604 } | 1726 } |
1605 | 1727 |
1606 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) { | 1728 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) { |
1607 CodeTreeBuilder builder = parent.create(); | 1729 CodeTreeBuilder builder = parent.create(); |
1608 builder.string(prefix); | 1730 builder.string(prefix); |
1609 if (guard.isNegated()) { | 1731 if (guard.isNegated()) { |
1610 builder.string("!"); | 1732 builder.string("!"); |
1611 } | 1733 } |
1612 builder.tree(createTemplateMethodCall(builder, null, source, guard, null)); | 1734 builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null)); |
1613 return builder.getRoot(); | 1735 return builder.getRoot(); |
1614 } | 1736 } |
1615 | 1737 |
1616 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { | 1738 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { |
1617 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1739 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1623 } | 1745 } |
1624 | 1746 |
1625 return encloseThrowsWithFallThrough(current, builder.getRoot()); | 1747 return encloseThrowsWithFallThrough(current, builder.getRoot()); |
1626 } | 1748 } |
1627 | 1749 |
1628 protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNodeVar) { | |
1629 CodeTreeBuilder builder = parent.create(); | |
1630 CodeTreeBuilder prefix = parent.create(); | |
1631 | |
1632 NodeData node = current.getNode(); | |
1633 | |
1634 if (current.isGeneric() && node.isPolymorphic()) { | |
1635 builder.startIf().string(currentNodeVar).string(".next0 == null && minimumState > 0").end().startBlock(); | |
1636 builder.tree(createRewritePolymorphic(builder, node, currentNodeVar)); | |
1637 builder.end(); | |
1638 builder.startElseBlock(); | |
1639 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar)); | |
1640 builder.end(); | |
1641 } else { | |
1642 if (current.getExceptions().isEmpty()) { | |
1643 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null)); | |
1644 } else { | |
1645 builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end(); | |
1646 builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar))); | |
1647 } | |
1648 } | |
1649 CodeTreeBuilder root = parent.create(); | |
1650 root.tree(prefix.getRoot()); | |
1651 root.tree(encloseThrowsWithFallThrough(current, builder.getRoot())); | |
1652 return root.getRoot(); | |
1653 } | |
1654 | |
1655 private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, String currentNode) { | |
1656 NodeData node = current.getNode(); | |
1657 | |
1658 CodeTreeBuilder builder = parent.create(); | |
1659 builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode); | |
1660 builder.startIf().string(currentNode).string(".next0 != null").end().startBlock(); | |
1661 /* | |
1662 * Communicates to the caller of executeAndSpecialize that it was rewritten to generic. | |
1663 * Its important that this is used instead of the currentNode since the caller is this. | |
1664 * CurrentNode may not be this anymore at this place. | |
1665 */ | |
1666 builder.statement("this.next0 = null"); | |
1667 builder.tree(createFindRoot(builder, node, false)); | |
1668 builder.end(); | |
1669 builder.end(); | |
1670 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, "root", "(" + baseClassName(node) + ") root", null), null)); | |
1671 return builder.getRoot(); | |
1672 } | |
1673 | |
1674 protected CodeTree createFindRoot(CodeTreeBuilder parent, NodeData node, boolean countDepth) { | |
1675 CodeTreeBuilder builder = parent.create(); | |
1676 builder.startDoBlock(); | |
1677 builder.startAssert().string("root != null").string(" : ").doubleQuote("No polymorphic parent node.").end(); | |
1678 builder.startStatement().string("root = ").string("root.getParent()").end(); | |
1679 if (countDepth) { | |
1680 builder.statement("depth++"); | |
1681 } | |
1682 builder.end(); | |
1683 builder.startDoWhile(); | |
1684 builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end(); | |
1685 builder.end(); | |
1686 return builder.getRoot(); | |
1687 } | |
1688 | |
1689 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { | 1750 private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { |
1690 if (current.getExceptions().isEmpty()) { | 1751 if (current.getExceptions().isEmpty()) { |
1691 return tree; | 1752 return tree; |
1692 } | 1753 } |
1693 CodeTreeBuilder builder = new CodeTreeBuilder(null); | 1754 CodeTreeBuilder builder = new CodeTreeBuilder(null); |
1694 | 1755 |
1695 builder.startTryBlock(); | 1756 builder.startTryBlock(); |
1696 builder.tree(tree); | 1757 builder.tree(tree); |
1697 for (SpecializationThrowsData exception : current.getExceptions()) { | 1758 for (SpecializationThrowsData exception : current.getExceptions()) { |
1698 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); | 1759 builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); |
1699 builder.string("// fall through").newLine(); | 1760 builder.tree(createDeoptimize(builder)); |
1700 } | 1761 builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null, |
1701 builder.end(); | 1762 "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); |
1702 | 1763 } |
1703 return builder.getRoot(); | |
1704 } | |
1705 | |
1706 protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current, CodeTree replaceCall, CodeTree replaceVar) { | |
1707 assert replaceCall == null || replaceVar == null; | |
1708 CodeTreeBuilder builder = parent.create(); | |
1709 CodeTree replace = replaceVar; | |
1710 if (replace == null) { | |
1711 replace = replaceCall; | |
1712 } | |
1713 if (current.isGeneric()) { | |
1714 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME); | |
1715 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(getContext()), null); | |
1716 builder.end().end(); | |
1717 } else if (current.getMethod() == null) { | |
1718 if (replaceCall != null) { | |
1719 builder.statement(replaceCall); | |
1720 } | |
1721 emitEncounteredSynthetic(builder, current); | |
1722 } else if (!current.canBeAccessedByInstanceOf(getContext(), source.getNode().getNodeType())) { | |
1723 if (replaceCall != null) { | |
1724 builder.statement(replaceCall); | |
1725 } | |
1726 builder.startReturn().tree(createTemplateMethodCall(parent, null, source, current, null)).end(); | |
1727 } else { | |
1728 replace.add(new CodeTree(CodeTreeKind.STRING, null, ".")); | |
1729 builder.startReturn().tree(createTemplateMethodCall(parent, replace, source, current, null)).end(); | |
1730 } | |
1731 return builder.getRoot(); | |
1732 } | |
1733 | |
1734 protected CodeTree createReplaceCall(CodeTreeBuilder builder, SpecializationData current, String target, String source, String message) { | |
1735 String className = nodeSpecializationClassName(current); | |
1736 CodeTreeBuilder replaceCall = builder.create(); | |
1737 if (target != null) { | |
1738 replaceCall.startCall(target, "replace"); | |
1739 } else { | |
1740 replaceCall.startCall("replace"); | |
1741 } | |
1742 replaceCall.startGroup().cast(baseClassName(current.getNode())).startCall(className, CREATE_SPECIALIZATION_NAME).string(source); | |
1743 for (ActualParameter param : current.getSignatureParameters()) { | |
1744 NodeChildData child = param.getSpecification().getExecution().getChild(); | |
1745 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); | |
1746 if (types.size() > 1) { | |
1747 replaceCall.string(implicitTypeName(param)); | |
1748 } | |
1749 } | |
1750 replaceCall.end().end(); | |
1751 | |
1752 if (message == null) { | |
1753 replaceCall.string("message"); | |
1754 } else { | |
1755 replaceCall.doubleQuote(message); | |
1756 } | |
1757 replaceCall.end(); | |
1758 return replaceCall.getRoot(); | |
1759 } | |
1760 | |
1761 private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) { | |
1762 String polyClassName = nodePolymorphicClassName(node); | |
1763 String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); | |
1764 CodeTreeBuilder builder = parent.create(); | |
1765 | |
1766 builder.declaration(getElement().asType(), "currentCopy", currentNode + "." + COPY_WITH_CONSTRUCTOR_NAME + "()"); | |
1767 for (ActualParameter param : getModel().getSignatureParameters()) { | |
1768 NodeExecutionData execution = param.getSpecification().getExecution(); | |
1769 builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end(); | |
1770 } | |
1771 builder.startStatement().string("currentCopy.next0 = ").startNew(uninitializedName).string("currentCopy").end().end(); | |
1772 | |
1773 builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end()); | |
1774 builder.startStatement().string("polymorphic.next0 = ").string("currentCopy").end(); | |
1775 builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end(); | |
1776 | |
1777 builder.startReturn(); | |
1778 builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME); | |
1779 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null); | |
1780 builder.end(); | |
1781 builder.end(); | 1764 builder.end(); |
1782 | 1765 |
1783 return builder.getRoot(); | 1766 return builder.getRoot(); |
1784 } | 1767 } |
1785 | 1768 |
1786 protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { | 1769 protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { |
1787 TypeData type = executable.getType(); | 1770 TypeData type = executable.getType(); |
1788 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1771 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1789 NodeData node = specialization.getNode(); | 1772 NodeData node = specialization.getNode(); |
1790 | 1773 |
1791 ExecutableTypeData castedType = node.findExecutableType(type, 0); | |
1792 TypeData primaryType = castExecutable.getType(); | 1774 TypeData primaryType = castExecutable.getType(); |
1793 | 1775 |
1794 boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); | 1776 boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); |
1795 boolean returnVoid = type.isVoid(); | 1777 boolean returnVoid = type.isVoid(); |
1796 | 1778 |
1807 for (int i = 0; i < executeParameterNames.length; i++) { | 1789 for (int i = 0; i < executeParameterNames.length; i++) { |
1808 executeParameterNames[i] = valueName(executeParameters.get(i)); | 1790 executeParameterNames[i] = valueName(executeParameters.get(i)); |
1809 } | 1791 } |
1810 | 1792 |
1811 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null)); | 1793 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null)); |
1794 boolean hasUnexpected = executable.hasUnexpectedValue(getContext()); | |
1812 | 1795 |
1813 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); | 1796 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); |
1814 if (needsTry) { | 1797 if (needsTry) { |
1815 if (!returnVoid) { | 1798 if (!returnVoid) { |
1816 builder.declaration(primaryType.getPrimitiveType(), "value"); | 1799 builder.declaration(primaryType.getPrimitiveType(), "value"); |
1829 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); | 1812 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); |
1830 if (returnVoid) { | 1813 if (returnVoid) { |
1831 builder.string("// ignore").newLine(); | 1814 builder.string("// ignore").newLine(); |
1832 } else { | 1815 } else { |
1833 builder.startReturn(); | 1816 builder.startReturn(); |
1834 builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()"))); | 1817 builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(), |
1818 CodeTreeBuilder.singleString("ex.getResult()"))); | |
1835 builder.end(); | 1819 builder.end(); |
1836 } | 1820 } |
1837 builder.end(); | 1821 builder.end(); |
1838 | 1822 |
1839 if (!returnVoid) { | 1823 if (!returnVoid) { |
1840 builder.startReturn(); | 1824 builder.startReturn(); |
1841 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value"))); | 1825 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value"))); |
1842 builder.end(); | 1826 builder.end(); |
1843 } | 1827 } |
1844 } else { | 1828 } else { |
1845 if (returnVoid) { | 1829 if (returnVoid) { |
1846 builder.statement(primaryExecuteCall); | 1830 builder.statement(primaryExecuteCall); |
1847 } else { | 1831 } else { |
1848 builder.startReturn(); | 1832 builder.startReturn(); |
1849 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall)); | 1833 builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall)); |
1850 builder.end(); | 1834 builder.end(); |
1851 } | 1835 } |
1852 } | 1836 } |
1853 | 1837 |
1854 return builder.getRoot(); | 1838 return builder.getRoot(); |
1855 } | 1839 } |
1856 | 1840 |
1857 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { | 1841 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) { |
1858 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); | 1842 return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value); |
1859 return createCastType(node.getTypeSystem(), sourceType, castedType.getType(), hasUnexpected, value); | |
1860 } | 1843 } |
1861 | 1844 |
1862 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, | 1845 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, |
1863 ActualParameter unexpectedParameter) { | 1846 ActualParameter unexpectedParameter) { |
1864 CodeTreeBuilder builder = parent.create(); | 1847 CodeTreeBuilder builder = parent.create(); |
1909 } | 1892 } |
1910 elseIf = builder.startIf(elseIf); | 1893 elseIf = builder.startIf(elseIf); |
1911 | 1894 |
1912 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); | 1895 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); |
1913 TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; | 1896 TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; |
1914 builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); | 1897 builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); |
1915 builder.end().startBlock(); | 1898 builder.end().startBlock(); |
1916 builder.startStatement(); | 1899 builder.startStatement(); |
1917 builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); | 1900 builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); |
1918 builder.end(); | 1901 builder.end(); |
1919 builder.end(); | 1902 builder.end(); |
2119 private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { | 2102 private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { |
2120 if (cast == null) { | 2103 if (cast == null) { |
2121 return expression; | 2104 return expression; |
2122 } | 2105 } |
2123 CodeTreeBuilder builder = parent.create(); | 2106 CodeTreeBuilder builder = parent.create(); |
2124 startCallTypeSystemMethod(getContext(), builder, typeSystem, cast.getMethodName()); | 2107 startCallTypeSystemMethod(builder, typeSystem, cast.getMethodName()); |
2125 builder.tree(expression); | 2108 builder.tree(expression); |
2126 builder.end().end(); | 2109 builder.end().end(); |
2127 return builder.getRoot(); | 2110 return builder.getRoot(); |
2128 } | 2111 } |
2129 | 2112 |
2176 sourceType = targetExecutable.getType(); | 2159 sourceType = targetExecutable.getType(); |
2177 } | 2160 } |
2178 | 2161 |
2179 ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); | 2162 ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); |
2180 if (cast != null) { | 2163 if (cast != null) { |
2181 if (cast.getSourceType().needsCastTo(getContext(), targetType)) { | 2164 if (cast.getSourceType().needsCastTo(targetType)) { |
2182 return true; | 2165 return true; |
2183 } | 2166 } |
2184 } | 2167 } |
2185 | 2168 |
2186 if (sourceType.needsCastTo(getContext(), targetType)) { | 2169 if (sourceType.needsCastTo(targetType)) { |
2187 return true; | 2170 return true; |
2188 } | 2171 } |
2189 } | 2172 } |
2190 return false; | 2173 return false; |
2191 } | 2174 } |
2217 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); | 2200 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); |
2218 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); | 2201 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); |
2219 if (specialization.isPolymorphic()) { | 2202 if (specialization.isPolymorphic()) { |
2220 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); | 2203 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); |
2221 } else { | 2204 } else { |
2222 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, | 2205 builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param, |
2223 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); | 2206 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); |
2224 } | 2207 } |
2225 builder.end(); // catch block | 2208 builder.end(); // catch block |
2226 | 2209 |
2227 return builder.getRoot(); | 2210 return builder.getRoot(); |
2230 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { | 2213 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { |
2231 NodeData node = specialization.getNode(); | 2214 NodeData node = specialization.getNode(); |
2232 SpecializationData polymorphic = node.getPolymorphicSpecialization(); | 2215 SpecializationData polymorphic = node.getPolymorphicSpecialization(); |
2233 | 2216 |
2234 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2217 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2235 builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); | 2218 builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); |
2236 | 2219 |
2237 builder.startReturn(); | 2220 builder.startReturn(); |
2238 | 2221 |
2239 CodeTreeBuilder execute = new CodeTreeBuilder(builder); | 2222 CodeTreeBuilder execute = new CodeTreeBuilder(builder); |
2240 execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME); | 2223 execute.startCall("next0", EXECUTE_CHAINED); |
2241 addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null); | 2224 addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null); |
2242 execute.end(); | 2225 execute.end(); |
2243 | 2226 |
2244 TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); | 2227 TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); |
2245 | 2228 |
2246 builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); | 2229 builder.tree(createExpectExecutableType(node, sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.getRoot())); |
2247 | 2230 |
2248 builder.end(); | 2231 builder.end(); |
2249 return builder.getRoot(); | 2232 return builder.getRoot(); |
2250 } | 2233 } |
2251 | 2234 |
2288 sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); | 2271 sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); |
2289 } | 2272 } |
2290 | 2273 |
2291 CodeTree value = CodeTreeBuilder.singleString(localName); | 2274 CodeTree value = CodeTreeBuilder.singleString(localName); |
2292 | 2275 |
2293 if (sourceType.needsCastTo(getContext(), targetType)) { | 2276 if (sourceType.needsCastTo(targetType)) { |
2294 value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); | 2277 value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); |
2295 } | 2278 } |
2296 builder.tree(value); | 2279 builder.tree(value); |
2297 } else { | 2280 } else { |
2298 builder.defaultValue(parameter.getType()); | 2281 builder.defaultValue(parameter.getType()); |
2299 } | 2282 } |
2348 builder.end(); // statement | 2331 builder.end(); // statement |
2349 | 2332 |
2350 return builder.getRoot(); | 2333 return builder.getRoot(); |
2351 } | 2334 } |
2352 | 2335 |
2353 protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData current, ActualParameter exceptionParam, String reason) { | 2336 protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, ActualParameter exceptionParam, String reason) { |
2354 NodeData node = current.getNode(); | 2337 NodeData node = current.getNode(); |
2355 SpecializationData generic = node.getGenericSpecialization(); | 2338 SpecializationData generic = node.getGenericSpecialization(); |
2356 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); | 2339 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); |
2357 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); | 2340 specializeCall.startCall(REWRITE); |
2358 specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current))); | |
2359 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null); | 2341 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null); |
2360 specializeCall.doubleQuote(reason); | 2342 specializeCall.doubleQuote(reason); |
2361 specializeCall.end().end(); | 2343 specializeCall.end().end(); |
2362 | 2344 |
2363 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2345 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2364 | 2346 |
2365 builder.startReturn(); | 2347 builder.startReturn(); |
2366 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); | 2348 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.getRoot())); |
2367 builder.end(); | 2349 builder.end(); |
2368 | 2350 |
2369 return builder.getRoot(); | 2351 return builder.getRoot(); |
2370 } | 2352 } |
2371 | 2353 |
2372 protected final CodeExecutableElement createUpdateTypes(TypeMirror polymorphicType) { | |
2373 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), UPDATE_TYPES_NAME); | |
2374 method.getParameters().add(new CodeVariableElement(polymorphicType, "polymorphic")); | |
2375 CodeTreeBuilder builder = method.createBuilder(); | |
2376 | |
2377 if (getModel().isPolymorphic()) { | |
2378 builder.startStatement(); | |
2379 builder.startCall("next0", "updateTypes").string("polymorphic").end(); | |
2380 builder.end(); | |
2381 } else if (getModel().isSpecialized()) { | |
2382 for (ActualParameter parameter : getModel().getParameters()) { | |
2383 if (!parameter.getSpecification().isSignature()) { | |
2384 continue; | |
2385 } | |
2386 if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { | |
2387 continue; | |
2388 } | |
2389 builder.startStatement(); | |
2390 builder.startCall("polymorphic", createUpdateTypeName(parameter)); | |
2391 builder.typeLiteral(parameter.getType()); | |
2392 builder.end().end(); | |
2393 } | |
2394 | |
2395 builder.startStatement().startCall("super", UPDATE_TYPES_NAME).string("polymorphic").end().end(); | |
2396 } | |
2397 return method; | |
2398 } | |
2399 | |
2400 protected String createUpdateTypeName(ActualParameter parameter) { | |
2401 return "update" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; | |
2402 } | |
2403 } | 2354 } |
2404 | 2355 |
2405 private class PolymorphicNodeFactory extends SpecializedNodeFactory { | 2356 private class PolymorphicNodeFactory extends SpecializedNodeFactory { |
2406 | 2357 |
2407 public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { | 2358 public PolymorphicNodeFactory(CodeTypeElement nodeGen) { |
2408 super(context, nodeGen); | 2359 super(nodeGen); |
2409 } | 2360 } |
2410 | 2361 |
2411 @Override | 2362 @Override |
2412 public CodeTypeElement create(SpecializationData polymorph) { | 2363 public CodeTypeElement create(SpecializationData polymorph) { |
2413 NodeData node = polymorph.getNode(); | 2364 NodeData node = polymorph.getNode(); |
2430 } | 2381 } |
2431 ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); | 2382 ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); |
2432 assert parameter != null; | 2383 assert parameter != null; |
2433 types.add(parameter.getTypeSystemType()); | 2384 types.add(parameter.getTypeSystemType()); |
2434 } | 2385 } |
2435 CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), polymorphicTypeName(polymorphParameter)); | 2386 |
2387 } | |
2388 | |
2389 for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) { | |
2390 String fieldName = polymorphicTypeName(execution); | |
2391 CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName); | |
2436 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); | 2392 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); |
2437 clazz.add(var); | 2393 clazz.add(var); |
2438 } | 2394 } |
2439 | 2395 |
2440 return clazz; | 2396 return clazz; |
2445 CodeTypeElement clazz = getElement(); | 2401 CodeTypeElement clazz = getElement(); |
2446 | 2402 |
2447 createConstructors(clazz); | 2403 createConstructors(clazz); |
2448 createExecuteMethods(specialization); | 2404 createExecuteMethods(specialization); |
2449 | 2405 |
2450 getElement().add(createUpdateTypes(nodeGen.asType())); | 2406 clazz.add(createUpdateTypes0()); |
2451 | |
2452 for (ActualParameter parameter : specialization.getParameters()) { | |
2453 if (!parameter.getSpecification().isSignature()) { | |
2454 continue; | |
2455 } | |
2456 if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { | |
2457 continue; | |
2458 } | |
2459 getElement().add(createUpdateType(parameter)); | |
2460 } | |
2461 | |
2462 if (needsInvokeCopyConstructorMethod()) { | |
2463 clazz.add(createCopy(nodeGen.asType(), specialization)); | |
2464 } | |
2465 | |
2466 createCachedExecuteMethods(specialization); | 2407 createCachedExecuteMethods(specialization); |
2467 } | 2408 } |
2468 | 2409 |
2469 private ExecutableElement createUpdateType(ActualParameter parameter) { | |
2470 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), createUpdateTypeName(parameter)); | |
2471 method.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), "type")); | |
2472 CodeTreeBuilder builder = method.createBuilder(); | |
2473 | |
2474 String fieldName = polymorphicTypeName(parameter); | |
2475 builder.startIf().string(fieldName).isNull().end().startBlock(); | |
2476 builder.startStatement().string(fieldName).string(" = ").string("type").end(); | |
2477 builder.end(); | |
2478 builder.startElseIf().string(fieldName).string(" != ").string("type").end(); | |
2479 builder.startBlock(); | |
2480 builder.startStatement().string(fieldName).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); | |
2481 builder.end(); | |
2482 | |
2483 return method; | |
2484 } | |
2485 | |
2486 } | 2410 } |
2487 | 2411 |
2488 private class SpecializedNodeFactory extends NodeBaseFactory { | 2412 private class SpecializedNodeFactory extends NodeBaseFactory { |
2489 | 2413 |
2490 protected final CodeTypeElement nodeGen; | 2414 protected final CodeTypeElement nodeGen; |
2491 | 2415 |
2492 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { | 2416 public SpecializedNodeFactory(CodeTypeElement nodeGen) { |
2493 super(context); | |
2494 this.nodeGen = nodeGen; | 2417 this.nodeGen = nodeGen; |
2495 } | 2418 } |
2496 | 2419 |
2497 @Override | 2420 @Override |
2498 public CodeTypeElement create(SpecializationData specialization) { | 2421 public CodeTypeElement create(SpecializationData specialization) { |
2500 TypeMirror baseType = node.getNodeType(); | 2423 TypeMirror baseType = node.getNodeType(); |
2501 if (nodeGen != null) { | 2424 if (nodeGen != null) { |
2502 baseType = nodeGen.asType(); | 2425 baseType = nodeGen.asType(); |
2503 } | 2426 } |
2504 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); | 2427 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); |
2428 | |
2429 if (specialization.isSpecialized() || specialization.isUninitialized()) { | |
2430 clazz.add(createGetMetadata0(false)); | |
2431 clazz.add(createMetadataLiteral()); | |
2432 } | |
2505 | 2433 |
2506 NodeCost cost; | 2434 NodeCost cost; |
2507 if (specialization.isGeneric()) { | 2435 if (specialization.isGeneric()) { |
2508 cost = NodeCost.MEGAMORPHIC; | 2436 cost = NodeCost.MEGAMORPHIC; |
2509 } else if (specialization.isUninitialized()) { | 2437 } else if (specialization.isUninitialized()) { |
2515 } else { | 2443 } else { |
2516 throw new AssertionError(); | 2444 throw new AssertionError(); |
2517 } | 2445 } |
2518 clazz.getAnnotationMirrors().add(createNodeInfo(node, cost)); | 2446 clazz.getAnnotationMirrors().add(createNodeInfo(node, cost)); |
2519 | 2447 |
2448 if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) { | |
2449 clazz.add(createUninitializedGetCostOverride()); | |
2450 } | |
2451 | |
2520 return clazz; | 2452 return clazz; |
2453 } | |
2454 | |
2455 private Element createUninitializedGetCostOverride() { | |
2456 TypeMirror returnType = context.getTruffleTypes().getNodeCost(); | |
2457 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost"); | |
2458 CodeTreeBuilder builder = method.createBuilder(); | |
2459 builder.startIf().string(CONTAINS_FALLBACK).end().startBlock(); | |
2460 builder.startReturn().staticReference(returnType, "MONOMORPHIC").end(); | |
2461 builder.end(); | |
2462 builder.startReturn().string("super.getCost()").end(); | |
2463 return method; | |
2464 } | |
2465 | |
2466 private CodeVariableElement createMetadataLiteral() { | |
2467 CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME); | |
2468 | |
2469 CodeTreeBuilder builder = includes.createInitBuilder(); | |
2470 | |
2471 SpecializationData specialization = getModel(); | |
2472 NodeData node = specialization.getNode(); | |
2473 | |
2474 Set<SpecializationData> contains = specialization.getContains(); | |
2475 if (specialization.isUninitialized()) { | |
2476 contains = new HashSet<>(); | |
2477 | |
2478 SpecializationData polymorphic = node.getPolymorphicSpecialization(); | |
2479 if (polymorphic != null) { | |
2480 contains.addAll(polymorphic.getContains()); | |
2481 } | |
2482 SpecializationData generic = node.getGenericSpecialization(); | |
2483 if (generic != null) { | |
2484 contains.addAll(generic.getContains()); | |
2485 } | |
2486 } | |
2487 | |
2488 builder.startNew(context.getTruffleTypes().getDslMetadata()); | |
2489 builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end(); | |
2490 builder.tree(createSpecializationListLiteral(builder, contains)); | |
2491 builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy())); | |
2492 builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel()))); | |
2493 builder.string("0").string("0"); | |
2494 builder.end(); | |
2495 return includes; | |
2496 } | |
2497 | |
2498 private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List<TypeMirror> list) { | |
2499 ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); | |
2500 CodeTreeBuilder builder = parent.create(); | |
2501 | |
2502 if (list.isEmpty()) { | |
2503 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); | |
2504 } else { | |
2505 builder.startNewArray(classArray, null); | |
2506 for (TypeMirror type : list) { | |
2507 builder.typeLiteral(type); | |
2508 } | |
2509 builder.end(); | |
2510 } | |
2511 | |
2512 return builder.getRoot(); | |
2513 } | |
2514 | |
2515 private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set<SpecializationData> list) { | |
2516 ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); | |
2517 CodeTreeBuilder builder = parent.create(); | |
2518 | |
2519 if (list.isEmpty()) { | |
2520 builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); | |
2521 } else { | |
2522 builder.startNewArray(classArray, null); | |
2523 for (SpecializationData specialization : list) { | |
2524 if (specialization.isGeneric() || specialization.isPolymorphic()) { | |
2525 specialization = getModel().getNode().getUninitializedSpecialization(); | |
2526 } | |
2527 builder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); | |
2528 } | |
2529 builder.end(); | |
2530 } | |
2531 | |
2532 return builder.getRoot(); | |
2521 } | 2533 } |
2522 | 2534 |
2523 protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) { | 2535 protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) { |
2524 String shortName = node.getShortName(); | 2536 String shortName = node.getShortName(); |
2525 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); | 2537 CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); |
2539 CodeTypeElement clazz = getElement(); | 2551 CodeTypeElement clazz = getElement(); |
2540 createConstructors(clazz); | 2552 createConstructors(clazz); |
2541 | 2553 |
2542 createExecuteMethods(specialization); | 2554 createExecuteMethods(specialization); |
2543 createCachedExecuteMethods(specialization); | 2555 createCachedExecuteMethods(specialization); |
2544 if (specialization.getNode().isPolymorphic()) { | 2556 |
2545 getElement().add(createUpdateTypes(nodeGen.asType())); | 2557 if (specialization.isUninitialized()) { |
2546 } | 2558 if (specialization.getNode().isFallbackReachable()) { |
2547 if (needsInvokeCopyConstructorMethod()) { | 2559 CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK); |
2548 clazz.add(createCopy(nodeGen.asType(), specialization)); | 2560 var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal())); |
2561 clazz.add(var); | |
2562 } | |
2563 clazz.add(createExecuteUninitialized()); | |
2549 } | 2564 } |
2550 | 2565 |
2551 if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) { | 2566 if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) { |
2552 clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization)); | 2567 clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization)); |
2553 } else { | 2568 } else { |
2566 SpecializationData specialization = getModel(); | 2581 SpecializationData specialization = getModel(); |
2567 NodeData node = specialization.getNode(); | 2582 NodeData node = specialization.getNode(); |
2568 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { | 2583 for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { |
2569 if (specialization.isUninitialized()) { | 2584 if (specialization.isUninitialized()) { |
2570 // ignore copy constructors for uninitialized if not polymorphic | 2585 // ignore copy constructors for uninitialized if not polymorphic |
2571 if (isCopyConstructor(constructor) && !node.isPolymorphic()) { | 2586 if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) { |
2572 continue; | 2587 continue; |
2573 } | 2588 } |
2574 } else if (node.getUninitializedSpecialization() != null) { | 2589 } else if (node.getUninitializedSpecialization() != null) { |
2575 // ignore others than copy constructors for specialized nodes | 2590 // ignore others than copy constructors for specialized nodes |
2576 if (!isCopyConstructor(constructor)) { | 2591 if (!isCopyConstructor(constructor)) { |
2584 } | 2599 } |
2585 CodeTree body = superConstructor.getBodyTree(); | 2600 CodeTree body = superConstructor.getBodyTree(); |
2586 CodeTreeBuilder builder = superConstructor.createBuilder(); | 2601 CodeTreeBuilder builder = superConstructor.createBuilder(); |
2587 builder.tree(body); | 2602 builder.tree(body); |
2588 | 2603 |
2589 if (node.isPolymorphic()) { | |
2590 if (specialization.isSpecialized() || specialization.isPolymorphic()) { | |
2591 builder.statement("this.next0 = copy.next0"); | |
2592 } | |
2593 } | |
2594 if (superConstructor != null) { | 2604 if (superConstructor != null) { |
2595 for (ActualParameter param : getImplicitTypeParameters(getModel())) { | 2605 for (ActualParameter param : getImplicitTypeParameters(getModel())) { |
2596 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); | 2606 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); |
2597 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); | 2607 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); |
2598 | 2608 |
2626 } | 2636 } |
2627 } | 2637 } |
2628 | 2638 |
2629 protected void createCachedExecuteMethods(SpecializationData specialization) { | 2639 protected void createCachedExecuteMethods(SpecializationData specialization) { |
2630 NodeData node = specialization.getNode(); | 2640 NodeData node = specialization.getNode(); |
2631 if (!node.isPolymorphic()) { | 2641 if (!node.isPolymorphic(context)) { |
2632 return; | 2642 return; |
2633 } | 2643 } |
2634 | 2644 |
2635 CodeTypeElement clazz = getElement(); | 2645 CodeTypeElement clazz = getElement(); |
2636 | 2646 |
2637 final SpecializationData polymorphic = node.getPolymorphicSpecialization(); | 2647 final SpecializationData polymorphic = node.getPolymorphicSpecialization(); |
2638 ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME); | 2648 ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED); |
2639 CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached); | 2649 CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached); |
2640 executeMethod.getModifiers().remove(Modifier.ABSTRACT); | 2650 executeMethod.getModifiers().remove(Modifier.ABSTRACT); |
2641 CodeTreeBuilder builder = executeMethod.createBuilder(); | 2651 CodeTreeBuilder builder = executeMethod.createBuilder(); |
2642 | 2652 |
2643 if (specialization.isGeneric() || specialization.isPolymorphic()) { | 2653 if (specialization.isPolymorphic()) { |
2644 builder.startThrow().startNew(getContext().getType(AssertionError.class)); | 2654 builder.startReturn().startCall("this.next0", EXECUTE_CHAINED); |
2645 builder.doubleQuote("Should not be reached."); | 2655 addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null); |
2646 builder.end().end(); | 2656 builder.end().end(); |
2647 } else if (specialization.isUninitialized()) { | 2657 } else if (specialization.isUninitialized()) { |
2648 builder.tree(createAppendPolymorphic(builder, specialization)); | 2658 if (node.getGenericSpecialization().isReachable()) { |
2659 builder.startIf().string("!containsFallback").end().startBlock(); | |
2660 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); | |
2661 builder.end(); | |
2662 } else { | |
2663 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); | |
2664 } | |
2665 builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED); | |
2666 addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null); | |
2667 builder.end().end(); | |
2649 } else { | 2668 } else { |
2650 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); | 2669 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); |
2651 elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME); | 2670 elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED); |
2652 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null); | 2671 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null); |
2653 elseBuilder.end().end(); | 2672 elseBuilder.end().end(); |
2654 | 2673 |
2655 boolean forceElse = specialization.getExceptions().size() > 0; | 2674 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() { |
2656 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { | |
2657 | 2675 |
2658 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 2676 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
2659 return createGenericInvoke(b, polymorphic, current); | 2677 return createGenericInvoke(b, polymorphic, current); |
2660 } | 2678 } |
2661 }, elseBuilder.getRoot(), forceElse, true, true)); | 2679 }, elseBuilder.getRoot(), false, true, true, false)); |
2662 } | 2680 } |
2663 clazz.add(executeMethod); | 2681 clazz.add(executeMethod); |
2664 } | |
2665 | |
2666 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { | |
2667 NodeData node = specialization.getNode(); | |
2668 | |
2669 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | |
2670 builder.tree(createDeoptimize(builder)); | |
2671 | |
2672 builder.declaration(getContext().getTruffleTypes().getNode(), "root", "this"); | |
2673 builder.declaration(getContext().getType(int.class), "depth", "0"); | |
2674 builder.tree(createFindRoot(builder, node, true)); | |
2675 builder.newLine(); | |
2676 | |
2677 builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end(); | |
2678 builder.startBlock(); | |
2679 String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"; | |
2680 String castRoot = "(" + baseClassName(node) + ") root"; | |
2681 builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(), | |
2682 createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null)); | |
2683 builder.end(); | |
2684 | |
2685 builder.startElseBlock(); | |
2686 builder.startStatement().string("next0 = "); | |
2687 builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); | |
2688 builder.end(); | |
2689 | |
2690 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); | |
2691 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); | |
2692 specializeCall.string("0"); | |
2693 addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, null); | |
2694 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); | |
2695 specializeCall.end().end(); | |
2696 | |
2697 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); | |
2698 | |
2699 CodeTree root = builder.create().cast(nodePolymorphicClassName(node)).string("root").getRoot(); | |
2700 builder.startIf().string("this.next0 != null").end().startBlock(); | |
2701 builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end(); | |
2702 builder.end(); | |
2703 | |
2704 if (Utils.isVoid(builder.findMethod().getReturnType())) { | |
2705 builder.returnStatement(); | |
2706 } else { | |
2707 builder.startReturn().string("result").end(); | |
2708 } | |
2709 | |
2710 builder.end(); | |
2711 | |
2712 return builder.getRoot(); | |
2713 } | 2682 } |
2714 | 2683 |
2715 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { | 2684 private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { |
2716 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2685 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2717 | 2686 |
2729 return builder.getRoot(); | 2698 return builder.getRoot(); |
2730 } | 2699 } |
2731 | 2700 |
2732 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { | 2701 private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { |
2733 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); | 2702 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); |
2703 | |
2704 method.getAnnotationMirrors().clear(); | |
2705 for (VariableElement variable : method.getParameters()) { | |
2706 variable.getAnnotationMirrors().clear(); | |
2707 } | |
2734 | 2708 |
2735 CodeTreeBuilder builder = method.createBuilder(); | 2709 CodeTreeBuilder builder = method.createBuilder(); |
2736 int i = 0; | 2710 int i = 0; |
2737 int signatureIndex = -1; | 2711 int signatureIndex = -1; |
2738 for (VariableElement param : method.getParameters()) { | 2712 for (VariableElement param : method.getParameters()) { |
2838 CodeTree returnSpecialized = null; | 2812 CodeTree returnSpecialized = null; |
2839 | 2813 |
2840 if (specialization.findNextSpecialization() != null) { | 2814 if (specialization.findNextSpecialization() != null) { |
2841 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); | 2815 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); |
2842 returnBuilder.tree(createDeoptimize(builder)); | 2816 returnBuilder.tree(createDeoptimize(builder)); |
2843 returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, specialization, null, "One of guards " + specialization.getGuardDefinitions() + " failed")); | 2817 returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, |
2818 "One of guards " + specialization.getGuards() + " failed")); | |
2844 returnSpecialized = returnBuilder.getRoot(); | 2819 returnSpecialized = returnBuilder.getRoot(); |
2845 } | 2820 } |
2846 | 2821 |
2847 builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { | 2822 builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() { |
2848 | 2823 |
2849 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 2824 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
2850 return createExecute(b, executable, specialization); | 2825 return createExecute(b, executable, specialization); |
2851 } | 2826 } |
2852 }, returnSpecialized, false, false, false)); | 2827 }, returnSpecialized, false, false, false, false)); |
2853 | 2828 |
2854 return builder.getRoot(); | 2829 return builder.getRoot(); |
2855 } | 2830 } |
2856 | 2831 |
2857 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { | 2832 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { |
2867 builder.end(); | 2842 builder.end(); |
2868 } | 2843 } |
2869 | 2844 |
2870 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); | 2845 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); |
2871 if (specialization.isPolymorphic()) { | 2846 if (specialization.isPolymorphic()) { |
2872 returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME); | 2847 returnBuilder.startCall("next0", EXECUTE_CHAINED); |
2873 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); | 2848 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); |
2874 returnBuilder.end(); | 2849 returnBuilder.end(); |
2875 } else if (specialization.isUninitialized()) { | 2850 } else if (specialization.isUninitialized()) { |
2876 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); | 2851 returnBuilder.startCall(EXECUTE_UNINITIALIZED); |
2877 returnBuilder.string("0"); | |
2878 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); | 2852 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null); |
2879 returnBuilder.doubleQuote("Uninitialized monomorphic"); | |
2880 returnBuilder.end(); | 2853 returnBuilder.end(); |
2881 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { | 2854 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { |
2882 emitEncounteredSynthetic(builder, specialization); | 2855 emitEncounteredSynthetic(builder, specialization); |
2883 } else if (specialization.isGeneric()) { | |
2884 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME); | |
2885 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(getContext()), null); | |
2886 returnBuilder.end(); | |
2887 } else { | 2856 } else { |
2888 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); | 2857 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); |
2889 } | 2858 } |
2890 | 2859 |
2891 if (!returnBuilder.isEmpty()) { | 2860 if (!returnBuilder.isEmpty()) { |
2893 TypeData sourceType = specialization.getReturnType().getTypeSystemType(); | 2862 TypeData sourceType = specialization.getReturnType().getTypeSystemType(); |
2894 | 2863 |
2895 builder.startReturn(); | 2864 builder.startReturn(); |
2896 if (targetType == null || sourceType == null) { | 2865 if (targetType == null || sourceType == null) { |
2897 builder.tree(returnBuilder.getRoot()); | 2866 builder.tree(returnBuilder.getRoot()); |
2898 } else if (sourceType.needsCastTo(getContext(), targetType)) { | 2867 } else if (sourceType.needsCastTo(targetType)) { |
2899 String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); | 2868 String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); |
2900 if (!executable.hasUnexpectedValue(context)) { | 2869 if (!executable.hasUnexpectedValue(context)) { |
2901 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); | 2870 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); |
2902 } | 2871 } |
2903 builder.tree(createCallTypeSystemMethod(context, parent, node, castMethodName, returnBuilder.getRoot())); | 2872 builder.tree(createCallTypeSystemMethod(parent, node, castMethodName, returnBuilder.getRoot())); |
2904 } else { | 2873 } else { |
2905 builder.tree(returnBuilder.getRoot()); | 2874 builder.tree(returnBuilder.getRoot()); |
2906 } | 2875 } |
2907 builder.end(); | 2876 builder.end(); |
2908 } | 2877 } |
2909 | 2878 |
2910 if (!specialization.getExceptions().isEmpty()) { | 2879 if (!specialization.getExceptions().isEmpty()) { |
2911 for (SpecializationThrowsData exception : specialization.getExceptions()) { | 2880 for (SpecializationThrowsData exception : specialization.getExceptions()) { |
2912 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); | 2881 builder.end().startCatchBlock(exception.getJavaClass(), "ex"); |
2913 builder.tree(createDeoptimize(builder)); | 2882 builder.tree(createDeoptimize(builder)); |
2914 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); | 2883 builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, |
2884 "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); | |
2915 } | 2885 } |
2916 builder.end(); | 2886 builder.end(); |
2917 } | 2887 } |
2918 if (!specialization.getAssumptions().isEmpty()) { | 2888 if (!specialization.getAssumptions().isEmpty()) { |
2919 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); | 2889 builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); |
2920 builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization, null, "Assumption failed")); | 2890 builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed")); |
2921 builder.end(); | 2891 builder.end(); |
2922 } | 2892 } |
2923 | 2893 |
2924 return builder.getRoot(); | 2894 return builder.getRoot(); |
2925 } | 2895 } |
2926 | 2896 |
2927 protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) { | 2897 protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) { |
2928 List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization); | 2898 List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization); |
2929 CodeVariableElement[] parameters = new CodeVariableElement[implicitTypeParams.size() + 1]; | |
2930 int i = 0; | |
2931 String baseName = "current"; | 2899 String baseName = "current"; |
2932 parameters[i++] = new CodeVariableElement(specialization.getNode().getNodeType(), baseName); | 2900 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME); |
2901 method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName)); | |
2933 for (ActualParameter implicitTypeParam : implicitTypeParams) { | 2902 for (ActualParameter implicitTypeParam : implicitTypeParams) { |
2934 parameters[i++] = new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)); | 2903 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam))); |
2935 } | 2904 } |
2936 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, parameters); | |
2937 CodeTreeBuilder builder = method.createBuilder(); | 2905 CodeTreeBuilder builder = method.createBuilder(); |
2938 builder.startReturn(); | 2906 builder.startReturn(); |
2939 builder.startNew(getElement().asType()); | 2907 builder.startNew(getElement().asType()); |
2940 builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end(); | 2908 builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end(); |
2941 for (ActualParameter param : implicitTypeParams) { | 2909 for (ActualParameter param : implicitTypeParams) { |
2945 return method; | 2913 return method; |
2946 } | 2914 } |
2947 | 2915 |
2948 protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) { | 2916 protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) { |
2949 List<? extends VariableElement> parameters = constructor.getParameters(); | 2917 List<? extends VariableElement> parameters = constructor.getParameters(); |
2950 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, | 2918 CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME, |
2951 parameters.toArray(new CodeVariableElement[parameters.size()])); | 2919 parameters.toArray(new CodeVariableElement[parameters.size()])); |
2952 CodeTreeBuilder builder = method.createBuilder(); | 2920 CodeTreeBuilder builder = method.createBuilder(); |
2953 builder.startReturn(); | 2921 builder.startReturn(); |
2954 builder.startNew(getElement().asType()); | 2922 builder.startNew(getElement().asType()); |
2955 for (VariableElement param : parameters) { | 2923 for (VariableElement param : parameters) { |