| 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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 6 import '../common/names.dart' show Selectors; | 6 import '../common/names.dart' show Selectors; |
| 7 import '../common/tasks.dart' show CompilerTask; | 7 import '../common/tasks.dart' show CompilerTask; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
| 9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 import 'value_range_analyzer.dart'; | 28 import 'value_range_analyzer.dart'; |
| 29 import 'value_set.dart'; | 29 import 'value_set.dart'; |
| 30 | 30 |
| 31 abstract class OptimizationPhase { | 31 abstract class OptimizationPhase { |
| 32 String get name; | 32 String get name; |
| 33 void visitGraph(HGraph graph); | 33 void visitGraph(HGraph graph); |
| 34 } | 34 } |
| 35 | 35 |
| 36 class SsaOptimizerTask extends CompilerTask { | 36 class SsaOptimizerTask extends CompilerTask { |
| 37 final JavaScriptBackend backend; | 37 final JavaScriptBackend backend; |
| 38 |
| 39 Map<HInstruction, Range> ranges = <HInstruction, Range>{}; |
| 40 |
| 38 SsaOptimizerTask(JavaScriptBackend backend) | 41 SsaOptimizerTask(JavaScriptBackend backend) |
| 39 : this.backend = backend, | 42 : this.backend = backend, |
| 40 super(backend.compiler.measurer); | 43 super(backend.compiler.measurer); |
| 44 |
| 41 String get name => 'SSA optimizer'; | 45 String get name => 'SSA optimizer'; |
| 46 |
| 42 Compiler get compiler => backend.compiler; | 47 Compiler get compiler => backend.compiler; |
| 43 ClosedWorld get closedWorld => compiler.closedWorld; | |
| 44 Map<HInstruction, Range> ranges = <HInstruction, Range>{}; | |
| 45 | 48 |
| 46 void optimize(CodegenWorkItem work, HGraph graph) { | 49 void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { |
| 47 void runPhase(OptimizationPhase phase) { | 50 void runPhase(OptimizationPhase phase) { |
| 48 measureSubtask(phase.name, () => phase.visitGraph(graph)); | 51 measureSubtask(phase.name, () => phase.visitGraph(graph)); |
| 49 compiler.tracer.traceGraph(phase.name, graph); | 52 backend.tracer.traceGraph(phase.name, graph); |
| 50 assert(graph.isValid()); | 53 assert(graph.isValid()); |
| 51 } | 54 } |
| 52 | 55 |
| 53 ConstantSystem constantSystem = compiler.backend.constantSystem; | 56 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 54 bool trustPrimitives = compiler.options.trustPrimitives; | 57 bool trustPrimitives = compiler.options.trustPrimitives; |
| 55 CodegenRegistry registry = work.registry; | 58 CodegenRegistry registry = work.registry; |
| 56 Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 59 Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| 57 SsaCodeMotion codeMotion; | 60 SsaCodeMotion codeMotion; |
| 58 measure(() { | 61 measure(() { |
| 59 List<OptimizationPhase> phases = <OptimizationPhase>[ | 62 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 60 // Run trivial instruction simplification first to optimize | 63 // Run trivial instruction simplification first to optimize |
| 61 // some patterns useful for type conversion. | 64 // some patterns useful for type conversion. |
| 62 new SsaInstructionSimplifier(constantSystem, backend, this, registry), | 65 new SsaInstructionSimplifier( |
| 66 constantSystem, backend, closedWorld, this, registry), |
| 63 new SsaTypeConversionInserter(closedWorld), | 67 new SsaTypeConversionInserter(closedWorld), |
| 64 new SsaRedundantPhiEliminator(), | 68 new SsaRedundantPhiEliminator(), |
| 65 new SsaDeadPhiEliminator(), | 69 new SsaDeadPhiEliminator(), |
| 66 new SsaTypePropagator(compiler), | 70 new SsaTypePropagator(compiler, closedWorld), |
| 67 // After type propagation, more instructions can be | 71 // After type propagation, more instructions can be |
| 68 // simplified. | 72 // simplified. |
| 69 new SsaInstructionSimplifier(constantSystem, backend, this, registry), | 73 new SsaInstructionSimplifier( |
| 74 constantSystem, backend, closedWorld, this, registry), |
| 70 new SsaCheckInserter( | 75 new SsaCheckInserter( |
| 71 trustPrimitives, backend, closedWorld, boundsChecked), | 76 trustPrimitives, backend, closedWorld, boundsChecked), |
| 72 new SsaInstructionSimplifier(constantSystem, backend, this, registry), | 77 new SsaInstructionSimplifier( |
| 78 constantSystem, backend, closedWorld, this, registry), |
| 73 new SsaCheckInserter( | 79 new SsaCheckInserter( |
| 74 trustPrimitives, backend, closedWorld, boundsChecked), | 80 trustPrimitives, backend, closedWorld, boundsChecked), |
| 75 new SsaTypePropagator(compiler), | 81 new SsaTypePropagator(compiler, closedWorld), |
| 76 // Run a dead code eliminator before LICM because dead | 82 // Run a dead code eliminator before LICM because dead |
| 77 // interceptors are often in the way of LICM'able instructions. | 83 // interceptors are often in the way of LICM'able instructions. |
| 78 new SsaDeadCodeEliminator(compiler, this), | 84 new SsaDeadCodeEliminator(compiler, closedWorld, this), |
| 79 new SsaGlobalValueNumberer(compiler), | 85 new SsaGlobalValueNumberer(compiler), |
| 80 // After GVN, some instructions might need their type to be | 86 // After GVN, some instructions might need their type to be |
| 81 // updated because they now have different inputs. | 87 // updated because they now have different inputs. |
| 82 new SsaTypePropagator(compiler), | 88 new SsaTypePropagator(compiler, closedWorld), |
| 83 codeMotion = new SsaCodeMotion(), | 89 codeMotion = new SsaCodeMotion(), |
| 84 new SsaLoadElimination(compiler), | 90 new SsaLoadElimination(compiler, closedWorld), |
| 85 new SsaRedundantPhiEliminator(), | 91 new SsaRedundantPhiEliminator(), |
| 86 new SsaDeadPhiEliminator(), | 92 new SsaDeadPhiEliminator(), |
| 87 new SsaTypePropagator(compiler), | 93 new SsaTypePropagator(compiler, closedWorld), |
| 88 new SsaValueRangeAnalyzer(compiler, constantSystem, this), | 94 new SsaValueRangeAnalyzer(compiler, closedWorld, constantSystem, this), |
| 89 // Previous optimizations may have generated new | 95 // Previous optimizations may have generated new |
| 90 // opportunities for instruction simplification. | 96 // opportunities for instruction simplification. |
| 91 new SsaInstructionSimplifier(constantSystem, backend, this, registry), | 97 new SsaInstructionSimplifier( |
| 98 constantSystem, backend, closedWorld, this, registry), |
| 92 new SsaCheckInserter( | 99 new SsaCheckInserter( |
| 93 trustPrimitives, backend, closedWorld, boundsChecked), | 100 trustPrimitives, backend, closedWorld, boundsChecked), |
| 94 ]; | 101 ]; |
| 95 phases.forEach(runPhase); | 102 phases.forEach(runPhase); |
| 96 | 103 |
| 97 // Simplifying interceptors is not strictly just an optimization, it is | 104 // Simplifying interceptors is not strictly just an optimization, it is |
| 98 // required for implementation correctness because the code generator | 105 // required for implementation correctness because the code generator |
| 99 // assumes it is always performed. | 106 // assumes it is always performed. |
| 100 runPhase( | 107 runPhase(new SsaSimplifyInterceptors( |
| 101 new SsaSimplifyInterceptors(compiler, constantSystem, work.element)); | 108 compiler, closedWorld, constantSystem, work.element)); |
| 102 | 109 |
| 103 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(compiler, this); | 110 SsaDeadCodeEliminator dce = |
| 111 new SsaDeadCodeEliminator(compiler, closedWorld, this); |
| 104 runPhase(dce); | 112 runPhase(dce); |
| 105 if (codeMotion.movedCode || dce.eliminatedSideEffects) { | 113 if (codeMotion.movedCode || dce.eliminatedSideEffects) { |
| 106 phases = <OptimizationPhase>[ | 114 phases = <OptimizationPhase>[ |
| 107 new SsaTypePropagator(compiler), | 115 new SsaTypePropagator(compiler, closedWorld), |
| 108 new SsaGlobalValueNumberer(compiler), | 116 new SsaGlobalValueNumberer(compiler), |
| 109 new SsaCodeMotion(), | 117 new SsaCodeMotion(), |
| 110 new SsaValueRangeAnalyzer(compiler, constantSystem, this), | 118 new SsaValueRangeAnalyzer( |
| 111 new SsaInstructionSimplifier(constantSystem, backend, this, registry), | 119 compiler, closedWorld, constantSystem, this), |
| 120 new SsaInstructionSimplifier( |
| 121 constantSystem, backend, closedWorld, this, registry), |
| 112 new SsaCheckInserter( | 122 new SsaCheckInserter( |
| 113 trustPrimitives, backend, closedWorld, boundsChecked), | 123 trustPrimitives, backend, closedWorld, boundsChecked), |
| 114 new SsaSimplifyInterceptors(compiler, constantSystem, work.element), | 124 new SsaSimplifyInterceptors( |
| 115 new SsaDeadCodeEliminator(compiler, this), | 125 compiler, closedWorld, constantSystem, work.element), |
| 126 new SsaDeadCodeEliminator(compiler, closedWorld, this), |
| 116 ]; | 127 ]; |
| 117 } else { | 128 } else { |
| 118 phases = <OptimizationPhase>[ | 129 phases = <OptimizationPhase>[ |
| 119 new SsaTypePropagator(compiler), | 130 new SsaTypePropagator(compiler, closedWorld), |
| 120 // Run the simplifier to remove unneeded type checks inserted by | 131 // Run the simplifier to remove unneeded type checks inserted by |
| 121 // type propagation. | 132 // type propagation. |
| 122 new SsaInstructionSimplifier(constantSystem, backend, this, registry), | 133 new SsaInstructionSimplifier( |
| 134 constantSystem, backend, closedWorld, this, registry), |
| 123 ]; | 135 ]; |
| 124 } | 136 } |
| 125 phases.forEach(runPhase); | 137 phases.forEach(runPhase); |
| 126 }); | 138 }); |
| 127 } | 139 } |
| 128 } | 140 } |
| 129 | 141 |
| 130 /// Returns `true` if [mask] represents only types that have a length that | 142 /// Returns `true` if [mask] represents only types that have a length that |
| 131 /// cannot change. The current implementation is conservative for the purpose | 143 /// cannot change. The current implementation is conservative for the purpose |
| 132 /// of identifying gvn-able lengths and mis-identifies some unions of fixed | 144 /// of identifying gvn-able lengths and mis-identifies some unions of fixed |
| 133 /// length indexables (see TODO) as not fixed length. | 145 /// length indexables (see TODO) as not fixed length. |
| 134 bool isFixedLength(mask, Compiler compiler) { | 146 bool isFixedLength(mask, ClosedWorld closedWorld) { |
| 135 ClosedWorld closedWorld = compiler.closedWorld; | |
| 136 JavaScriptBackend backend = compiler.backend; | |
| 137 if (mask.isContainer && mask.length != null) { | 147 if (mask.isContainer && mask.length != null) { |
| 138 // A container on which we have inferred the length. | 148 // A container on which we have inferred the length. |
| 139 return true; | 149 return true; |
| 140 } | 150 } |
| 141 // TODO(sra): Recognize any combination of fixed length indexables. | 151 // TODO(sra): Recognize any combination of fixed length indexables. |
| 142 if (mask.containsOnly(closedWorld.backendClasses.fixedListImplementation) || | 152 if (mask.containsOnly(closedWorld.backendClasses.fixedListImplementation) || |
| 143 mask.containsOnly(closedWorld.backendClasses.constListImplementation) || | 153 mask.containsOnly(closedWorld.backendClasses.constListImplementation) || |
| 144 mask.containsOnlyString(closedWorld) || | 154 mask.containsOnlyString(closedWorld) || |
| 145 closedWorld.commonMasks.isTypedArray(mask)) { | 155 closedWorld.commonMasks.isTypedArray(mask)) { |
| 146 return true; | 156 return true; |
| 147 } | 157 } |
| 148 return false; | 158 return false; |
| 149 } | 159 } |
| 150 | 160 |
| 151 /** | 161 /** |
| 152 * If both inputs to known operations are available execute the operation at | 162 * If both inputs to known operations are available execute the operation at |
| 153 * compile-time. | 163 * compile-time. |
| 154 */ | 164 */ |
| 155 class SsaInstructionSimplifier extends HBaseVisitor | 165 class SsaInstructionSimplifier extends HBaseVisitor |
| 156 implements OptimizationPhase { | 166 implements OptimizationPhase { |
| 157 // We don't produce constant-folded strings longer than this unless they have | 167 // We don't produce constant-folded strings longer than this unless they have |
| 158 // a single use. This protects against exponentially large constant folded | 168 // a single use. This protects against exponentially large constant folded |
| 159 // strings. | 169 // strings. |
| 160 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; | 170 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; |
| 161 | 171 |
| 162 final String name = "SsaInstructionSimplifier"; | 172 final String name = "SsaInstructionSimplifier"; |
| 163 final JavaScriptBackend backend; | 173 final JavaScriptBackend backend; |
| 174 final ClosedWorld closedWorld; |
| 164 final ConstantSystem constantSystem; | 175 final ConstantSystem constantSystem; |
| 165 final CodegenRegistry registry; | 176 final CodegenRegistry registry; |
| 166 HGraph graph; | 177 HGraph graph; |
| 167 Compiler get compiler => backend.compiler; | 178 Compiler get compiler => backend.compiler; |
| 168 final SsaOptimizerTask optimizer; | 179 final SsaOptimizerTask optimizer; |
| 169 | 180 |
| 170 SsaInstructionSimplifier( | 181 SsaInstructionSimplifier(this.constantSystem, this.backend, this.closedWorld, |
| 171 this.constantSystem, this.backend, this.optimizer, this.registry); | 182 this.optimizer, this.registry); |
| 172 | |
| 173 ClosedWorld get closedWorld => compiler.closedWorld; | |
| 174 | 183 |
| 175 CommonElements get commonElements => closedWorld.commonElements; | 184 CommonElements get commonElements => closedWorld.commonElements; |
| 176 | 185 |
| 177 BackendHelpers get helpers => backend.helpers; | 186 BackendHelpers get helpers => backend.helpers; |
| 178 | 187 |
| 179 GlobalTypeInferenceResults get globalInferenceResults => | 188 GlobalTypeInferenceResults get globalInferenceResults => |
| 180 compiler.globalInference.results; | 189 compiler.globalInference.results; |
| 181 | 190 |
| 182 void visitGraph(HGraph visitee) { | 191 void visitGraph(HGraph visitee) { |
| 183 graph = visitee; | 192 graph = visitee; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 if (actualReceiver.isConstantString()) { | 345 if (actualReceiver.isConstantString()) { |
| 337 HConstant constantInput = actualReceiver; | 346 HConstant constantInput = actualReceiver; |
| 338 StringConstantValue constant = constantInput.constant; | 347 StringConstantValue constant = constantInput.constant; |
| 339 return graph.addConstantInt(constant.length, compiler); | 348 return graph.addConstantInt(constant.length, compiler); |
| 340 } else if (actualReceiver.isConstantList()) { | 349 } else if (actualReceiver.isConstantList()) { |
| 341 HConstant constantInput = actualReceiver; | 350 HConstant constantInput = actualReceiver; |
| 342 ListConstantValue constant = constantInput.constant; | 351 ListConstantValue constant = constantInput.constant; |
| 343 return graph.addConstantInt(constant.length, compiler); | 352 return graph.addConstantInt(constant.length, compiler); |
| 344 } | 353 } |
| 345 MemberElement element = helpers.jsIndexableLength; | 354 MemberElement element = helpers.jsIndexableLength; |
| 346 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler); | 355 bool isFixed = isFixedLength(actualReceiver.instructionType, closedWorld); |
| 347 TypeMask actualType = node.instructionType; | 356 TypeMask actualType = node.instructionType; |
| 348 TypeMask resultType = closedWorld.commonMasks.positiveIntType; | 357 TypeMask resultType = closedWorld.commonMasks.positiveIntType; |
| 349 // If we already have computed a more specific type, keep that type. | 358 // If we already have computed a more specific type, keep that type. |
| 350 if (HInstruction.isInstanceOf( | 359 if (HInstruction.isInstanceOf( |
| 351 actualType, helpers.jsUInt31Class, closedWorld)) { | 360 actualType, helpers.jsUInt31Class, closedWorld)) { |
| 352 resultType = closedWorld.commonMasks.uint31Type; | 361 resultType = closedWorld.commonMasks.uint31Type; |
| 353 } else if (HInstruction.isInstanceOf( | 362 } else if (HInstruction.isInstanceOf( |
| 354 actualType, helpers.jsUInt32Class, closedWorld)) { | 363 actualType, helpers.jsUInt32Class, closedWorld)) { |
| 355 resultType = closedWorld.commonMasks.uint32Type; | 364 resultType = closedWorld.commonMasks.uint32Type; |
| 356 } | 365 } |
| (...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 instruction = instruction.accept(this); | 1332 instruction = instruction.accept(this); |
| 1324 instruction = next; | 1333 instruction = next; |
| 1325 } | 1334 } |
| 1326 } | 1335 } |
| 1327 | 1336 |
| 1328 HBoundsCheck insertBoundsCheck( | 1337 HBoundsCheck insertBoundsCheck( |
| 1329 HInstruction indexNode, HInstruction array, HInstruction indexArgument) { | 1338 HInstruction indexNode, HInstruction array, HInstruction indexArgument) { |
| 1330 Compiler compiler = backend.compiler; | 1339 Compiler compiler = backend.compiler; |
| 1331 HFieldGet length = new HFieldGet(helpers.jsIndexableLength, array, | 1340 HFieldGet length = new HFieldGet(helpers.jsIndexableLength, array, |
| 1332 closedWorld.commonMasks.positiveIntType, | 1341 closedWorld.commonMasks.positiveIntType, |
| 1333 isAssignable: !isFixedLength(array.instructionType, compiler)); | 1342 isAssignable: !isFixedLength(array.instructionType, closedWorld)); |
| 1334 indexNode.block.addBefore(indexNode, length); | 1343 indexNode.block.addBefore(indexNode, length); |
| 1335 | 1344 |
| 1336 TypeMask type = indexArgument.isPositiveInteger(closedWorld) | 1345 TypeMask type = indexArgument.isPositiveInteger(closedWorld) |
| 1337 ? indexArgument.instructionType | 1346 ? indexArgument.instructionType |
| 1338 : closedWorld.commonMasks.positiveIntType; | 1347 : closedWorld.commonMasks.positiveIntType; |
| 1339 HBoundsCheck check = new HBoundsCheck(indexArgument, length, array, type); | 1348 HBoundsCheck check = new HBoundsCheck(indexArgument, length, array, type); |
| 1340 indexNode.block.addBefore(indexNode, check); | 1349 indexNode.block.addBefore(indexNode, check); |
| 1341 // If the index input to the bounds check was not known to be an integer | 1350 // If the index input to the bounds check was not known to be an integer |
| 1342 // then we replace its uses with the bounds check, which is known to be an | 1351 // then we replace its uses with the bounds check, which is known to be an |
| 1343 // integer. However, if the input was already an integer we don't do this | 1352 // integer. However, if the input was already an integer we don't do this |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 HInstruction minusOne = graph.addConstantInt(-1, backend.compiler); | 1385 HInstruction minusOne = graph.addConstantInt(-1, backend.compiler); |
| 1377 check.inputs.add(minusOne); | 1386 check.inputs.add(minusOne); |
| 1378 minusOne.usedBy.add(check); | 1387 minusOne.usedBy.add(check); |
| 1379 } | 1388 } |
| 1380 } | 1389 } |
| 1381 | 1390 |
| 1382 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { | 1391 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
| 1383 final String name = "SsaDeadCodeEliminator"; | 1392 final String name = "SsaDeadCodeEliminator"; |
| 1384 | 1393 |
| 1385 final Compiler compiler; | 1394 final Compiler compiler; |
| 1395 final ClosedWorld closedWorld; |
| 1386 final SsaOptimizerTask optimizer; | 1396 final SsaOptimizerTask optimizer; |
| 1387 SsaLiveBlockAnalyzer analyzer; | 1397 SsaLiveBlockAnalyzer analyzer; |
| 1388 Map<HInstruction, bool> trivialDeadStoreReceivers = | 1398 Map<HInstruction, bool> trivialDeadStoreReceivers = |
| 1389 new Maplet<HInstruction, bool>(); | 1399 new Maplet<HInstruction, bool>(); |
| 1390 bool eliminatedSideEffects = false; | 1400 bool eliminatedSideEffects = false; |
| 1391 | 1401 |
| 1392 SsaDeadCodeEliminator(this.compiler, this.optimizer); | 1402 SsaDeadCodeEliminator(this.compiler, this.closedWorld, this.optimizer); |
| 1393 | |
| 1394 ClosedWorld get closedWorld => compiler.closedWorld; | |
| 1395 | 1403 |
| 1396 HInstruction zapInstructionCache; | 1404 HInstruction zapInstructionCache; |
| 1397 HInstruction get zapInstruction { | 1405 HInstruction get zapInstruction { |
| 1398 if (zapInstructionCache == null) { | 1406 if (zapInstructionCache == null) { |
| 1399 // A constant with no type does not pollute types at phi nodes. | 1407 // A constant with no type does not pollute types at phi nodes. |
| 1400 ConstantValue constant = new SyntheticConstantValue( | 1408 ConstantValue constant = new SyntheticConstantValue( |
| 1401 SyntheticConstantKind.EMPTY_VALUE, const TypeMask.nonNullEmpty()); | 1409 SyntheticConstantKind.EMPTY_VALUE, const TypeMask.nonNullEmpty()); |
| 1402 zapInstructionCache = analyzer.graph.addConstant(constant, compiler); | 1410 zapInstructionCache = analyzer.graph.addConstant(constant, compiler); |
| 1403 } | 1411 } |
| 1404 return zapInstructionCache; | 1412 return zapInstructionCache; |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2221 } | 2229 } |
| 2222 } | 2230 } |
| 2223 | 2231 |
| 2224 /** | 2232 /** |
| 2225 * Optimization phase that tries to eliminate memory loads (for | 2233 * Optimization phase that tries to eliminate memory loads (for |
| 2226 * example [HFieldGet]), when it knows the value stored in that memory | 2234 * example [HFieldGet]), when it knows the value stored in that memory |
| 2227 * location. | 2235 * location. |
| 2228 */ | 2236 */ |
| 2229 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { | 2237 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
| 2230 final Compiler compiler; | 2238 final Compiler compiler; |
| 2239 final ClosedWorld closedWorld; |
| 2231 final String name = "SsaLoadElimination"; | 2240 final String name = "SsaLoadElimination"; |
| 2232 MemorySet memorySet; | 2241 MemorySet memorySet; |
| 2233 List<MemorySet> memories; | 2242 List<MemorySet> memories; |
| 2234 | 2243 |
| 2235 SsaLoadElimination(this.compiler); | 2244 SsaLoadElimination(this.compiler, this.closedWorld); |
| 2236 | |
| 2237 ClosedWorld get closedWorld => compiler.closedWorld; | |
| 2238 | 2245 |
| 2239 void visitGraph(HGraph graph) { | 2246 void visitGraph(HGraph graph) { |
| 2240 memories = new List<MemorySet>(graph.blocks.length); | 2247 memories = new List<MemorySet>(graph.blocks.length); |
| 2241 List<HBasicBlock> blocks = graph.blocks; | 2248 List<HBasicBlock> blocks = graph.blocks; |
| 2242 for (int i = 0; i < blocks.length; i++) { | 2249 for (int i = 0; i < blocks.length; i++) { |
| 2243 HBasicBlock block = blocks[i]; | 2250 HBasicBlock block = blocks[i]; |
| 2244 visitBasicBlock(block); | 2251 visitBasicBlock(block); |
| 2245 if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) { | 2252 if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) { |
| 2246 // We've reached the ending block of a loop. Iterate over the | 2253 // We've reached the ending block of a loop. Iterate over the |
| 2247 // blocks of the loop again to take values that flow from that | 2254 // blocks of the loop again to take values that flow from that |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 | 2753 |
| 2747 keyedValues.forEach((receiver, values) { | 2754 keyedValues.forEach((receiver, values) { |
| 2748 result.keyedValues[receiver] = | 2755 result.keyedValues[receiver] = |
| 2749 new Map<HInstruction, HInstruction>.from(values); | 2756 new Map<HInstruction, HInstruction>.from(values); |
| 2750 }); | 2757 }); |
| 2751 | 2758 |
| 2752 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2759 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2753 return result; | 2760 return result; |
| 2754 } | 2761 } |
| 2755 } | 2762 } |
| OLD | NEW |