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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart

Issue 312793002: dart2dart: Preserve variable names throughout the IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: SVN rebase Created 6 years, 6 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // IrNodes are kept in a separate library to have precise control over their 5 // IrNodes are kept in a separate library to have precise control over their
6 // dependencies on other parts of the system. 6 // dependencies on other parts of the system.
7 library dart2js.ir_nodes; 7 library dart2js.ir_nodes;
8 8
9 import '../dart2jslib.dart' as dart2js show Constant; 9 import '../dart2jslib.dart' as dart2js show Constant;
10 import '../elements/elements.dart' 10 import '../elements/elements.dart'
11 show FunctionElement, LibraryElement, ParameterElement, ClassElement, 11 show FunctionElement, LibraryElement, ParameterElement, ClassElement,
12 Element; 12 Element, VariableElement;
13 import '../universe/universe.dart' show Selector, SelectorKind; 13 import '../universe/universe.dart' show Selector, SelectorKind;
14 import '../dart_types.dart' show DartType, GenericType; 14 import '../dart_types.dart' show DartType, GenericType;
15 import '../helpers/helpers.dart';
15 16
16 abstract class Node { 17 abstract class Node {
17 static int hashCount = 0; 18 static int hashCount = 0;
18 final int hashCode = hashCount = (hashCount + 1) & 0x3fffffff; 19 final int hashCode = hashCount = (hashCount + 1) & 0x3fffffff;
19 20
20 accept(Visitor visitor); 21 accept(Visitor visitor);
21 } 22 }
22 23
23 abstract class Expression extends Node { 24 abstract class Expression extends Node {
24 Expression plug(Expression expr) => throw 'impossible'; 25 Expression plug(Expression expr) => throw 'impossible';
(...skipping 16 matching lines...) Expand all
41 do { 42 do {
42 current.definition = this; 43 current.definition = this;
43 previous = current; 44 previous = current;
44 current = current.nextRef; 45 current = current.nextRef;
45 } while (current != null); 46 } while (current != null);
46 previous.nextRef = firstRef; 47 previous.nextRef = firstRef;
47 firstRef = other.firstRef; 48 firstRef = other.firstRef;
48 } 49 }
49 } 50 }
50 51
52 /// A pure expression that cannot throw or diverge.
53 /// All primitives are named using the identity of the [Primitive] object.
51 abstract class Primitive extends Definition { 54 abstract class Primitive extends Definition {
55 /// The [VariableElement] or [ParameterElement] from which the primitive
56 /// binding originated.
57 Element element;
58
59 /// Register in which the variable binding this primitive can be allocated.
60 /// Separate register spaces are used for primitives with different [element].
61 /// Assigned by [RegisterAllocator], is null before that phase.
62 int registerIndex;
63
64 /// Use the given element as a hint for naming this primitive.
65 ///
66 /// Has no effect if this primitive already has a non-null [element].
67 void useElementAsHint(Element hint) {
68 if (element == null) {
69 element = hint;
70 }
71 }
52 } 72 }
53 73
54 /// Operands to invocations and primitives are always variables. They point to 74 /// Operands to invocations and primitives are always variables. They point to
55 /// their definition and are linked into a list of occurrences. 75 /// their definition and are linked into a list of occurrences.
56 class Reference { 76 class Reference {
57 Definition definition; 77 Definition definition;
58 Reference nextRef = null; 78 Reference nextRef = null;
59 79
60 Reference(this.definition) { 80 Reference(this.definition) {
61 nextRef = definition.firstRef; 81 nextRef = definition.firstRef;
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 List<Reference> values; 312 List<Reference> values;
293 313
294 LiteralMap(List<Primitive> keys, List<Primitive> values) 314 LiteralMap(List<Primitive> keys, List<Primitive> values)
295 : this.keys = _referenceList(keys), 315 : this.keys = _referenceList(keys),
296 this.values = _referenceList(values); 316 this.values = _referenceList(values);
297 317
298 accept(Visitor visitor) => visitor.visitLiteralMap(this); 318 accept(Visitor visitor) => visitor.visitLiteralMap(this);
299 } 319 }
300 320
301 class Parameter extends Primitive { 321 class Parameter extends Primitive {
302 final ParameterElement element; 322 Parameter(Element element) {
303 323 super.element = element;
304 Parameter(this.element); 324 }
305 325
306 accept(Visitor visitor) => visitor.visitParameter(this); 326 accept(Visitor visitor) => visitor.visitParameter(this);
307 } 327 }
308 328
309 /// Continuations are normally bound by 'let cont'. A continuation with no 329 /// Continuations are normally bound by 'let cont'. A continuation with no
310 /// parameter (or body) is used to represent a function's return continuation. 330 /// parameter (or body) is used to represent a function's return continuation.
311 /// The return continuation is bound by the Function, not by 'let cont'. 331 /// The return continuation is bound by the Function, not by 'let cont'.
312 class Continuation extends Definition { 332 class Continuation extends Definition {
313 final List<Parameter> parameters; 333 final List<Parameter> parameters;
314 Expression body = null; 334 Expression body = null;
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 String visitContinuation(Continuation node) { 515 String visitContinuation(Continuation node) {
496 // Continuations are visited directly in visitLetCont. 516 // Continuations are visited directly in visitLetCont.
497 return '(Unexpected Continuation)'; 517 return '(Unexpected Continuation)';
498 } 518 }
499 519
500 String visitIsTrue(IsTrue node) { 520 String visitIsTrue(IsTrue node) {
501 String value = names[node.value.definition]; 521 String value = names[node.value.definition];
502 return '(IsTrue $value)'; 522 return '(IsTrue $value)';
503 } 523 }
504 } 524 }
525
526 /// Keeps track of currently unused register indices.
527 class RegisterArray {
528 int nextIndex = 0;
529 final List<int> freeStack = <int>[];
530
531 int makeIndex() {
532 if (freeStack.isEmpty) {
533 return nextIndex++;
534 } else {
535 return freeStack.removeLast();
536 }
537 }
538
539 void releaseIndex(int index) {
540 freeStack.add(index);
541 }
542 }
543
544 /// Assigns indices to each primitive in the IR such that primitives that are
545 /// live simultaneously never get assigned the same index.
546 /// This information is used by the dart tree builder to generate fewer
547 /// redundant variables.
548 /// Currently, the liveness analysis is very simple and is often inadequate
549 /// for removing all of the redundant variables.
550 class RegisterAllocator extends Visitor {
551 /// Separate register spaces for each source-level variable/parameter.
552 /// Note that null is used as key for primitives without elements.
553 final Map<Element, RegisterArray> elementRegisters =
554 <Element, RegisterArray>{};
555
556 RegisterArray getRegisterArray(Element element) {
557 RegisterArray registers = elementRegisters[element];
558 if (registers == null) {
559 registers = new RegisterArray();
560 elementRegisters[element] = registers;
561 }
562 return registers;
563 }
564
565 void allocate(Primitive primitive) {
566 if (primitive.registerIndex == null) {
567 primitive.registerIndex = getRegisterArray(primitive.element).makeIndex();
568 }
569 }
570
571 void release(Primitive primitive) {
572 // Do not share indices for temporaries as this may obstruct inlining.
573 if (primitive.element == null) return;
574 if (primitive.registerIndex != null) {
575 getRegisterArray(primitive.element).releaseIndex(primitive.registerIndex);
576 }
577 }
578
579 void visitReference(Reference reference) {
580 allocate(reference.definition);
581 }
582
583 void visitFunctionDefinition(FunctionDefinition node) {
584 visit(node.body);
585 node.parameters.forEach(allocate); // Assign indices to unused parameters.
586 elementRegisters.clear();
587 }
588
589 void visitLetPrim(LetPrim node) {
590 visit(node.body);
591 release(node.primitive);
592 visit(node.primitive);
593 }
594
595 void visitLetCont(LetCont node) {
596 visit(node.continuation);
597 visit(node.body);
598 }
599
600 void visitInvokeStatic(InvokeStatic node) {
601 node.arguments.forEach(visitReference);
602 }
603
604 void visitInvokeContinuation(InvokeContinuation node) {
605 node.arguments.forEach(visitReference);
606 }
607
608 void visitInvokeMethod(InvokeMethod node) {
609 visitReference(node.receiver);
610 node.arguments.forEach(visitReference);
611 }
612
613 void visitInvokeConstructor(InvokeConstructor node) {
614 node.arguments.forEach(visitReference);
615 }
616
617 void visitConcatenateStrings(ConcatenateStrings node) {
618 node.arguments.forEach(visitReference);
619 }
620
621 void visitBranch(Branch node) {
622 visit(node.condition);
623 }
624
625 void visitInvokeConstConstructor(InvokeConstConstructor node) {
626 node.arguments.forEach(visitReference);
627 }
628
629 void visitLiteralList(LiteralList node) {
630 node.values.forEach(visitReference);
631 }
632
633 void visitLiteralMap(LiteralMap node) {
634 for (int i = 0; i < node.keys.length; ++i) {
635 visitReference(node.keys[i]);
636 visitReference(node.values[i]);
637 }
638 }
639
640 void visitConstant(Constant node) {
641 }
642
643 void visitParameter(Parameter node) {
644 throw "Parameters should not be visited by RegisterAllocator";
645 }
646
647 void visitContinuation(Continuation node) {
648 visit(node.body);
649
650 // Arguments get allocated left-to-right, so we release parameters
651 // right-to-left. This increases the likelihood that arguments can be
652 // transferred without intermediate assignments.
653 for (int i = node.parameters.length - 1; i >= 0; --i) {
654 release(node.parameters[i]);
655 }
656 }
657
658 void visitIsTrue(IsTrue node) {
659 visitReference(node.value);
660 }
661
662 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698