Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10873025: Inlining of static functions: applying Florian's CL. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698