Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| index 05bf6969af85fecc1d26e07c7f5abbc09f1f6fbb..052b8cf53c1c207a7195eb2935917b9f3b59173d 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| @@ -885,29 +885,8 @@ class SwitchCaseJumpHandler extends TargetJumpHandler { |
| } |
| } |
| -class SsaBuilder extends ResolvedVisitor implements Visitor { |
| - final SsaBuilderTask builder; |
| - final JavaScriptBackend backend; |
| - final CodegenWorkItem work; |
| - final ConstantSystem constantSystem; |
| - HGraph graph; |
| - LocalsHandler localsHandler; |
| - HInstruction rethrowableException; |
| - Map<Element, HInstruction> parameters; |
| - final RuntimeTypes rti; |
| - HParameterValue lastAddedParameter; |
| - |
| - Map<TargetElement, JumpHandler> jumpTargets; |
| - |
| - /** |
| - * Variables stored in the current activation. These variables are |
| - * being updated in try/catch blocks, and should be |
| - * accessed indirectly through [HLocalGet] and [HLocalSet]. |
| - */ |
| - Map<Element, HLocalValue> activationVariables; |
| - |
| - // We build the Ssa graph by simulating a stack machine. |
| - List<HInstruction> stack; |
| +class SsaGraphBuilderMixin { |
| + final HGraph graph = new HGraph(); |
| /** |
| * The current block to add instructions to. Might be null, if we are |
| @@ -931,6 +910,88 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| */ |
| bool isReachable = true; |
| + HBasicBlock get current => _current; |
| + void set current(c) { |
| + isReachable = c != null; |
| + _current = c; |
| + } |
| + |
| + HBasicBlock addNewBlock() { |
| + HBasicBlock block = graph.addNewBlock(); |
| + // If adding a new block during building of an expression, it is due to |
| + // conditional expressions or short-circuit logical operators. |
| + return block; |
| + } |
| + |
| + void open(HBasicBlock block) { |
| + block.open(); |
| + current = block; |
| + lastOpenedBlock = block; |
| + } |
| + |
| + HBasicBlock close(HControlFlow end) { |
| + HBasicBlock result = current; |
| + current.close(end); |
| + current = null; |
| + return result; |
| + } |
| + |
| + HBasicBlock closeAndGotoExit(HControlFlow end) { |
| + HBasicBlock result = current; |
| + current.close(end); |
| + current = null; |
| + result.addSuccessor(graph.exit); |
| + return result; |
| + } |
| + |
| + void goto(HBasicBlock from, HBasicBlock to) { |
| + from.close(new HGoto()); |
| + from.addSuccessor(to); |
| + } |
| + |
| + bool isAborted() { |
| + return _current == null; |
| + } |
| + |
| + /** |
| + * Creates a new block, transitions to it from any current block, and |
| + * opens the new block. |
| + */ |
| + HBasicBlock openNewBlock() { |
| + HBasicBlock newBlock = addNewBlock(); |
| + if (!isAborted()) goto(current, newBlock); |
| + open(newBlock); |
| + return newBlock; |
| + } |
| + |
| + void add(HInstruction instruction) { |
| + current.add(instruction); |
| + } |
| +} |
| + |
| +class SsaBuilder extends ResolvedVisitor with SsaGraphBuilderMixin { |
| + final SsaBuilderTask builder; |
| + final JavaScriptBackend backend; |
| + final CodegenWorkItem work; |
| + final ConstantSystem constantSystem; |
| + LocalsHandler localsHandler; |
| + HInstruction rethrowableException; |
| + Map<Element, HInstruction> parameters; |
| + final RuntimeTypes rti; |
| + HParameterValue lastAddedParameter; |
| + |
| + Map<TargetElement, JumpHandler> jumpTargets; |
| + |
| + /** |
| + * Variables stored in the current activation. These variables are |
| + * being updated in try/catch blocks, and should be |
| + * accessed indirectly through [HLocalGet] and [HLocalSet]. |
| + */ |
| + Map<Element, HLocalValue> activationVariables; |
| + |
| + // We build the Ssa graph by simulating a stack machine. |
| + List<HInstruction> stack; |
| + |
| /** |
| * True if we are visiting the expression of a throw expression. |
| */ |
| @@ -971,7 +1032,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| : this.builder = builder, |
| this.backend = builder.backend, |
| this.work = work, |
| - graph = new HGraph(), |
| stack = new List<HInstruction>(), |
| activationVariables = new Map<Element, HLocalValue>(), |
| jumpTargets = new Map<TargetElement, JumpHandler>(), |
| @@ -991,12 +1051,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| bool inTryStatement = false; |
| int loopNesting = 0; |
| - HBasicBlock get current => _current; |
| - void set current(c) { |
| - isReachable = c != null; |
| - _current = c; |
| - } |
| - |
| Constant getConstantForNode(Node node) { |
| ConstantHandler handler = compiler.constantHandler; |
| Constant constant = elements.getConstant(node); |
| @@ -1225,9 +1279,15 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| localsHandler, inTryStatement); |
| inTryStatement = false; |
| LocalsHandler newLocalsHandler = new LocalsHandler(this); |
| - newLocalsHandler.closureData = |
| - compiler.closureToClassMapper.computeClosureToClassMapping( |
| - function, function.parseNode(compiler), elements); |
| + if (function.hasIrNode(compiler)) { |
| + // TODO(lry): handle ir functions with nested closure definitions. |
|
ngeoffray
2013/11/20 14:55:27
Why can't you call computeClosureToClassMapping?
lukas
2013/11/20 15:13:26
It is an AST visitor, but we don't have a tree ava
|
| + newLocalsHandler.closureData = |
| + new ClosureClassMap(null, null, null, new ThisElement(function)); |
| + } else { |
| + newLocalsHandler.closureData = |
| + compiler.closureToClassMapper.computeClosureToClassMapping( |
| + function, function.parseNode(compiler), elements); |
| + } |
| int argumentIndex = 0; |
| if (isInstanceMember) { |
| newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, |
| @@ -1350,7 +1410,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| return true; |
| } |
| - bool heuristicSayGoodToGo(FunctionExpression functionExpression) { |
| + bool heuristicSayGoodToGo(bool canBeInlined(int maxNodes)) { |
| // Don't inline recursivly |
| if (inliningStack.any((entry) => entry.function == function)) { |
| return false; |
| @@ -1371,17 +1431,16 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
| InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
| } |
| - bool canBeInlined = InlineWeeder.canBeInlined( |
| - functionExpression, maxInliningNodes); |
| - if (canBeInlined) { |
| + bool canInline = canBeInlined(maxInliningNodes); |
| + if (canInline) { |
| backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); |
| } else { |
| backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
| } |
| - return canBeInlined; |
| + return canInline; |
| } |
| - void doInlining(FunctionExpression functionExpression) { |
| + void doInlining(void visitBody()) { |
| // Add an explicit null check on the receiver before doing the |
| // inlining. We use [element] to get the same name in the |
| // NoSuchMethodError message as if we had called it. |
| @@ -1407,7 +1466,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| if (element.isGenerativeConstructor()) { |
| buildFactory(element); |
| } else { |
| - functionExpression.body.accept(this); |
| + visitBody(); |
| } |
| removeInlinedInstantiation(instantiatedType); |
| }); |
| @@ -1415,11 +1474,21 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| } |
| if (meetsHardConstraints()) { |
| - FunctionExpression functionExpression = function.parseNode(compiler); |
| - |
| - if (heuristicSayGoodToGo(functionExpression)) { |
| - doInlining(functionExpression); |
| - return true; |
| + if (function.hasIrNode(compiler)) { |
| + IrFunction irFunction = function.irNode(compiler); |
| + bool canInline(int n) => IrInlineWeeder.canBeInlined(irFunction, n); |
| + if (heuristicSayGoodToGo(canInline)) { |
| + SsaFromIrInliner irInliner = new SsaFromIrInliner(this); |
| + doInlining(() => irInliner.visitAll(irFunction.statements)); |
| + return true; |
| + } |
| + } else { |
| + FunctionExpression functionNode = function.parseNode(compiler); |
| + bool canInline(int n) => InlineWeeder.canBeInlined(functionNode, n); |
| + if (heuristicSayGoodToGo(canInline)) { |
| + doInlining(() => functionNode.body.accept(this)); |
| + return true; |
| + } |
| } |
| } |
| @@ -2047,58 +2116,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| return graph; |
| } |
| - HBasicBlock addNewBlock() { |
| - HBasicBlock block = graph.addNewBlock(); |
| - // If adding a new block during building of an expression, it is due to |
| - // conditional expressions or short-circuit logical operators. |
| - return block; |
| - } |
| - |
| - void open(HBasicBlock block) { |
| - block.open(); |
| - current = block; |
| - lastOpenedBlock = block; |
| - } |
| - |
| - HBasicBlock close(HControlFlow end) { |
| - HBasicBlock result = current; |
| - current.close(end); |
| - current = null; |
| - return result; |
| - } |
| - |
| - HBasicBlock closeAndGotoExit(HControlFlow end) { |
| - HBasicBlock result = current; |
| - current.close(end); |
| - current = null; |
| - result.addSuccessor(graph.exit); |
| - return result; |
| - } |
| - |
| - void goto(HBasicBlock from, HBasicBlock to) { |
| - from.close(new HGoto()); |
| - from.addSuccessor(to); |
| - } |
| - |
| - bool isAborted() { |
| - return _current == null; |
| - } |
| - |
| - /** |
| - * Creates a new block, transitions to it from any current block, and |
| - * opens the new block. |
| - */ |
| - HBasicBlock openNewBlock() { |
| - HBasicBlock newBlock = addNewBlock(); |
| - if (!isAborted()) goto(current, newBlock); |
| - open(newBlock); |
| - return newBlock; |
| - } |
| - |
| - void add(HInstruction instruction) { |
| - current.add(instruction); |
| - } |
| - |
| void addWithPosition(HInstruction instruction, Node node) { |
| add(attachPosition(instruction, node)); |
| } |
| @@ -2155,7 +2172,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| } |
| Script script = element.getCompilationUnit().script; |
| SourceFile sourceFile = script.file; |
| - SourceFileLocation location = new SourceFileLocation(sourceFile, token); |
| + SourceFileLocation location = |
| + new TokenSourceFileLocation(sourceFile, token); |
| if (!location.isValid()) { |
| throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
| {'offset': token.charOffset, |