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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart

Issue 190763013: Detect total switches to prevent type pollution by default cases. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address review comments Created 6 years, 9 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) 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 part of ssa; 5 part of ssa;
6 6
7 abstract class OptimizationPhase { 7 abstract class OptimizationPhase {
8 String get name; 8 String get name;
9 void visitGraph(HGraph graph); 9 void visitGraph(HGraph graph);
10 } 10 }
11 11
12 class SsaOptimizerTask extends CompilerTask { 12 class SsaOptimizerTask extends CompilerTask {
13 final JavaScriptBackend backend; 13 final JavaScriptBackend backend;
14 SsaOptimizerTask(JavaScriptBackend backend) 14 SsaOptimizerTask(JavaScriptBackend backend)
15 : this.backend = backend, 15 : this.backend = backend,
16 super(backend.compiler); 16 super(backend.compiler);
17 String get name => 'SSA optimizer'; 17 String get name => 'SSA optimizer';
18 Compiler get compiler => backend.compiler; 18 Compiler get compiler => backend.compiler;
19 Map<HInstruction, Range> ranges = <HInstruction, Range>{};
19 20
20 void runPhases(HGraph graph, List<OptimizationPhase> phases) { 21 void runPhases(HGraph graph, List<OptimizationPhase> phases) {
21 for (OptimizationPhase phase in phases) { 22 for (OptimizationPhase phase in phases) {
22 runPhase(graph, phase); 23 runPhase(graph, phase);
23 } 24 }
24 } 25 }
25 26
26 void runPhase(HGraph graph, OptimizationPhase phase) { 27 void runPhase(HGraph graph, OptimizationPhase phase) {
27 phase.visitGraph(graph); 28 phase.visitGraph(graph);
28 compiler.tracer.traceGraph(phase.name, graph); 29 compiler.tracer.traceGraph(phase.name, graph);
(...skipping 30 matching lines...) Expand all
59 new SsaCodeMotion(), 60 new SsaCodeMotion(),
60 new SsaLoadElimination(compiler), 61 new SsaLoadElimination(compiler),
61 new SsaDeadPhiEliminator(), 62 new SsaDeadPhiEliminator(),
62 new SsaTypePropagator(compiler), 63 new SsaTypePropagator(compiler),
63 new SsaValueRangeAnalyzer(compiler, constantSystem, work), 64 new SsaValueRangeAnalyzer(compiler, constantSystem, work),
64 // Previous optimizations may have generated new 65 // Previous optimizations may have generated new
65 // opportunities for instruction simplification. 66 // opportunities for instruction simplification.
66 new SsaInstructionSimplifier(constantSystem, backend, work), 67 new SsaInstructionSimplifier(constantSystem, backend, work),
67 new SsaCheckInserter(backend, work, context.boundsChecked), 68 new SsaCheckInserter(backend, work, context.boundsChecked),
68 new SsaSimplifyInterceptors(compiler, constantSystem, work), 69 new SsaSimplifyInterceptors(compiler, constantSystem, work),
69 dce = new SsaDeadCodeEliminator(compiler)]; 70 dce = new SsaDeadCodeEliminator(compiler),
71 new SsaTypePropagator(compiler)];
70 runPhases(graph, phases); 72 runPhases(graph, phases);
71 if (!dce.eliminatedSideEffects) return; 73 if (dce.eliminatedSideEffects) {
72 phases = <OptimizationPhase>[ 74 phases = <OptimizationPhase>[
73 new SsaGlobalValueNumberer(compiler), 75 new SsaGlobalValueNumberer(compiler),
74 new SsaCodeMotion(), 76 new SsaCodeMotion(),
75 new SsaValueRangeAnalyzer(compiler, constantSystem, work), 77 new SsaValueRangeAnalyzer(compiler, constantSystem, work),
76 new SsaInstructionSimplifier(constantSystem, backend, work), 78 new SsaInstructionSimplifier(constantSystem, backend, work),
77 new SsaCheckInserter(backend, work, context.boundsChecked), 79 new SsaCheckInserter(backend, work, context.boundsChecked),
78 new SsaSimplifyInterceptors(compiler, constantSystem, work), 80 new SsaSimplifyInterceptors(compiler, constantSystem, work),
79 new SsaDeadCodeEliminator(compiler)]; 81 new SsaDeadCodeEliminator(compiler)];
82 } else {
83 phases = <OptimizationPhase>[
84 // Run the simplifier to remove unneeded type checks inserted
85 // by type propagation.
86 new SsaInstructionSimplifier(constantSystem, backend, work)];
87 }
80 runPhases(graph, phases); 88 runPhases(graph, phases);
81 }); 89 });
82 } 90 }
83 } 91 }
84 92
85 bool isFixedLength(mask, Compiler compiler) { 93 bool isFixedLength(mask, Compiler compiler) {
86 JavaScriptBackend backend = compiler.backend; 94 JavaScriptBackend backend = compiler.backend;
87 if (mask.isContainer && mask.length != null) { 95 if (mask.isContainer && mask.length != null) {
88 // A container on which we have inferred the length. 96 // A container on which we have inferred the length.
89 return true; 97 return true;
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 && instruction.onlyThrowsNSM() 942 && instruction.onlyThrowsNSM()
935 && hasFollowingThrowingNSM(instruction)) { 943 && hasFollowingThrowingNSM(instruction)) {
936 return true; 944 return true;
937 } 945 }
938 return !instruction.canThrow() 946 return !instruction.canThrow()
939 && instruction is !HParameterValue 947 && instruction is !HParameterValue
940 && instruction is !HLocalSet; 948 && instruction is !HLocalSet;
941 } 949 }
942 950
943 void visitGraph(HGraph graph) { 951 void visitGraph(HGraph graph) {
944 analyzer = new SsaLiveBlockAnalyzer(graph); 952 analyzer = new SsaLiveBlockAnalyzer(graph, compiler);
945 analyzer.analyze(); 953 analyzer.analyze();
946 visitPostDominatorTree(graph); 954 visitPostDominatorTree(graph);
947 cleanPhis(graph); 955 cleanPhis(graph);
948 } 956 }
949 957
950 void visitBasicBlock(HBasicBlock block) { 958 void visitBasicBlock(HBasicBlock block) {
951 bool isDeadBlock = analyzer.isDeadBlock(block); 959 bool isDeadBlock = analyzer.isDeadBlock(block);
952 block.isLive = !isDeadBlock; 960 block.isLive = !isDeadBlock;
953 // Start from the last non-control flow instruction in the block. 961 // Start from the last non-control flow instruction in the block.
954 HInstruction instruction = block.last.previous; 962 HInstruction instruction = block.last.previous;
955 while (instruction != null) { 963 while (instruction != null) {
956 var previous = instruction.previous; 964 var previous = instruction.previous;
957 if (isDeadBlock) { 965 if (isDeadBlock) {
958 eliminatedSideEffects = eliminatedSideEffects || 966 eliminatedSideEffects = eliminatedSideEffects ||
959 instruction.sideEffects.hasSideEffects(); 967 instruction.sideEffects.hasSideEffects();
960 removeUsers(instruction); 968 removeUsers(instruction);
961 block.remove(instruction); 969 block.remove(instruction);
962 } else if (isDeadCode(instruction)) { 970 } else if (isDeadCode(instruction)) {
963 block.remove(instruction); 971 block.remove(instruction);
964 } 972 }
965 instruction = previous; 973 instruction = previous;
966 } 974 }
967 } 975 }
968 976
969 void cleanPhis(HGraph graph) { 977 void cleanPhis(HGraph graph) {
970 L: for (HBasicBlock block in graph.blocks) { 978 L: for (HBasicBlock block in graph.blocks) {
971 List<HBasicBlock> predecessors = block.predecessors; 979 List<HBasicBlock> predecessors = block.predecessors;
980 // Zap all inputs to phis that correspond to dead blocks.
981 block.forEachPhi((HPhi phi) {
982 for (int i = 0; i < phi.inputs.length; ++i) {
983 if (!predecessors[i].isLive && phi.inputs[i] != zapInstruction) {
984 replaceInput(i, phi, zapInstruction);
985 }
986 }
987 });
972 if (predecessors.length < 2) continue L; 988 if (predecessors.length < 2) continue L;
973 // Find the index of the single live predecessor if it exists. 989 // Find the index of the single live predecessor if it exists.
974 int indexOfLive = -1; 990 int indexOfLive = -1;
975 for (int i = 0; i < predecessors.length; i++) { 991 for (int i = 0; i < predecessors.length; i++) {
976 if (predecessors[i].isLive) { 992 if (predecessors[i].isLive) {
977 if (indexOfLive >= 0) continue L; 993 if (indexOfLive >= 0) continue L;
978 indexOfLive = i; 994 indexOfLive = i;
979 } 995 }
980 } 996 }
981 // Run through the phis of the block and replace them with their input 997 // Run through the phis of the block and replace them with their input
982 // that comes from the only live predecessor if that dominates the phi. 998 // that comes from the only live predecessor if that dominates the phi.
983 block.forEachPhi((HPhi phi) { 999 block.forEachPhi((HPhi phi) {
984 HInstruction replacement = (indexOfLive >= 0) 1000 HInstruction replacement = (indexOfLive >= 0)
985 ? phi.inputs[indexOfLive] : zapInstruction; 1001 ? phi.inputs[indexOfLive] : zapInstruction;
986 if (replacement.dominates(phi)) { 1002 if (replacement.dominates(phi)) {
987 block.rewrite(phi, replacement); 1003 block.rewrite(phi, replacement);
988 block.removePhi(phi); 1004 block.removePhi(phi);
989 } 1005 }
990 }); 1006 });
991 } 1007 }
992 } 1008 }
993 1009
1010 void replaceInput(int i, HInstruction from, HInstruction by) {
1011 from.inputs[i].usedBy.remove(from);
1012 from.inputs[i] = by;
1013 by.usedBy.add(from);
1014 }
1015
994 void removeUsers(HInstruction instruction) { 1016 void removeUsers(HInstruction instruction) {
995 instruction.usedBy.forEach((user) { 1017 instruction.usedBy.forEach((user) {
996 removeInput(user, instruction); 1018 removeInput(user, instruction);
997 }); 1019 });
998 instruction.usedBy.clear(); 1020 instruction.usedBy.clear();
999 } 1021 }
1000 1022
1001 void removeInput(HInstruction user, HInstruction input) { 1023 void removeInput(HInstruction user, HInstruction input) {
1002 List<HInstruction> inputs = user.inputs; 1024 List<HInstruction> inputs = user.inputs;
1003 for (int i = 0, length = inputs.length; i < length; i++) { 1025 for (int i = 0, length = inputs.length; i < length; i++) {
1004 if (input == inputs[i]) { 1026 if (input == inputs[i]) {
1005 HInstruction zap = zapInstruction; 1027 user.inputs[i] = zapInstruction;
1006 inputs[i] = zap; 1028 zapInstruction.usedBy.add(user);
1007 zap.usedBy.add(user);
1008 } 1029 }
1009 } 1030 }
1010 } 1031 }
1011 } 1032 }
1012 1033
1013 class SsaLiveBlockAnalyzer extends HBaseVisitor { 1034 class SsaLiveBlockAnalyzer extends HBaseVisitor {
1014 final HGraph graph; 1035 final HGraph graph;
1036 final Compiler compiler;
1015 final Set<HBasicBlock> live = new Set<HBasicBlock>(); 1037 final Set<HBasicBlock> live = new Set<HBasicBlock>();
1016 final List<HBasicBlock> worklist = <HBasicBlock>[]; 1038 final List<HBasicBlock> worklist = <HBasicBlock>[];
1017 SsaLiveBlockAnalyzer(this.graph); 1039
1040 SsaLiveBlockAnalyzer(this.graph, this.compiler);
1041
1042 JavaScriptBackend get backend => compiler.backend;
1043 Map<HInstruction, Range> get ranges => backend.optimizer.ranges;
1018 1044
1019 bool isDeadBlock(HBasicBlock block) => !live.contains(block); 1045 bool isDeadBlock(HBasicBlock block) => !live.contains(block);
1020 1046
1021 void analyze() { 1047 void analyze() {
1022 markBlockLive(graph.entry); 1048 markBlockLive(graph.entry);
1023 while (!worklist.isEmpty) { 1049 while (!worklist.isEmpty) {
1024 HBasicBlock live = worklist.removeLast(); 1050 HBasicBlock live = worklist.removeLast();
1025 live.last.accept(this); 1051 live.last.accept(this);
1026 } 1052 }
1027 } 1053 }
(...skipping 14 matching lines...) Expand all
1042 if (condition.isConstant()) { 1068 if (condition.isConstant()) {
1043 if (condition.isConstantTrue()) { 1069 if (condition.isConstantTrue()) {
1044 markBlockLive(instruction.thenBlock); 1070 markBlockLive(instruction.thenBlock);
1045 } else { 1071 } else {
1046 markBlockLive(instruction.elseBlock); 1072 markBlockLive(instruction.elseBlock);
1047 } 1073 }
1048 } else { 1074 } else {
1049 visitControlFlow(instruction); 1075 visitControlFlow(instruction);
1050 } 1076 }
1051 } 1077 }
1078
1079 void visitSwitch(HSwitch node) {
1080 if (!node.isTotal && node.expression.isInteger(compiler)) {
1081 Range switchRange = ranges[node.expression];
1082 if (switchRange != null &&
1083 switchRange.lower is IntValue &&
1084 switchRange.upper is IntValue) {
1085 IntValue lowerValue = switchRange.lower;
1086 IntValue upperValue = switchRange.upper;
1087 int lower = lowerValue.value;
1088 int upper = upperValue.value;
1089 Set<int> liveLabels = new Set<int>();
1090 for (int pos = 1; pos < node.inputs.length; pos++) {
1091 HConstant input = node.inputs[pos];
1092 if (!input.isConstantInteger()) continue;
1093 IntConstant constant = input.constant;
1094 int label = constant.value;
1095 if (!liveLabels.contains(label) &&
1096 label <= upper &&
1097 label >= lower) {
1098 markBlockLive(node.block.successors[pos - 1]);
1099 liveLabels.add(label);
1100 }
1101 }
1102 if (liveLabels.length != upper - lower + 1) {
1103 markBlockLive(node.defaultTarget);
1104 } else {
1105 node.isTotal = true;
1106 }
1107 return;
1108 }
1109 }
1110 visitControlFlow(node);
1111 }
1052 } 1112 }
1053 1113
1054 class SsaDeadPhiEliminator implements OptimizationPhase { 1114 class SsaDeadPhiEliminator implements OptimizationPhase {
1055 final String name = "SsaDeadPhiEliminator"; 1115 final String name = "SsaDeadPhiEliminator";
1056 1116
1057 void visitGraph(HGraph graph) { 1117 void visitGraph(HGraph graph) {
1058 final List<HPhi> worklist = <HPhi>[]; 1118 final List<HPhi> worklist = <HPhi>[];
1059 // A set to keep track of the live phis that we found. 1119 // A set to keep track of the live phis that we found.
1060 final Set<HPhi> livePhis = new Set<HPhi>(); 1120 final Set<HPhi> livePhis = new Set<HPhi>();
1061 1121
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after
1968 2028
1969 keyedValues.forEach((receiver, values) { 2029 keyedValues.forEach((receiver, values) {
1970 result.keyedValues[receiver] = 2030 result.keyedValues[receiver] =
1971 new Map<HInstruction, HInstruction>.from(values); 2031 new Map<HInstruction, HInstruction>.from(values);
1972 }); 2032 });
1973 2033
1974 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2034 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
1975 return result; 2035 return result;
1976 } 2036 }
1977 } 2037 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/nodes.dart ('k') | sdk/lib/_internal/compiler/implementation/ssa/tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698