| Index: frog/leg/ssa/bailout.dart
|
| ===================================================================
|
| --- frog/leg/ssa/bailout.dart (revision 5925)
|
| +++ frog/leg/ssa/bailout.dart (working copy)
|
| @@ -1,366 +0,0 @@
|
| -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -class BailoutInfo {
|
| - int instructionId;
|
| - int bailoutId;
|
| - BailoutInfo(this.instructionId, this.bailoutId);
|
| -}
|
| -
|
| -/**
|
| - * Keeps track of the execution environment for instructions. An
|
| - * execution environment contains the SSA instructions that are live.
|
| - */
|
| -class Environment {
|
| - final Set<HInstruction> lives;
|
| - final Set<HBasicBlock> loopMarkers;
|
| - Environment() : lives = new Set<HInstruction>(),
|
| - loopMarkers = new Set<HBasicBlock>();
|
| - Environment.from(Environment other)
|
| - : lives = new Set<HInstruction>.from(other.lives),
|
| - loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
|
| -
|
| - Environment.forLoopBody(Environment other)
|
| - : lives = new Set<HInstruction>(),
|
| - loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
|
| -
|
| - void remove(HInstruction instruction) {
|
| - lives.remove(instruction);
|
| - }
|
| -
|
| - void add(HInstruction instruction) {
|
| - if (!instruction.isCodeMotionInvariant()) {
|
| - lives.add(instruction);
|
| - } else {
|
| - for (int i = 0, len = instruction.inputs.length; i < len; i++) {
|
| - add(instruction.inputs[i]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void addLoopMarker(HBasicBlock block) {
|
| - loopMarkers.add(block);
|
| - }
|
| -
|
| - void removeLoopMarker(HBasicBlock block) {
|
| - loopMarkers.remove(block);
|
| - }
|
| -
|
| - void addAll(Environment other) {
|
| - lives.addAll(other.lives);
|
| - loopMarkers.addAll(other.loopMarkers);
|
| - }
|
| -
|
| - List<HInstruction> buildAndSetLast(HInstruction instruction) {
|
| - remove(instruction);
|
| - List<HInstruction> result = new List<HInstruction>.from(lives);
|
| - result.addLast(instruction);
|
| - add(instruction);
|
| - return result;
|
| - }
|
| -
|
| - bool isEmpty() => lives.isEmpty();
|
| - bool contains(HInstruction instruction) => lives.contains(instruction);
|
| - bool containsLoopMarker(HBasicBlock block) => loopMarkers.contains(block);
|
| - void clear() => lives.clear();
|
| -}
|
| -
|
| -/**
|
| - * Computes the environment for each SSA instruction: visits the graph
|
| - * in post-dominator order. Removes an instruction from the environment
|
| - * and adds its inputs to the environment at the instruction's
|
| - * definition.
|
| - *
|
| - * At the end of the computation, insert type guards in the graph.
|
| - */
|
| -class SsaTypeGuardBuilder extends HBaseVisitor implements OptimizationPhase {
|
| - final Compiler compiler;
|
| - final WorkItem work;
|
| - final String name = 'SsaTypeGuardBuilder';
|
| - Environment environment;
|
| - SubGraph subGraph;
|
| -
|
| - final Map<HInstruction, Environment> capturedEnvironments;
|
| -
|
| - SsaTypeGuardBuilder(Compiler this.compiler, WorkItem this.work)
|
| - : capturedEnvironments = new Map<HInstruction, Environment>();
|
| -
|
| -
|
| - void visitGraph(HGraph graph) {
|
| - subGraph = new SubGraph(graph.entry, graph.exit);
|
| - environment = new Environment();
|
| - visitBasicBlock(graph.entry);
|
| - if (!environment.isEmpty()) {
|
| - compiler.internalError('Bailout environment computation',
|
| - node: compiler.currentElement.parseNode(compiler));
|
| - }
|
| - insertCapturedEnvironments();
|
| - }
|
| -
|
| - void maybeCaptureEnvironment(HInstruction instruction) {
|
| - if (shouldCaptureEnvironment(instruction)) {
|
| - capturedEnvironments[instruction] = new Environment.from(environment);
|
| - }
|
| - }
|
| -
|
| - void visitSubGraph(SubGraph newSubGraph) {
|
| - SubGraph oldSubGraph = subGraph;
|
| - subGraph = newSubGraph;
|
| - visitBasicBlock(subGraph.start);
|
| - subGraph = oldSubGraph;
|
| - }
|
| -
|
| - void visitBasicBlock(HBasicBlock block) {
|
| - if (!subGraph.contains(block)) return;
|
| - block.last.accept(this);
|
| -
|
| - HInstruction instruction = block.last.previous;
|
| - while (instruction != null) {
|
| - HInstruction previous = instruction.previous;
|
| - instruction.accept(this);
|
| - instruction = previous;
|
| - }
|
| -
|
| - for (HPhi phi = block.phis.first; phi != null; phi = phi.next) {
|
| - phi.accept(this);
|
| - }
|
| -
|
| - if (block.isLoopHeader()) {
|
| - // If the block is a loop header, we need to change every uses
|
| - // of its loop marker to the current set of live instructions.
|
| - // For example with the following loop (read the example in
|
| - // reverse):
|
| - //
|
| - // while (true) { <-- (4) update the marker with the environment
|
| - // use(x); <-- (3) environment = {x}
|
| - // bailout; <-- (2) has the marker when computed
|
| - // } <-- (1) create a loop marker
|
| - //
|
| - // The bailout instruction first captures the marker, but it
|
| - // will be replaced by the live environment at the loop entry,
|
| - // in this case {x}.
|
| - environment.removeLoopMarker(block);
|
| - capturedEnvironments.forEach((instruction, env) {
|
| - if (env.containsLoopMarker(block)) {
|
| - env.removeLoopMarker(block);
|
| - env.addAll(environment);
|
| - }
|
| - });
|
| - }
|
| - }
|
| -
|
| - void visitPhi(HPhi phi) {
|
| - maybeCaptureEnvironment(phi);
|
| - environment.remove(phi);
|
| - // If the block is a loop header, we insert the incoming values of
|
| - // the phis, and remove the loop values.
|
| - // If the block is not a loop header, the phi will be handled by
|
| - // the control flow instruction.
|
| - if (phi.block.isLoopHeader()) {
|
| - environment.add(phi.inputs[0]);
|
| - for (int i = 1, len = phi.inputs.length; i < len; i++) {
|
| - environment.remove(phi.inputs[i]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void visitInstruction(HInstruction instruction) {
|
| - maybeCaptureEnvironment(instruction);
|
| - environment.remove(instruction);
|
| - for (int i = 0, len = instruction.inputs.length; i < len; i++) {
|
| - environment.add(instruction.inputs[i]);
|
| - }
|
| - }
|
| -
|
| - void visitIf(HIf instruction) {
|
| - HIfBlockInformation info = instruction.blockInformation;
|
| - HBasicBlock joinBlock = info.joinBlock;
|
| -
|
| - if (joinBlock != null) {
|
| - visitBasicBlock(joinBlock);
|
| - }
|
| - Environment thenEnvironment = new Environment.from(environment);
|
| - Environment elseEnvironment = environment;
|
| -
|
| - if (joinBlock != null) {
|
| - for (HPhi phi = joinBlock.phis.first; phi != null; phi = phi.next) {
|
| - if (joinBlock.predecessors[0] == instruction.block) {
|
| - // We're dealing with an 'if' without an else branch.
|
| - thenEnvironment.add(phi.inputs[1]);
|
| - elseEnvironment.add(phi.inputs[0]);
|
| - } else {
|
| - thenEnvironment.add(phi.inputs[0]);
|
| - elseEnvironment.add(phi.inputs[1]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (instruction.hasElse) {
|
| - environment = elseEnvironment;
|
| - visitSubGraph(info.elseGraph);
|
| - elseEnvironment = environment;
|
| - }
|
| -
|
| - environment = thenEnvironment;
|
| - visitSubGraph(info.thenGraph);
|
| - environment.addAll(elseEnvironment);
|
| - }
|
| -
|
| - void visitGoto(HGoto goto) {
|
| - HBasicBlock block = goto.block;
|
| - if (block.successors[0].dominator != block) return;
|
| - visitBasicBlock(block.successors[0]);
|
| - }
|
| -
|
| - void visitBreak(HBreak breakInstruction) {
|
| - compiler.unimplemented("SsaEnvironmentBuilder.visitBreak");
|
| - }
|
| -
|
| - void visitLoopBranch(HLoopBranch branch) {
|
| - HBasicBlock block = branch.block;
|
| -
|
| - // Visit the code after the loop.
|
| - visitBasicBlock(block.successors[1]);
|
| -
|
| - Environment joinEnvironment = environment;
|
| -
|
| - // When visiting the loop body, we don't require the live
|
| - // instructions after the loop body to be in the environment. They
|
| - // will be either recomputed in the loop header, or inserted
|
| - // with the loop marker. We still need to transfer existing loop
|
| - // markers from the current environment, because they must be live
|
| - // for this loop body.
|
| - environment = new Environment.forLoopBody(environment);
|
| -
|
| - // Put the loop phis in the environment.
|
| - HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
|
| - for (HPhi phi = header.phis.first; phi != null; phi = phi.next) {
|
| - for (int i = 1, len = phi.inputs.length; i < len; i++) {
|
| - environment.add(phi.inputs[i]);
|
| - }
|
| - }
|
| -
|
| - // Add the loop marker
|
| - environment.addLoopMarker(header);
|
| -
|
| - if (!branch.isDoWhile()) {
|
| - assert(block.successors[0] == block.dominatedBlocks[0]);
|
| - visitBasicBlock(block.successors[0]);
|
| - }
|
| -
|
| - // We merge the environment required by the code after the loop,
|
| - // and the code inside the loop.
|
| - environment.addAll(joinEnvironment);
|
| - }
|
| -
|
| - // Deal with all kinds of control flow instructions. In case we add
|
| - // a new one, we will hit an internal error.
|
| - void visitExit(HExit exit) {}
|
| -
|
| - void visitReturn(HReturn instruction) {
|
| - environment.clear();
|
| - visitInstruction(instruction);
|
| - }
|
| -
|
| - void visitThrow(HThrow instruction) {
|
| - environment.clear();
|
| - visitInstruction(instruction);
|
| - }
|
| -
|
| - void visitControlFlow(HControlFlow instruction) {
|
| - compiler.internalError('Control flow instructions already dealt with.',
|
| - instruction: instruction);
|
| - }
|
| -
|
| - bool shouldCaptureEnvironment(HInstruction instruction) {
|
| - return instruction.type.isKnown() && !instruction.hasExpectedType();
|
| - }
|
| -
|
| - void insertCapturedEnvironments() {
|
| - work.guards = <HTypeGuard>[];
|
| - int state = 1;
|
| - capturedEnvironments.forEach((HInstruction instruction, Environment env) {
|
| - List<HInstruction> inputs = env.buildAndSetLast(instruction);
|
| - HTypeGuard guard = new HTypeGuard(state++, inputs);
|
| - work.guards.add(guard);
|
| - instruction.block.rewrite(instruction, guard);
|
| - HInstruction insertionPoint = (instruction is HPhi)
|
| - ? instruction.block.first
|
| - : instruction.next;
|
| - insertionPoint.block.addBefore(insertionPoint, guard);
|
| - });
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Propagates bailout information to blocks that need it. This visitor
|
| - * is run before codegen, to know which blocks have to deal with
|
| - * bailouts.
|
| - */
|
| -class SsaBailoutPropagator extends HBaseVisitor {
|
| - final Compiler compiler;
|
| - final List<HBasicBlock> blocks;
|
| -
|
| - SsaBailoutPropagator(Compiler this.compiler) : blocks = <HBasicBlock>[];
|
| -
|
| - void visitGraph(HGraph graph) {
|
| - blocks.addLast(graph.entry);
|
| - visitBasicBlock(graph.entry);
|
| - }
|
| -
|
| - void visitBasicBlock(HBasicBlock block) {
|
| - if (block.isLoopHeader()) blocks.addLast(block);
|
| - HInstruction instruction = block.first;
|
| - while (instruction != null) {
|
| - instruction.accept(this);
|
| - instruction = instruction.next;
|
| - }
|
| - }
|
| -
|
| - void enterBlock(HBasicBlock block) {
|
| - if (block == null) return;
|
| - blocks.addLast(block);
|
| - visitBasicBlock(block);
|
| - blocks.removeLast();
|
| - }
|
| -
|
| - void visitIf(HIf instruction) {
|
| - enterBlock(instruction.thenBlock);
|
| - enterBlock(instruction.elseBlock);
|
| - enterBlock(instruction.joinBlock);
|
| - }
|
| -
|
| - void visitGoto(HGoto goto) {
|
| - HBasicBlock block = goto.block;
|
| - if (block.successors[0].dominator != block) return;
|
| - visitBasicBlock(block.successors[0]);
|
| - }
|
| -
|
| - void visitLoopBranch(HLoopBranch branch) {
|
| - HBasicBlock branchBlock = branch.block;
|
| - if (!branch.isDoWhile()) {
|
| - // Not a do while loop. We visit the body of the loop.
|
| - visitBasicBlock(branchBlock.dominatedBlocks[0]);
|
| - }
|
| - blocks.removeLast();
|
| - visitBasicBlock(branchBlock.successors[1]);
|
| - }
|
| -
|
| - // Deal with all kinds of control flow instructions. In case we add
|
| - // a new one, we will hit an internal error.
|
| - void visitExit(HExit exit) {}
|
| - void visitReturn(HReturn instruction) {}
|
| - void visitThrow(HThrow instruction) {}
|
| -
|
| - void visitControlFlow(HControlFlow instruction) {
|
| - compiler.internalError('Control flow instructions already dealt with.',
|
| - instruction: instruction);
|
| - }
|
| -
|
| - visitTypeGuard(HTypeGuard guard) {
|
| - blocks.forEach((HBasicBlock block) {
|
| - block.guards.add(guard);
|
| - });
|
| - }
|
| -}
|
|
|