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

Side by Side Diff: lib/compiler/implementation/ssa/variable_allocator.dart

Issue 10573027: Use GVN for length loads from arrays and strings. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comment. Created 8 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
« no previous file with comments | « lib/compiler/implementation/ssa/nodes.dart ('k') | no next file » | 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 /** 5 /**
6 * The [LiveRange] class covers a range where an instruction is live. 6 * The [LiveRange] class covers a range where an instruction is live.
7 */ 7 */
8 class LiveRange { 8 class LiveRange {
9 final int start; 9 final int start;
10 // [end] is not final because it can be updated due to loops. 10 // [end] is not final because it can be updated due to loops.
11 int end; 11 int end;
12 LiveRange(this.start, this.end) { 12 LiveRange(this.start, this.end) {
13 assert(start <= end); 13 assert(start <= end);
14 } 14 }
15 15
16 String toString() => '[$start $end['; 16 String toString() => '[$start $end[';
17 } 17 }
18 18
19 /** 19 /**
20 * The [LiveInterval] class contains the list of ranges where an 20 * The [LiveInterval] class contains the list of ranges where an
21 * instruction is live. 21 * instruction is live.
22 */ 22 */
23 class LiveInterval { 23 class LiveInterval {
24 /** 24 /**
25 * The id where there instruction is defined. 25 * The id where the instruction is defined.
26 */ 26 */
27 int start; 27 int start;
28 final List<LiveRange> ranges; 28 final List<LiveRange> ranges;
29 LiveInterval() : ranges = <LiveRange>[]; 29 LiveInterval() : ranges = <LiveRange>[];
30 30
31 /** 31 /**
32 * Update all ranges that are contained in [from, to[ to 32 * Update all ranges that are contained in [from, to[ to
33 * die at [to]. 33 * die at [to].
34 */ 34 */
35 void loopUpdate(int from, int to) { 35 void loopUpdate(int from, int to) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 range.start = id; 131 range.start = id;
132 } 132 }
133 liveInstructions.remove(instruction); 133 liveInstructions.remove(instruction);
134 } 134 }
135 135
136 /** 136 /**
137 * Add [instruction] to the liveIn set. If the instruction is not 137 * Add [instruction] to the liveIn set. If the instruction is not
138 * already in the set, we save the id where it dies. 138 * already in the set, we save the id where it dies.
139 */ 139 */
140 void add(HInstruction instruction, int userId) { 140 void add(HInstruction instruction, int userId) {
141 // Note that we are visiting the grap in post-dominator order, so 141 // Note that we are visiting the graph in post-dominator order, so
142 // the first time we see a variable is when it dies. 142 // the first time we see a variable is when it dies.
143 liveInstructions.putIfAbsent(instruction, () => userId); 143 liveInstructions.putIfAbsent(instruction, () => userId);
144 if (instruction is HCheck) { 144 if (instruction is HCheck) {
145 // Special case the HCheck instruction to mark the actual 145 // Special case the HCheck instruction to mark the actual
146 // checked instruction live. 146 // checked instruction live.
147 var input = instruction.checkedInput; 147 var input = instruction.checkedInput;
148 while (input is HCheck) input = input.checkedInput; 148 while (input is HCheck) input = input.checkedInput;
149 liveInstructions.putIfAbsent(input, () => userId); 149 liveInstructions.putIfAbsent(input, () => userId);
150 } 150 }
151 } 151 }
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 * Returns whether [instruction] dies at the instruction [at]. 582 * Returns whether [instruction] dies at the instruction [at].
583 */ 583 */
584 bool diesAt(HInstruction instruction, HInstruction at) { 584 bool diesAt(HInstruction instruction, HInstruction at) {
585 LiveInterval atInterval = liveIntervals[at]; 585 LiveInterval atInterval = liveIntervals[at];
586 LiveInterval instructionInterval = liveIntervals[instruction]; 586 LiveInterval instructionInterval = liveIntervals[instruction];
587 int start = atInterval.start; 587 int start = atInterval.start;
588 return instructionInterval.diesAt(start); 588 return instructionInterval.diesAt(start);
589 } 589 }
590 590
591 void handleInstruction(HInstruction instruction, VariableNamer namer) { 591 void handleInstruction(HInstruction instruction, VariableNamer namer) {
592 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 592 // TODO(ager): We cannot perform this check to free names for
593 HInstruction input = instruction.inputs[i]; 593 // HCheck instructions because they are special cased to have the
594 // If [input] has a name, and its use here is the last use, free 594 // same live intervals as the instruction they are checking. This
595 // its name. 595 // includes sharing the start id with the checked
596 if (needsName(input) && diesAt(input, instruction)) { 596 // input. Therefore, for HCheck(checkedInput, otherInput) we would
597 namer.freeName(input); 597 // end up checking that otherInput dies not here, but at the
598 // location of checkedInput. We should preserve the start id for
599 // the check instruction.
600 if (instruction is! HCheck) {
601 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
602 HInstruction input = instruction.inputs[i];
603 // If [input] has a name, and its use here is the last use, free
604 // its name.
605 if (needsName(input) && diesAt(input, instruction)) {
606 namer.freeName(input);
607 }
598 } 608 }
599 } 609 }
600 610
601 if (needsName(instruction)) { 611 if (needsName(instruction)) {
602 namer.allocateName(instruction); 612 namer.allocateName(instruction);
603 } 613 }
604 } 614 }
605 615
606 void handlePhi(HPhi phi, VariableNamer namer) { 616 void handlePhi(HPhi phi, VariableNamer namer) {
607 if (!needsName(phi)) return; 617 if (!needsName(phi)) return;
608 618
609 for (int i = 0; i < phi.inputs.length; i++) { 619 for (int i = 0; i < phi.inputs.length; i++) {
610 HInstruction input = phi.inputs[i]; 620 HInstruction input = phi.inputs[i];
611 HBasicBlock predecessor = phi.block.predecessors[i]; 621 HBasicBlock predecessor = phi.block.predecessors[i];
612 if (!needsName(input)) { 622 if (!needsName(input)) {
613 names.addAssignment(predecessor, input, phi); 623 names.addAssignment(predecessor, input, phi);
614 } else { 624 } else {
615 names.addCopy(predecessor, input, phi); 625 names.addCopy(predecessor, input, phi);
616 } 626 }
617 } 627 }
618 628
619 namer.allocateName(phi); 629 namer.allocateName(phi);
620 } 630 }
621 } 631 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/nodes.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698