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 class Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 830 SsaBuilder(SsaBuilderTask builder, WorkItem work) | 830 SsaBuilder(SsaBuilderTask builder, WorkItem work) |
| 831 : this.builder = builder, | 831 : this.builder = builder, |
| 832 this.work = work, | 832 this.work = work, |
| 833 interceptors = builder.interceptors, | 833 interceptors = builder.interceptors, |
| 834 methodInterceptionEnabled = true, | 834 methodInterceptionEnabled = true, |
| 835 graph = new HGraph(), | 835 graph = new HGraph(), |
| 836 stack = new List<HInstruction>(), | 836 stack = new List<HInstruction>(), |
| 837 activationVariables = new Map<Element, HLocalValue>(), | 837 activationVariables = new Map<Element, HLocalValue>(), |
| 838 jumpTargets = new Map<TargetElement, JumpHandler>(), | 838 jumpTargets = new Map<TargetElement, JumpHandler>(), |
| 839 parameters = new Map<Element, HParameterValue>(), | 839 parameters = new Map<Element, HParameterValue>(), |
| 840 inliningStack = <InliningState>[], | |
| 840 super(work.resolutionTree) { | 841 super(work.resolutionTree) { |
| 841 localsHandler = new LocalsHandler(this); | 842 localsHandler = new LocalsHandler(this); |
| 842 } | 843 } |
| 843 | 844 |
| 845 static final MAX_INLINING_DEPTH = 3; | |
| 846 static final MAX_INLINING_SOURCE_SIZE = 100; | |
| 847 List<InliningState> inliningStack; | |
| 848 Element returnElement = null; | |
| 849 | |
| 844 void disableMethodInterception() { | 850 void disableMethodInterception() { |
| 845 assert(methodInterceptionEnabled); | 851 assert(methodInterceptionEnabled); |
| 846 methodInterceptionEnabled = false; | 852 methodInterceptionEnabled = false; |
| 847 } | 853 } |
| 848 | 854 |
| 849 void enableMethodInterception() { | 855 void enableMethodInterception() { |
| 850 assert(!methodInterceptionEnabled); | 856 assert(!methodInterceptionEnabled); |
| 851 methodInterceptionEnabled = true; | 857 methodInterceptionEnabled = true; |
| 852 } | 858 } |
| 853 | 859 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 TreeElements treeElements = | 899 TreeElements treeElements = |
| 894 compiler.resolver.resolveMethodElement(constructor); | 900 compiler.resolver.resolveMethodElement(constructor); |
| 895 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); | 901 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); |
| 896 classElement.backendMembers = | 902 classElement.backendMembers = |
| 897 classElement.backendMembers.prepend(bodyElement); | 903 classElement.backendMembers.prepend(bodyElement); |
| 898 } | 904 } |
| 899 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); | 905 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); |
| 900 return bodyElement; | 906 return bodyElement; |
| 901 } | 907 } |
| 902 | 908 |
| 909 InliningState enterInlinedMethod(PartialFunctionElement function, | |
| 910 Selector selector, | |
| 911 Link<Node> arguments) { | |
| 912 // Once we start to compile the arguments we must be sure that we don't | |
| 913 // abort. | |
| 914 List<HInstruction> compiledArguments = new List<HInstruction>(); | |
| 915 bool succeeded = addStaticSendArgumentsToList(selector, | |
| 916 arguments, | |
| 917 function, | |
| 918 compiledArguments); | |
| 919 assert(succeeded); | |
| 920 | |
| 921 InliningState state = | |
| 922 new InliningState(function, returnElement, elements, stack); | |
| 923 inliningStack.add(state); | |
| 924 stack = <HInstruction>[]; | |
| 925 returnElement = new Element(const SourceString("result"), | |
| 926 ElementKind.VARIABLE, | |
| 927 function); | |
| 928 localsHandler.updateLocal(returnElement, graph.addConstantNull()); | |
| 929 elements = compiler.enqueuer.resolution.getCachedElements(function); | |
| 930 FunctionSignature signature = function.computeSignature(compiler); | |
| 931 int index = 0; | |
| 932 signature.forEachParameter((Element parameter) { | |
| 933 HInstruction argument = compiledArguments[index++]; | |
| 934 localsHandler.updateLocal(parameter, argument); | |
| 935 potentiallyCheckType(argument, parameter); | |
| 936 }); | |
| 937 return state; | |
| 938 } | |
| 939 | |
| 940 void leaveInlinedMethod(InliningState state) { | |
| 941 InliningState poppedState = inliningStack.removeLast(); | |
| 942 assert(state == poppedState); | |
| 943 elements = state.oldElements; | |
| 944 stack.add(localsHandler.readLocal(returnElement)); | |
| 945 returnElement = state.oldReturnElement; | |
| 946 assert(stack.length == 1); | |
| 947 state.oldStack.add(stack[0]); | |
| 948 stack = state.oldStack; | |
| 949 } | |
| 950 | |
| 951 bool tryInlineMethod(Element element, | |
| 952 Selector selector, | |
| 953 Link<Node> arguments) { | |
| 954 if (element.kind != ElementKind.FUNCTION) return false; | |
| 955 if (element is !PartialFunctionElement) return false; | |
| 956 if (inliningStack.length > MAX_INLINING_DEPTH) return false; | |
| 957 // Don't inline recursive calls. We use the same elements for the inlined | |
| 958 // functions and would thus clobber our local variables. | |
| 959 if (work.element == element) return false; | |
| 960 for (int i = 0; i < inliningStack.length; i++) { | |
| 961 if (inliningStack[i].function == element) return false; | |
| 962 } | |
| 963 // TODO(ngeoffray): Inlining currently does not work in the presence of | |
|
kasperl
2012/08/23 09:18:51
I wonder if this restriction could be lifted. Mayb
| |
| 964 // private calls. | |
| 965 if (currentLibrary != element.getLibrary()) return false; | |
| 966 PartialFunctionElement function = element; | |
| 967 int sourceSize = | |
| 968 function.endToken.charOffset - function.beginToken.charOffset; | |
| 969 if (sourceSize > MAX_INLINING_SOURCE_SIZE) return false; | |
| 970 if (!selector.applies(function, compiler)) return false; | |
| 971 FunctionExpression functionExpression = function.parseNode(compiler); | |
| 972 TreeElements newElements = | |
| 973 compiler.enqueuer.resolution.getCachedElements(function); | |
| 974 if (newElements === null) { | |
| 975 compiler.internalError("Element not resolved: $function"); | |
| 976 } | |
| 977 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { | |
| 978 return false; | |
| 979 } | |
| 980 | |
| 981 InliningState state = enterInlinedMethod(function, selector, arguments); | |
| 982 functionExpression.body.accept(this); | |
| 983 leaveInlinedMethod(state); | |
| 984 return true; | |
| 985 } | |
| 986 | |
| 903 void inlineSuperOrRedirect(FunctionElement constructor, | 987 void inlineSuperOrRedirect(FunctionElement constructor, |
| 904 Selector selector, | 988 Selector selector, |
| 905 Link<Node> arguments, | 989 Link<Node> arguments, |
| 906 List<FunctionElement> constructors, | 990 List<FunctionElement> constructors, |
| 907 Map<Element, HInstruction> fieldValues) { | 991 Map<Element, HInstruction> fieldValues) { |
| 908 constructors.addLast(constructor); | 992 constructors.addLast(constructor); |
| 909 | 993 |
| 910 List<HInstruction> compiledArguments = new List<HInstruction>(); | 994 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 911 bool succeeded = addStaticSendArgumentsToList(selector, | 995 bool succeeded = addStaticSendArgumentsToList(selector, |
| 912 arguments, | 996 arguments, |
| (...skipping 1443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2356 } | 2440 } |
| 2357 | 2441 |
| 2358 visitStaticSend(Send node) { | 2442 visitStaticSend(Send node) { |
| 2359 Selector selector = elements.getSelector(node); | 2443 Selector selector = elements.getSelector(node); |
| 2360 Element element = elements[node]; | 2444 Element element = elements[node]; |
| 2361 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { | 2445 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { |
| 2362 stack.add(graph.addConstantNull()); | 2446 stack.add(graph.addConstantNull()); |
| 2363 return; | 2447 return; |
| 2364 } | 2448 } |
| 2365 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); | 2449 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); |
| 2450 | |
| 2451 if (tryInlineMethod(element, selector, node.arguments)) return; | |
| 2452 | |
| 2366 HInstruction target = new HStatic(element); | 2453 HInstruction target = new HStatic(element); |
| 2367 add(target); | 2454 add(target); |
| 2368 var inputs = <HInstruction>[]; | 2455 var inputs = <HInstruction>[]; |
| 2369 inputs.add(target); | 2456 inputs.add(target); |
| 2370 if (element.kind == ElementKind.FUNCTION) { | 2457 if (element.kind == ElementKind.FUNCTION) { |
| 2371 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2458 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2372 element, inputs); | 2459 element, inputs); |
| 2373 if (!succeeded) { | 2460 if (!succeeded) { |
| 2374 // TODO(ngeoffray): Match the VM behavior and throw an | 2461 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2375 // exception at runtime. | 2462 // exception at runtime. |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2610 native.handleSsaNative(this, node.expression); | 2697 native.handleSsaNative(this, node.expression); |
| 2611 return; | 2698 return; |
| 2612 } | 2699 } |
| 2613 HInstruction value; | 2700 HInstruction value; |
| 2614 if (node.expression === null) { | 2701 if (node.expression === null) { |
| 2615 value = graph.addConstantNull(); | 2702 value = graph.addConstantNull(); |
| 2616 } else { | 2703 } else { |
| 2617 visit(node.expression); | 2704 visit(node.expression); |
| 2618 value = pop(); | 2705 value = pop(); |
| 2619 } | 2706 } |
| 2620 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); | 2707 if (!inliningStack.isEmpty()) { |
| 2708 localsHandler.updateLocal(returnElement, value); | |
| 2709 } else { | |
| 2710 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); | |
| 2711 } | |
| 2621 } | 2712 } |
| 2622 | 2713 |
| 2623 visitThrow(Throw node) { | 2714 visitThrow(Throw node) { |
| 2624 if (node.expression === null) { | 2715 if (node.expression === null) { |
| 2625 HInstruction exception = rethrowableException; | 2716 HInstruction exception = rethrowableException; |
| 2626 if (exception === null) { | 2717 if (exception === null) { |
| 2627 exception = graph.addConstantNull(); | 2718 exception = graph.addConstantNull(); |
| 2628 compiler.reportError(node, | 2719 compiler.reportError(node, |
| 2629 'throw without expression outside catch block'); | 2720 'throw without expression outside catch block'); |
| 2630 } | 2721 } |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3414 node.visitChildren(this); | 3505 node.visitChildren(this); |
| 3415 } | 3506 } |
| 3416 | 3507 |
| 3417 HInstruction concat(HInstruction left, HInstruction right) { | 3508 HInstruction concat(HInstruction left, HInstruction right) { |
| 3418 HInstruction instruction = new HStringConcat(left, right, diagnosticNode); | 3509 HInstruction instruction = new HStringConcat(left, right, diagnosticNode); |
| 3419 builder.add(instruction); | 3510 builder.add(instruction); |
| 3420 return instruction; | 3511 return instruction; |
| 3421 } | 3512 } |
| 3422 } | 3513 } |
| 3423 | 3514 |
| 3515 /** | |
| 3516 * This class visits the method that is a candidate for inlining and | |
| 3517 * finds whether it is too difficult to inline. | |
| 3518 */ | |
| 3519 class InlineWeeder extends AbstractVisitor { | |
| 3520 final TreeElements elements; | |
| 3521 bool seenReturn = false; | |
| 3522 bool tooDifficult = false; | |
| 3523 | |
| 3524 InlineWeeder(this.elements); | |
| 3525 | |
| 3526 static bool canBeInlined(FunctionExpression functionExpression, | |
| 3527 TreeElements elements) { | |
| 3528 InlineWeeder weeder = new InlineWeeder(elements); | |
| 3529 weeder.visit(functionExpression.body); | |
| 3530 if (weeder.tooDifficult) return false; | |
| 3531 return true; | |
| 3532 } | |
| 3533 | |
| 3534 void visit(Node node) { | |
| 3535 node.accept(this); | |
| 3536 } | |
| 3537 | |
| 3538 void visitNode(Node node) { | |
| 3539 if (seenReturn) { | |
| 3540 tooDifficult = true; | |
| 3541 } else { | |
| 3542 node.visitChildren(this); | |
| 3543 } | |
| 3544 } | |
| 3545 | |
| 3546 void visitFunctionExpression(Node node) { | |
| 3547 tooDifficult = true; | |
| 3548 } | |
| 3549 | |
| 3550 void visitFunctionDeclaration(Node node) { | |
| 3551 tooDifficult = true; | |
| 3552 } | |
| 3553 | |
| 3554 void visitSend(Node node) { | |
| 3555 Element element = elements[node]; | |
| 3556 // Native methods rely on the names of the arguments. If we inline they | |
| 3557 // could change. | |
| 3558 if (!Element.isInvalid(element) && element.kind == ElementKind.FOREIGN) { | |
| 3559 tooDifficult = true; | |
| 3560 } else { | |
| 3561 node.visitChildren(this); | |
| 3562 } | |
| 3563 } | |
| 3564 | |
| 3565 visitLoop(Node node) { | |
| 3566 node.visitChildren(this); | |
| 3567 if (seenReturn) tooDifficult = true; | |
| 3568 } | |
| 3569 | |
| 3570 void visitReturn(Node node) { | |
| 3571 if (seenReturn || node.getBeginToken().stringValue === 'native') { | |
| 3572 tooDifficult = true; | |
| 3573 return; | |
| 3574 } | |
| 3575 node.visitChildren(this); | |
| 3576 seenReturn = true; | |
| 3577 } | |
| 3578 | |
| 3579 void visitTryStatement(Node node) { | |
| 3580 tooDifficult = true; | |
| 3581 } | |
| 3582 } | |
| 3583 | |
| 3584 class InliningState { | |
| 3585 final PartialFunctionElement function; | |
| 3586 final Element oldReturnElement; | |
| 3587 final TreeElements oldElements; | |
| 3588 final List<HInstruction> oldStack; | |
| 3589 | |
| 3590 InliningState(this.function, | |
| 3591 this.oldReturnElement, | |
| 3592 this.oldElements, | |
| 3593 this.oldStack); | |
| 3594 } | |
| 3595 | |
| 3424 class SsaBranch { | 3596 class SsaBranch { |
| 3425 final SsaBranchBuilder branchBuilder; | 3597 final SsaBranchBuilder branchBuilder; |
| 3426 final HBasicBlock block; | 3598 final HBasicBlock block; |
| 3427 LocalsHandler startLocals; | 3599 LocalsHandler startLocals; |
| 3428 LocalsHandler exitLocals; | 3600 LocalsHandler exitLocals; |
| 3429 SubGraph graph; | 3601 SubGraph graph; |
| 3430 | 3602 |
| 3431 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); | 3603 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); |
| 3432 } | 3604 } |
| 3433 | 3605 |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3646 new HSubGraphBlockInformation(elseBranch.graph)); | 3818 new HSubGraphBlockInformation(elseBranch.graph)); |
| 3647 | 3819 |
| 3648 HBasicBlock conditionStartBlock = conditionBranch.block; | 3820 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 3649 conditionStartBlock.setBlockFlow(info, joinBlock); | 3821 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 3650 SubGraph conditionGraph = conditionBranch.graph; | 3822 SubGraph conditionGraph = conditionBranch.graph; |
| 3651 HIf branch = conditionGraph.end.last; | 3823 HIf branch = conditionGraph.end.last; |
| 3652 assert(branch is HIf); | 3824 assert(branch is HIf); |
| 3653 branch.blockInformation = conditionStartBlock.blockFlow; | 3825 branch.blockInformation = conditionStartBlock.blockFlow; |
| 3654 } | 3826 } |
| 3655 } | 3827 } |
| OLD | NEW |