Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9327001: Implement super initializers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/leg/resolver.dart ('k') | frog/leg/ssa/closure.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 } 121 }
122 new HTracer.singleton().traceCompilation(name); 122 new HTracer.singleton().traceCompilation(name);
123 new HTracer.singleton().traceGraph('builder', graph); 123 new HTracer.singleton().traceGraph('builder', graph);
124 } 124 }
125 return graph; 125 return graph;
126 }); 126 });
127 } 127 }
128 128
129 HGraph compileConstructor(SsaBuilder builder, WorkItem work) { 129 HGraph compileConstructor(SsaBuilder builder, WorkItem work) {
130 // The body of the constructor will be generated in a separate function. 130 // The body of the constructor will be generated in a separate function.
131 ClassElement classElement = work.element.enclosingElement; 131 final ClassElement classElement = work.element.enclosingElement;
132 ConstructorBodyElement bodyElement; 132 return builder.buildFactory(classElement, work.element);
133 // In case of a bailout version, the constructor body has already
134 // been created.
135 if (work.isBailoutVersion()) {
136 for (Link<Element> backendMembers = classElement.backendMembers;
137 !backendMembers.isEmpty();
138 backendMembers = backendMembers.tail) {
139 Element current = backendMembers.head;
140 if (current.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
141 ConstructorBodyElement temp = current;
142 if (temp.constructor == work.element) {
143 bodyElement = temp;
144 break;
145 }
146 }
147 }
148 } else {
149 bodyElement = new ConstructorBodyElement(work.element);
150 compiler.enqueue(
151 new WorkItem.toCodegen(bodyElement, work.resolutionTree));
152 classElement.backendMembers =
153 classElement.backendMembers.prepend(bodyElement);
154 }
155 // TODO(floitsch): pass initializer-list to builder.
156 return builder.buildFactory(classElement, bodyElement, work.element);
157 } 133 }
158 } 134 }
159 135
160 /** 136 /**
161 * Keeps track of locals (including parameters and phis) when building. The 137 * Keeps track of locals (including parameters and phis) when building. The
162 * 'this' reference is treated as parameter and hence handled by this class, 138 * 'this' reference is treated as parameter and hence handled by this class,
163 * too. 139 * too.
164 */ 140 */
165 class LocalsHandler { 141 class LocalsHandler {
166 // The values of locals that can be directly accessed (without redirections 142 // The values of locals that can be directly accessed (without redirections
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 joinBlock.addPhi(phi); 390 joinBlock.addPhi(phi);
415 joinedLocals[element] = phi; 391 joinedLocals[element] = phi;
416 } 392 }
417 }); 393 });
418 directLocals = joinedLocals; 394 directLocals = joinedLocals;
419 } 395 }
420 } 396 }
421 397
422 class SsaBuilder implements Visitor { 398 class SsaBuilder implements Visitor {
423 final Compiler compiler; 399 final Compiler compiler;
424 final TreeElements elements; 400 TreeElements elements;
425 final Interceptors interceptors; 401 final Interceptors interceptors;
426 final WorkItem work; 402 final WorkItem work;
427 bool methodInterceptionEnabled; 403 bool methodInterceptionEnabled;
428 HGraph graph; 404 HGraph graph;
429 LocalsHandler localsHandler; 405 LocalsHandler localsHandler;
430 406
431 // We build the Ssa graph by simulating a stack machine. 407 // We build the Ssa graph by simulating a stack machine.
432 List<HInstruction> stack; 408 List<HInstruction> stack;
433 409
434 // The current block to add instructions to. Might be null, if we are 410 // The current block to add instructions to. Might be null, if we are
(...skipping 21 matching lines...) Expand all
456 methodInterceptionEnabled = true; 432 methodInterceptionEnabled = true;
457 } 433 }
458 434
459 HGraph buildMethod(FunctionElement functionElement) { 435 HGraph buildMethod(FunctionElement functionElement) {
460 FunctionExpression function = functionElement.parseNode(compiler); 436 FunctionExpression function = functionElement.parseNode(compiler);
461 openFunction(functionElement, function); 437 openFunction(functionElement, function);
462 function.body.accept(this); 438 function.body.accept(this);
463 return closeFunction(); 439 return closeFunction();
464 } 440 }
465 441
442 /**
443 * Returns the constructor body associated with the given constructor or
444 * creates a new constructor body, if none can be found.
445 */
446 ConstructorBodyElement getConstructorBody(ClassElement classElement,
447 FunctionElement constructor) {
448 assert(constructor.kind === ElementKind.GENERATIVE_CONSTRUCTOR);
449 ConstructorBodyElement bodyElement;
450 for (Link<Element> backendMembers = classElement.backendMembers;
451 !backendMembers.isEmpty();
452 backendMembers = backendMembers.tail) {
453 Element backendMember = backendMembers.head;
454 if (backendMember.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
455 ConstructorBodyElement body = backendMember;
456 if (body.constructor == constructor) {
457 bodyElement = backendMember;
458 break;
459 }
460 }
461 }
462 if (bodyElement === null) {
463 bodyElement = new ConstructorBodyElement(constructor);
464 TreeElements treeElements =
465 compiler.resolver.resolveMethodElement(bodyElement);
466 compiler.enqueue(new WorkItem.toCodegen(bodyElement, treeElements));
467 classElement.backendMembers =
468 classElement.backendMembers.prepend(bodyElement);
469 }
470 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY);
471 return bodyElement;
472 }
473
474 /**
475 * Call [f] for every argument and parameter element of [target]
476 * that is used in the invocation [send].
477 */
478 forEachArgument(Send send, FunctionElement target,
479 f(VariableElement parameter, Node argument)) {
480 final FunctionParameters parameters = target.computeParameters(compiler);
481 Link<Element> parameterElements = parameters.requiredParameters;
482 for (Link<Node> arguments = send.arguments;
483 !arguments.isEmpty();
484 arguments = arguments.tail) {
485 if (parameterElements.isEmpty()) {
486 parameterElements = parameters.optionalParameters;
487 }
488 f(parameterElements.head, arguments.head);
489 parameterElements = parameterElements.tail;
490 };
491 }
492
493 /**
494 * Run through the initializers and inline all field initializers. Returns the
495 * next constructor to analyze.
496 */
497 FunctionElement analyzeInitializers(Link<Node> initializers) {
498 FunctionElement nextConstructor;
499 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) {
500 assert(link.head is Send);
501 if (link.head is !SendSet) {
502 // A super initializer or constructor redirection.
503 Send call = link.head;
504 if (Initializers.isSuperConstructorCall(call)) {
505 assert(nextConstructor === null);
506 nextConstructor = elements[call];
507 // Visit arguments and map the corresponding parameter value to
508 // the resulting HInstruction value.
509 forEachArgument(call, nextConstructor, (parameter, node) {
510 visit(node);
511 HInstruction value = pop();
512 localsHandler.updateLocal(parameter, value);
513 });
514 } else {
515 compiler.unimplemented('SsaBuilder.buildFactory redirect');
516 }
517 } else {
518 // A field initializer.
519 SendSet init = link.head;
520 Link<Node> arguments = init.arguments;
521 assert(!arguments.isEmpty() && arguments.tail.isEmpty());
522 visit(arguments.head);
523 // We treat the init field-elements like locals. In the context of
524 // the factory this is correct, and simplifies dealing with
525 // parameter-initializers (like A(this.x)).
526 localsHandler.updateLocal(elements[init], pop());
527 }
528 }
529 return nextConstructor;
530 }
531
532 /**
533 * Build the factory function corresponding to the constructor
534 * [functionElement]:
535 * - Initialize fields with the values of the field initializers of the
536 * current constructor and super constructors or constructors redirected
537 * to, starting from the current constructor.
538 * - Call the the constructor bodies, starting from the constructor(s) in the
539 * super class(es).
540 */
466 HGraph buildFactory(ClassElement classElement, 541 HGraph buildFactory(ClassElement classElement,
467 ConstructorBodyElement bodyElement,
468 FunctionElement functionElement) { 542 FunctionElement functionElement) {
469 FunctionExpression function = functionElement.parseNode(compiler); 543 FunctionExpression function = functionElement.parseNode(compiler);
470 // The initializer list could contain closures. 544 // The initializer list could contain closures.
471 openFunction(functionElement, function); 545 openFunction(functionElement, function);
472 546
473 NodeList initializers = function.initializers; 547 final Map<FunctionElement, TreeElements> constructorElements =
548 compiler.resolver.constructorElements;
ngeoffray 2012/02/09 08:25:51 This variable is unused.
549 List<FunctionElement> constructors = new List<FunctionElement>();
474 550
475 // Run through the initializers. 551 // Analyze the constructor and all referenced constructors and collect
476 if (initializers !== null) { 552 // initializers and constructor bodies.
477 for (Link<Node> link = initializers.nodes; 553 FunctionElement nextConstructor = functionElement;
478 !link.isEmpty(); 554 while (nextConstructor != null) {
479 link = link.tail) { 555 FunctionElement constructor = nextConstructor;
480 assert(link.head is Send); 556 constructors.addLast(constructor);
481 if (link.head is !SendSet) { 557 nextConstructor = null;
482 compiler.unimplemented('SsaBuilder.buildFactory super-init'); 558 elements = compiler.resolver.resolveMethodElement(constructor);
483 } else { 559 FunctionExpression functionNode = constructor.parseNode(compiler);
484 SendSet init = link.head; 560 Link<Node> initializers = const EmptyLink<Node>();
485 Link<Node> arguments = init.arguments; 561 if (functionNode.initializers !== null) {
486 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); 562 nextConstructor = analyzeInitializers(functionNode.initializers.nodes);
487 visit(arguments.head); 563 }
488 // We treat the init field-elements like locals. In the context of 564 if (nextConstructor === null) {
489 // the factory this is correct, and simplifies dealing with 565 // No super initializer found. Try to find the default constructor if
490 // parameter-initializers (like A(this.x)). 566 // the class is not Object.
491 localsHandler.updateLocal(elements[init], pop()); 567 ClassElement enclosingClass = constructor.enclosingElement;
568 ClassElement superClass = enclosingClass.superclass;
569 if (enclosingClass.name != Types.OBJECT) {
floitsch 2012/02/08 15:30:27 use: compiler.coreLibrary.find(const SourceString
karlklose 2012/02/08 17:20:44 Done.
570 assert(superClass !== null);
571 assert(superClass.isResolved);
572 nextConstructor = superClass.lookupConstructor(superClass.name);
573 if (nextConstructor === null &&
574 superClass.canHaveDefaultConstructor()) {
575 nextConstructor = superClass.getSynthesizedConstructor();
576 } else if (nextConstructor === null) {
577 compiler.internalError("no default constructor available");
578 }
492 } 579 }
493 } 580 }
494 } 581 }
ngeoffray 2012/02/09 08:27:03 I would put 'elements' to null here, to make sure
495
496 // Call the JavaScript constructor with the fields as argument. 582 // Call the JavaScript constructor with the fields as argument.
497 // TODO(floitsch): allow super calls. 583 // TODO(floitsch,karlklose): move this code to ClassElement and share with
498 // TODO(floitsch): allow inits at field declarations. 584 // the emitter.
499 List<HInstruction> constructorArguments = <HInstruction>[]; 585 List<HInstruction> constructorArguments = <HInstruction>[];
500 for (Element member in classElement.members) { 586 ClassElement element = classElement;
501 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { 587 while (element != null) {
502 HInstruction value; 588 for (Element member in element.members) {
503 if (localsHandler.hasValueForDirectLocal(member)) { 589 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
504 value = localsHandler.readLocal(member); 590 HInstruction value;
505 } else { 591 if (localsHandler.hasValueForDirectLocal(member)) {
506 value = new HLiteral(null, HType.UNKNOWN); 592 value = localsHandler.readLocal(member);
507 add(value); 593 } else {
594 // TODO(karlklose): get default value.
595 value = new HLiteral(null, HType.UNKNOWN);
596 add(value);
597 }
598 constructorArguments.add(value);
508 } 599 }
509 constructorArguments.add(value);
510 } 600 }
601 element = element.superclass;
511 } 602 }
512 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); 603 HForeignNew newObject = new HForeignNew(classElement, constructorArguments);
513 add(newObject); 604 add(newObject);
514 605 // Generate calls to the constructor bodies.
515 // Call the method body. 606 for (int index = constructors.length - 1; index >= 0; index--) {
516 SourceString methodName = bodyElement.name; 607 FunctionElement constructor = constructors[index];
517 608 ConstructorBodyElement body = this.getConstructorBody(classElement,
518 List bodyCallInputs = <HInstruction>[]; 609 constructor);
519 bodyCallInputs.add(newObject); 610 List bodyCallInputs = <HInstruction>[];
520 FunctionParameters parameters = functionElement.computeParameters(compiler); 611 bodyCallInputs.add(newObject);
521 parameters.forEachParameter((Element parameterElement) { 612 body.functionParameters.forEachParameter((parameter) {
ngeoffray 2012/02/09 08:25:51 To be safe, should that be body.computeParameters(
522 HInstruction currentValue = localsHandler.readLocal(parameterElement); 613 bodyCallInputs.add(localsHandler.readLocal(parameter));
523 bodyCallInputs.add(currentValue); 614 });
524 }); 615 SourceString methodName = body.name;
525 add(new HInvokeDynamicMethod(null, methodName, bodyCallInputs)); 616 add(new HInvokeDynamicMethod(null, methodName, bodyCallInputs));
617 }
526 close(new HReturn(newObject)).addSuccessor(graph.exit); 618 close(new HReturn(newObject)).addSuccessor(graph.exit);
527 return closeFunction(); 619 return closeFunction();
528 } 620 }
529 621
530 void openFunction(FunctionElement functionElement, 622 void openFunction(FunctionElement functionElement,
531 FunctionExpression node) { 623 FunctionExpression node) {
532 HBasicBlock block = graph.addNewBlock(); 624 HBasicBlock block = graph.addNewBlock();
533 open(graph.entry); 625 open(graph.entry);
534 626
535 localsHandler.startFunction(functionElement, node); 627 localsHandler.startFunction(functionElement, node);
(...skipping 1237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 if (exception.type != null) { 1865 if (exception.type != null) {
1774 compiler.unimplemented('SsaBuilder catch with type', node: node); 1866 compiler.unimplemented('SsaBuilder catch with type', node: node);
1775 } 1867 }
1776 visit(node.block); 1868 visit(node.block);
1777 } 1869 }
1778 1870
1779 visitTypedef(Typedef node) { 1871 visitTypedef(Typedef node) {
1780 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 1872 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
1781 } 1873 }
1782 } 1874 }
OLDNEW
« no previous file with comments | « frog/leg/resolver.dart ('k') | frog/leg/ssa/closure.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698