OLD | NEW |
---|---|
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. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 | 108 |
109 /** | 109 /** |
110 * Remove an instruction from the liveIn set. This method also | 110 * Remove an instruction from the liveIn set. This method also |
111 * updates the live interval of [instruction] to contain the new | 111 * updates the live interval of [instruction] to contain the new |
112 * range: [id, / id contained in [liveInstructions] /]. | 112 * range: [id, / id contained in [liveInstructions] /]. |
113 */ | 113 */ |
114 void remove(HInstruction instruction, int id) { | 114 void remove(HInstruction instruction, int id) { |
115 // Special case the HCheck instruction to have the same live | 115 // Special case the HCheck instruction to have the same live |
116 // interval as the instruction it is checking. | 116 // interval as the instruction it is checking. |
117 if (instruction is HCheck) { | 117 if (instruction is HCheck) { |
118 HInstruction input = instruction.checkedInput; | 118 var input = instruction.checkedInput; |
119 while (input is HCheck) input = input.checkedInput; | 119 while (input is HCheck) input = input.checkedInput; |
120 liveIntervals.putIfAbsent(input, () => new LiveInterval()); | 120 liveIntervals.putIfAbsent(input, () => new LiveInterval()); |
121 liveIntervals.putIfAbsent(instruction, () => liveIntervals[input]); | 121 liveIntervals.putIfAbsent(instruction, () => liveIntervals[input]); |
122 return; | 122 } else { |
123 LiveInterval range = liveIntervals.putIfAbsent( | |
124 instruction, () => new LiveInterval()); | |
125 int lastId = liveInstructions[instruction]; | |
126 // If [lastId] is null, then this instruction is not being used. | |
127 range.add(new LiveRange(id, lastId == null ? id : lastId)); | |
128 // The instruction is defined at [id]. | |
129 range.start = id; | |
123 } | 130 } |
124 LiveInterval range = liveIntervals.putIfAbsent( | |
125 instruction, () => new LiveInterval()); | |
126 int lastId = liveInstructions[instruction]; | |
127 // If [lastId] is null, then this instruction is not being used. | |
128 range.add(new LiveRange(id, lastId == null ? id : lastId)); | |
129 // The instruction is defined at [id]. | |
130 range.start = id; | |
131 liveInstructions.remove(instruction); | 131 liveInstructions.remove(instruction); |
132 } | 132 } |
133 | 133 |
134 /** | 134 /** |
135 * Add [instruction] to the liveIn set. If the instruction is not | 135 * Add [instruction] to the liveIn set. If the instruction is not |
136 * already in the set, we save the id where it dies. | 136 * already in the set, we save the id where it dies. |
137 */ | 137 */ |
138 void add(HInstruction instruction, int userId) { | 138 void add(HInstruction instruction, int userId) { |
139 // Special case the HCheck instruction to use the actual checked | |
140 // instruction. | |
141 while (instruction is HCheck) instruction = instruction.checkedInput; | |
142 // Note that we are visiting the grap in post-dominator order, so | 139 // Note that we are visiting the grap in post-dominator order, so |
143 // the first time we see a variable is when it dies. | 140 // the first time we see a variable is when it dies. |
144 liveInstructions.putIfAbsent(instruction, () => userId); | 141 liveInstructions.putIfAbsent(instruction, () => userId); |
142 if (instruction is HCheck) { | |
143 // Special case the HCheck instruction to mark the actual | |
144 // checked instruction live. | |
145 liveInstructions.putIfAbsent(instruction, () => userId); | |
146 var input = instruction.checkedInput; | |
147 while (input is HCheck) input = input.checkedInput; | |
148 liveInstructions.putIfAbsent(input, () => userId); | |
149 } | |
145 } | 150 } |
146 | 151 |
147 /** | 152 /** |
148 * Merge this environment with [other]. Update the end id of | 153 * Merge this environment with [other]. Update the end id of |
149 * instructions in case they are different between this and [other]. | 154 * instructions in case they are different between this and [other]. |
150 */ | 155 */ |
151 void mergeWith(LiveEnvironment other) { | 156 void mergeWith(LiveEnvironment other) { |
152 other.liveInstructions.forEach((HInstruction instruction, int existingId) { | 157 other.liveInstructions.forEach((HInstruction instruction, int existingId) { |
153 // If both environments have the same instruction id of where | 158 // If both environments have the same instruction id of where |
154 // [instruction] dies, there is no need to update the live | 159 // [instruction] dies, there is no need to update the live |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 if (user is HPhi && user.sourceElement !== null) { | 432 if (user is HPhi && user.sourceElement !== null) { |
428 return user; | 433 return user; |
429 } | 434 } |
430 } | 435 } |
431 return null; | 436 return null; |
432 } | 437 } |
433 | 438 |
434 String allocateName(HInstruction instruction) { | 439 String allocateName(HInstruction instruction) { |
435 String name; | 440 String name; |
436 if (instruction is HCheck) { | 441 if (instruction is HCheck) { |
437 // Special case the check instruction to use the name of its | 442 // Special case this instruction to use the name of its |
438 // checked instruction. | 443 // input if it has one. |
439 HCheck check = instruction; | 444 var temp = instruction; |
440 name = names.ownName[check.checkedInput]; | 445 do { |
441 // If the name is null, then the checked input is being | 446 temp = temp.checkedInput; |
442 // generated at use site, and we don't need a name for the check | 447 name = names.ownName[temp]; |
443 // instruction. | 448 } while (name == null && temp is HCheck); |
444 if (name == null) return null; | 449 } |
445 } else if (instruction is HParameterValue) { | 450 |
446 HParameterValue parameter = instruction; | 451 if (name == null) { |
447 name = parameterNames[parameter.sourceElement]; | 452 if (instruction is HParameterValue) { |
kasperl
2012/06/07 08:29:14
There's something a bit fishy about the control fl
ngeoffray
2012/06/07 09:02:42
Done.
| |
448 if (name == null) { | 453 HParameterValue parameter = instruction; |
449 name = allocateWithHint(parameter.sourceElement.name.slowToString()); | 454 name = parameterNames[parameter.sourceElement]; |
450 } | 455 if (name == null) { |
451 } else if (instruction.sourceElement !== null) { | 456 name = allocateWithHint(parameter.sourceElement.name.slowToString()); |
452 name = allocateWithHint(instruction.sourceElement.name.slowToString()); | 457 } |
453 } else { | 458 } else if (instruction.sourceElement !== null) { |
454 // We could not find an element for the instruction. If the | 459 name = allocateWithHint(instruction.sourceElement.name.slowToString()); |
455 // instruction is used by a phi, try to use the name of the phi. | |
456 // Otherwise, just allocate a temporary name. | |
457 HPhi phi = firstPhiUserWithElement(instruction); | |
458 if (phi !== null) { | |
459 name = allocateWithHint(phi.sourceElement.name.slowToString()); | |
460 } else { | 460 } else { |
461 name = allocateTemporary(); | 461 // We could not find an element for the instruction. If the |
462 // instruction is used by a phi, try to use the name of the phi. | |
463 // Otherwise, just allocate a temporary name. | |
464 HPhi phi = firstPhiUserWithElement(instruction); | |
465 if (phi !== null) { | |
466 name = allocateWithHint(phi.sourceElement.name.slowToString()); | |
467 } else { | |
468 name = allocateTemporary(); | |
469 } | |
462 } | 470 } |
463 } | 471 } |
464 usedNames.add(name); | 472 usedNames.add(name); |
kasperl
2012/06/07 08:29:14
You could also create a helper function for this l
ngeoffray
2012/06/07 09:02:42
Done.
| |
465 names.ownName[instruction] = name; | 473 names.ownName[instruction] = name; |
466 return name; | 474 return name; |
467 } | 475 } |
468 | 476 |
469 /** | 477 /** |
470 * Frees [instruction]'s name so it can be used for other instructions. | 478 * Frees [instruction]'s name so it can be used for other instructions. |
471 */ | 479 */ |
472 void freeName(HInstruction instruction) { | 480 void freeName(HInstruction instruction) { |
473 String ownName = names.ownName[instruction]; | 481 String ownName = names.ownName[instruction]; |
474 if (ownName != null) { | 482 if (ownName != null) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
527 * Returns whether [instruction] needs a name. Instructions that | 535 * Returns whether [instruction] needs a name. Instructions that |
528 * have no users or that are generated at use site does not need a name. | 536 * have no users or that are generated at use site does not need a name. |
529 */ | 537 */ |
530 bool needsName(HInstruction instruction) { | 538 bool needsName(HInstruction instruction) { |
531 if (instruction.usedBy.isEmpty()) return false; | 539 if (instruction.usedBy.isEmpty()) return false; |
532 // TODO(ngeoffray): parameters are being generated at use site, | 540 // TODO(ngeoffray): parameters are being generated at use site, |
533 // but we need a name for parameters. We should probably not make | 541 // but we need a name for parameters. We should probably not make |
534 // them generate at use site to make things simpler. | 542 // them generate at use site to make things simpler. |
535 if (instruction is HParameterValue && instruction is !HThis) return true; | 543 if (instruction is HParameterValue && instruction is !HThis) return true; |
536 if (generateAtUseSite.contains(instruction)) return false; | 544 if (generateAtUseSite.contains(instruction)) return false; |
545 // A [HCheckStatement] instruction needs a name only if its | |
546 // checked input needs a name (e.g. a check [HConstant] does not | |
547 // need a name). | |
548 if (instruction is HCheckStatement) { | |
549 HCheck check = instruction; | |
550 return needsName(instruction.checkedInput); | |
551 } | |
537 return true; | 552 return true; |
538 } | 553 } |
539 | 554 |
540 /** | 555 /** |
541 * Returns whether [instruction] dies at the instruction [at]. | 556 * Returns whether [instruction] dies at the instruction [at]. |
542 */ | 557 */ |
543 bool diesAt(HInstruction instruction, HInstruction at) { | 558 bool diesAt(HInstruction instruction, HInstruction at) { |
544 LiveInterval atInterval = liveIntervals[at]; | 559 LiveInterval atInterval = liveIntervals[at]; |
545 LiveInterval instructionInterval = liveIntervals[instruction]; | 560 LiveInterval instructionInterval = liveIntervals[instruction]; |
546 int start = atInterval.start; | 561 int start = atInterval.start; |
(...skipping 24 matching lines...) Expand all Loading... | |
571 if (!needsName(input)) { | 586 if (!needsName(input)) { |
572 names.addAssignment(predecessor, input, phi); | 587 names.addAssignment(predecessor, input, phi); |
573 } else { | 588 } else { |
574 names.addCopy(predecessor, input, phi); | 589 names.addCopy(predecessor, input, phi); |
575 } | 590 } |
576 } | 591 } |
577 | 592 |
578 namer.allocateName(phi); | 593 namer.allocateName(phi); |
579 } | 594 } |
580 } | 595 } |
OLD | NEW |