| // Copyright (c) 2013, 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. |
| |
| part of ssa; |
| |
| /** |
| * This class implements an [IrNodesVisitor] that inlines a function represented |
| * as IR into an [SsaBuilder]. |
| */ |
| class SsaFromIrInliner |
| extends IrNodesVisitor with SsaGraphBuilderMixin<IrNode>, SsaFromIrMixin { |
| final SsaBuilder builder; |
| |
| SsaFromIrInliner(this.builder); |
| |
| Compiler get compiler => builder.compiler; |
| |
| JavaScriptBackend get backend => builder.backend; |
| |
| Element get sourceElement => builder.sourceElementStack.last; |
| |
| HGraph get graph => builder.graph; |
| |
| HBasicBlock get current => builder.current; |
| |
| void set current(HBasicBlock block) { |
| builder.current = block; |
| } |
| |
| HBasicBlock get lastOpenedBlock => builder.lastOpenedBlock; |
| |
| void set lastOpenedBlock(HBasicBlock block) { |
| builder.lastOpenedBlock = block; |
| } |
| |
| bool get isReachable => builder.isReachable; |
| |
| void set isReachable(bool value) { |
| builder.isReachable = value; |
| } |
| |
| bool get inThrowExpression => builder.inThrowExpression; |
| |
| int get loopNesting => builder.loopNesting; |
| |
| List<InliningState> get inliningStack => builder.inliningStack; |
| |
| List<Element> get sourceElementStack => builder.sourceElementStack; |
| |
| void setupInliningState(FunctionElement function, |
| List<HInstruction> compiledArguments) { |
| builder.setupInliningState(function, compiledArguments); |
| } |
| |
| void leaveInlinedMethod() { |
| builder.leaveInlinedMethod(); |
| } |
| |
| void doInline(Element element) { |
| builder.doInline(element); |
| } |
| |
| void emitReturn(HInstruction value, IrReturn node) { |
| builder.localsHandler.updateLocal(builder.returnElement, value); |
| } |
| } |
| |
| class IrInlineWeeder extends IrNodesVisitor { |
| static bool canBeInlined(IrFunction irFunction, |
| int maxInliningNodes, |
| bool useMaxInliningNodes) { |
| IrInlineWeeder weeder = |
| new IrInlineWeeder(maxInliningNodes, useMaxInliningNodes); |
| weeder.visitAll(irFunction.statements); |
| return !weeder.tooDifficult; |
| } |
| |
| final int maxInliningNodes; |
| final bool useMaxInliningNodes; |
| |
| IrInlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes); |
| |
| bool seenReturn = false; |
| bool tooDifficult = false; |
| int nodeCount = 0; |
| |
| bool registerNode() { |
| if (!useMaxInliningNodes) return true; |
| if (nodeCount++ > maxInliningNodes) { |
| tooDifficult = true; |
| return false; |
| } else { |
| return true; |
| } |
| } |
| |
| void visitIrNode(IrNode node) { |
| if (!registerNode()) return; |
| if (seenReturn) { |
| tooDifficult = true; |
| } |
| } |
| |
| void visitIrReturn(IrReturn node) { |
| visitIrNode(node); |
| seenReturn = true; |
| } |
| |
| void visitIrFunction(IrFunction node) { |
| tooDifficult = true; |
| } |
| } |