Chromium Code Reviews| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class BailoutInfo { | 7 class BailoutInfo { |
| 8 int instructionId; | 8 int instructionId; |
| 9 int bailoutId; | 9 int bailoutId; |
| 10 BailoutInfo(this.instructionId, this.bailoutId); | 10 BailoutInfo(this.instructionId, this.bailoutId); |
| 11 } | 11 } |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * Keeps track of the execution environment for instructions. An | 14 * Keeps track of the execution environment for instructions. An |
| 15 * execution environment contains the SSA instructions that are live. | 15 * execution environment contains the SSA instructions that are live. |
| 16 */ | 16 */ |
| 17 class Environment { | 17 class Environment { |
| 18 final Set<HInstruction> lives; | 18 final Set<HInstruction> lives; |
| 19 final Set<HBasicBlock> loopMarkers; | 19 final List<HBasicBlock> loopMarkers; |
| 20 Environment() : lives = new Set<HInstruction>(), | 20 Environment() : lives = new Set<HInstruction>(), |
| 21 loopMarkers = new Set<HBasicBlock>(); | 21 loopMarkers = new List<HBasicBlock>(); |
| 22 Environment.from(Environment other) | 22 Environment.from(Environment other) |
| 23 : lives = new Set<HInstruction>.from(other.lives), | 23 : lives = new Set<HInstruction>.from(other.lives), |
| 24 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers); | 24 loopMarkers = new List<HBasicBlock>.from(other.loopMarkers); |
| 25 | 25 |
| 26 void remove(HInstruction instruction) { | 26 void remove(HInstruction instruction) { |
| 27 lives.remove(instruction); | 27 lives.remove(instruction); |
| 28 } | 28 } |
| 29 | 29 |
| 30 void add(HInstruction instruction) { | 30 void add(HInstruction instruction) { |
| 31 // If the instruction is a check, we add its checked input | 31 // If the instruction is a check, we add its checked input |
| 32 // instead. This allows sharing the same environment between | 32 // instead. This allows sharing the same environment between |
| 33 // different type guards. | 33 // different type guards. |
| 34 // | 34 // |
| 35 // Also, we don't need to add code motion invariant instructions | 35 // Also, we don't need to add code motion invariant instructions |
| 36 // in the live set (because we generate them at use-site), except | 36 // in the live set (because we generate them at use-site), except |
| 37 // for parameters that are not 'this', which is always passed as | 37 // for parameters that are not 'this', which is always passed as |
| 38 // the receiver. | 38 // the receiver. |
| 39 if (instruction is HCheck) { | 39 if (instruction is HCheck) { |
| 40 add(instruction.checkedInput); | 40 add(instruction.checkedInput); |
| 41 } else if (!instruction.isCodeMotionInvariant() | 41 } else if (!instruction.isCodeMotionInvariant() |
| 42 || (instruction is HParameterValue && instruction is !HThis)) { | 42 || (instruction is HParameterValue && instruction is !HThis)) { |
| 43 lives.add(instruction); | 43 lives.add(instruction); |
| 44 } else { | 44 } else { |
| 45 for (int i = 0, len = instruction.inputs.length; i < len; i++) { | 45 for (int i = 0, len = instruction.inputs.length; i < len; i++) { |
| 46 add(instruction.inputs[i]); | 46 add(instruction.inputs[i]); |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 | 50 |
| 51 void addLoopMarker(HBasicBlock block) { | |
| 52 loopMarkers.add(block); | |
| 53 } | |
| 54 | |
| 55 void removeLoopMarker(HBasicBlock block) { | |
| 56 loopMarkers.remove(block); | |
| 57 } | |
| 58 | |
| 59 void addAll(Environment other) { | 51 void addAll(Environment other) { |
| 60 lives.addAll(other.lives); | 52 lives.addAll(other.lives); |
| 61 loopMarkers.addAll(other.loopMarkers); | |
| 62 } | 53 } |
| 63 | 54 |
| 64 bool get isEmpty => lives.isEmpty && loopMarkers.isEmpty; | 55 bool get isEmpty => lives.isEmpty && loopMarkers.isEmpty; |
| 56 | |
| 57 String toString() => '${loopMarkers.length}'; | |
|
floitsch
2012/11/20 15:39:31
Remove or make it at least mention "Environment".
ngeoffray
2012/11/20 16:40:37
Removed.
| |
| 65 } | 58 } |
| 66 | 59 |
| 67 | 60 |
| 68 /** | 61 /** |
| 69 * Visits the graph in dominator order and inserts TypeGuards in places where | 62 * Visits the graph in dominator order and inserts TypeGuards in places where |
| 70 * we consider the guard to be of value. | 63 * we consider the guard to be of value. |
| 71 * | 64 * |
| 72 * Might modify the [types] in an inconsistent way. No further analysis should | 65 * Might modify the [types] in an inconsistent way. No further analysis should |
| 73 * rely on them. | 66 * rely on them. |
| 74 */ | 67 */ |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 * | 243 * |
| 251 * At the end of the computation, insert type guards in the graph. | 244 * At the end of the computation, insert type guards in the graph. |
| 252 */ | 245 */ |
| 253 class SsaEnvironmentBuilder extends HBaseVisitor implements OptimizationPhase { | 246 class SsaEnvironmentBuilder extends HBaseVisitor implements OptimizationPhase { |
| 254 final Compiler compiler; | 247 final Compiler compiler; |
| 255 final String name = 'SsaEnvironmentBuilder'; | 248 final String name = 'SsaEnvironmentBuilder'; |
| 256 | 249 |
| 257 final Map<HBailoutTarget, Environment> capturedEnvironments; | 250 final Map<HBailoutTarget, Environment> capturedEnvironments; |
| 258 final Map<HBasicBlock, Environment> liveInstructions; | 251 final Map<HBasicBlock, Environment> liveInstructions; |
| 259 Environment environment; | 252 Environment environment; |
| 253 List<HBasicBlock> loopMarkers; | |
|
floitsch
2012/11/20 15:39:31
Add comment explaining what these contain.
ngeoffray
2012/11/20 16:40:37
Done.
| |
| 260 | 254 |
| 261 SsaEnvironmentBuilder(Compiler this.compiler) | 255 SsaEnvironmentBuilder(Compiler this.compiler) |
| 262 : capturedEnvironments = new Map<HBailoutTarget, Environment>(), | 256 : capturedEnvironments = new Map<HBailoutTarget, Environment>(), |
| 263 liveInstructions = new Map<HBasicBlock, Environment>(); | 257 liveInstructions = new Map<HBasicBlock, Environment>(), |
| 258 loopMarkers = <HBasicBlock>[]; | |
| 264 | 259 |
| 265 | 260 |
| 266 void visitGraph(HGraph graph) { | 261 void visitGraph(HGraph graph) { |
| 267 visitPostDominatorTree(graph); | 262 visitPostDominatorTree(graph); |
| 268 if (!liveInstructions[graph.entry].isEmpty) { | 263 if (!liveInstructions[graph.entry].isEmpty) { |
| 269 compiler.internalError('Bailout environment computation', | 264 compiler.internalError('Bailout environment computation', |
| 270 node: compiler.currentElement.parseNode(compiler)); | 265 node: compiler.currentElement.parseNode(compiler)); |
| 271 } | 266 } |
| 272 updateLoopMarkers(); | 267 updateLoopMarkers(); |
| 273 insertCapturedEnvironments(); | 268 insertCapturedEnvironments(); |
| 274 } | 269 } |
| 275 | 270 |
| 276 void updateLoopMarkers() { | 271 void updateLoopMarkers() { |
| 277 // If the block is a loop header, we need to merge the loop | 272 // If the block is a loop header, we need to merge the loop |
| 278 // header's live instructions into every environment that contains | 273 // header's live instructions into every environment that contains |
| 279 // the loop marker. | 274 // the loop marker. |
| 280 // For example with the following loop (read the example in | 275 // For example with the following loop (read the example in |
| 281 // reverse): | 276 // reverse): |
| 282 // | 277 // |
| 283 // while (true) { <-- (4) update the marker with the environment | 278 // while (true) { <-- (4) update the marker with the environment |
| 284 // use(x); <-- (3) environment = {x} | 279 // use(x); <-- (3) environment = {x} |
| 285 // bailout; <-- (2) has the marker when computed | 280 // bailout; <-- (2) has the marker when computed |
| 286 // } <-- (1) create a loop marker | 281 // } <-- (1) create a loop marker |
| 287 // | 282 // |
| 288 // The bailout instruction first captures the marker, but it | 283 // The bailout instruction first captures the marker, but it |
| 289 // will be replaced by the live environment at the loop entry, | 284 // will be replaced by the live environment at the loop entry, |
| 290 // in this case {x}. | 285 // in this case {x}. |
| 291 capturedEnvironments.forEach((ignoredInstruction, env) { | 286 capturedEnvironments.forEach((ignoredInstruction, env) { |
| 292 env.loopMarkers.forEach((HBasicBlock header) { | 287 env.loopMarkers.forEach((HBasicBlock header) { |
| 293 env.removeLoopMarker(header); | |
| 294 env.addAll(liveInstructions[header]); | 288 env.addAll(liveInstructions[header]); |
| 295 }); | 289 }); |
| 290 env.loopMarkers.clear(); | |
| 296 }); | 291 }); |
| 297 } | 292 } |
| 298 | 293 |
| 299 void visitBasicBlock(HBasicBlock block) { | 294 void visitBasicBlock(HBasicBlock block) { |
| 300 environment = new Environment(); | 295 environment = new Environment(); |
| 301 | 296 |
| 302 // Add to the environment the live instructions of its successor, as well as | 297 // Add to the environment the live instructions of its successor, as well as |
| 303 // the inputs of the phis of the successor that flow from this block. | 298 // the inputs of the phis of the successor that flow from this block. |
| 304 for (int i = 0; i < block.successors.length; i++) { | 299 for (int i = 0; i < block.successors.length; i++) { |
| 305 HBasicBlock successor = block.successors[i]; | 300 HBasicBlock successor = block.successors[i]; |
| 306 Environment successorEnv = liveInstructions[successor]; | 301 Environment successorEnv = liveInstructions[successor]; |
| 307 if (successorEnv != null) { | 302 if (successorEnv != null) { |
| 308 environment.addAll(successorEnv); | 303 environment.addAll(successorEnv); |
| 309 } else { | 304 } else { |
| 310 // If we haven't computed the liveInstructions of that successor, we | 305 // If we haven't computed the liveInstructions of that successor, we |
| 311 // know it must be a loop header. | 306 // know it must be a loop header. |
| 312 assert(successor.isLoopHeader()); | 307 assert(successor.isLoopHeader()); |
| 313 environment.addLoopMarker(successor); | 308 assert(!block.isLoopHeader()); |
| 309 loopMarkers.add(successor); | |
| 314 } | 310 } |
| 315 | 311 |
| 316 int index = successor.predecessors.indexOf(block); | 312 int index = successor.predecessors.indexOf(block); |
| 317 for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) { | 313 for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) { |
| 318 environment.add(phi.inputs[index]); | 314 environment.add(phi.inputs[index]); |
| 319 } | 315 } |
| 320 } | 316 } |
| 321 | 317 |
| 318 // If the block is a loop header, we can remove the loop marker, | |
|
floitsch
2012/11/20 15:39:31
This sounds too much like an optimization.
In fact
ngeoffray
2012/11/20 16:40:37
Improved comment.
| |
| 319 // because it will just recompute the loop phis. | |
| 320 if (block.isLoopHeader()) { | |
| 321 loopMarkers.removeLast(); | |
|
floitsch
2012/11/20 15:39:31
assert that it is the same as block?
ngeoffray
2012/11/20 16:40:37
Done.
ngeoffray
2012/11/20 17:30:45
Actually, I had to change the data structure to be
| |
| 322 } | |
| 323 | |
| 324 environment.loopMarkers.addAll(loopMarkers); | |
| 325 | |
| 322 // Iterate over all instructions to remove an instruction from the | 326 // Iterate over all instructions to remove an instruction from the |
| 323 // environment and add its inputs. | 327 // environment and add its inputs. |
| 324 HInstruction instruction = block.last; | 328 HInstruction instruction = block.last; |
| 325 while (instruction != null) { | 329 while (instruction != null) { |
| 326 instruction.accept(this); | 330 instruction.accept(this); |
| 327 instruction = instruction.previous; | 331 instruction = instruction.previous; |
| 328 } | 332 } |
| 329 | 333 |
| 330 // We just remove the phis from the environment. The inputs of the | 334 // We just remove the phis from the environment. The inputs of the |
| 331 // phis will be put in the environment of the predecessors. | 335 // phis will be put in the environment of the predecessors. |
| 332 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) { | 336 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) { |
| 333 environment.remove(phi); | 337 environment.remove(phi); |
| 334 } | 338 } |
| 335 | 339 |
| 336 // If the block is a loop header, we can remove the loop marker, | |
| 337 // because it will just recompute the loop phis. | |
| 338 if (block.isLoopHeader()) { | |
| 339 environment.removeLoopMarker(block); | |
| 340 } | |
| 341 | |
| 342 // Finally save the liveInstructions of that block. | 340 // Finally save the liveInstructions of that block. |
| 343 liveInstructions[block] = environment; | 341 liveInstructions[block] = environment; |
| 344 } | 342 } |
| 345 | 343 |
| 346 void visitBailoutTarget(HBailoutTarget target) { | 344 void visitBailoutTarget(HBailoutTarget target) { |
| 347 visitInstruction(target); | 345 visitInstruction(target); |
| 348 capturedEnvironments[target] = new Environment.from(environment); | 346 capturedEnvironments[target] = new Environment.from(environment); |
| 349 } | 347 } |
| 350 | 348 |
| 351 void visitInstruction(HInstruction instruction) { | 349 void visitInstruction(HInstruction instruction) { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 hasComplexBailoutTargets = true; | 537 hasComplexBailoutTargets = true; |
| 540 } | 538 } |
| 541 } else { | 539 } else { |
| 542 hasComplexBailoutTargets = true; | 540 hasComplexBailoutTargets = true; |
| 543 blocks.forEach((HBasicBlock block) { | 541 blocks.forEach((HBasicBlock block) { |
| 544 block.bailoutTargets.add(target); | 542 block.bailoutTargets.add(target); |
| 545 }); | 543 }); |
| 546 } | 544 } |
| 547 } | 545 } |
| 548 } | 546 } |
| OLD | NEW |