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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1394 constructor = constructor.targetConstructor; | 1394 constructor = constructor.targetConstructor; |
| 1395 } | 1395 } |
| 1396 elements = | 1396 elements = |
| 1397 compiler.enqueuer.resolution.getCachedElements(constructor); | 1397 compiler.enqueuer.resolution.getCachedElements(constructor); |
| 1398 ClosureClassMap oldClosureData = localsHandler.closureData; | 1398 ClosureClassMap oldClosureData = localsHandler.closureData; |
| 1399 Node node = constructor.parseNode(compiler); | 1399 Node node = constructor.parseNode(compiler); |
| 1400 ClosureClassMap newClosureData = | 1400 ClosureClassMap newClosureData = |
| 1401 compiler.closureToClassMapper.computeClosureToClassMapping( | 1401 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1402 constructor, node, elements); | 1402 constructor, node, elements); |
| 1403 localsHandler.closureData = newClosureData; | 1403 localsHandler.closureData = newClosureData; |
| 1404 | |
| 1405 params.orderedForEachParameter((Element parameterElement) { | |
| 1406 if (elements.isParameterChecked(parameterElement)) { | |
| 1407 addParameterCheckInstruction(parameterElement); | |
| 1408 } | |
| 1409 }); | |
| 1410 localsHandler.enterScope(node, constructor); | 1404 localsHandler.enterScope(node, constructor); |
| 1411 buildInitializers(constructor, constructors, fieldValues); | 1405 buildInitializers(constructor, constructors, fieldValues); |
| 1412 localsHandler.closureData = oldClosureData; | 1406 localsHandler.closureData = oldClosureData; |
| 1413 elements = oldElements; | 1407 elements = oldElements; |
| 1414 }); | 1408 }); |
| 1415 } | 1409 } |
| 1416 | 1410 |
| 1417 /** | 1411 /** |
| 1418 * Run through the initializers and inline all field initializers. Recursively | 1412 * Run through the initializers and inline all field initializers. Recursively |
| 1419 * inlines super initializers. | 1413 * inlines super initializers. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1616 FunctionSignature functionSignature = body.computeSignature(compiler); | 1610 FunctionSignature functionSignature = body.computeSignature(compiler); |
| 1617 // Provide the parameters to the generative constructor body. | 1611 // Provide the parameters to the generative constructor body. |
| 1618 functionSignature.orderedForEachParameter((parameter) { | 1612 functionSignature.orderedForEachParameter((parameter) { |
| 1619 // If [parameter] is boxed, it will be a field in the box passed as the | 1613 // If [parameter] is boxed, it will be a field in the box passed as the |
| 1620 // last parameter. So no need to directly pass it. | 1614 // last parameter. So no need to directly pass it. |
| 1621 if (!localsHandler.isBoxed(parameter)) { | 1615 if (!localsHandler.isBoxed(parameter)) { |
| 1622 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 1616 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 1623 } | 1617 } |
| 1624 }); | 1618 }); |
| 1625 | 1619 |
| 1626 // Provide the parameter checks to the generative constructor | |
| 1627 // body. | |
| 1628 functionSignature.orderedForEachParameter((parameter) { | |
| 1629 // If [parameter] is checked, we pass the already computed | |
| 1630 // boolean to the constructor body. | |
| 1631 if (elements.isParameterChecked(parameter)) { | |
| 1632 Element fieldCheck = | |
| 1633 parameterClosureData.parametersWithSentinel[parameter]; | |
| 1634 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); | |
| 1635 } | |
| 1636 }); | |
| 1637 | |
| 1638 ClassElement currentClass = constructor.getEnclosingClass(); | 1620 ClassElement currentClass = constructor.getEnclosingClass(); |
| 1639 if (backend.classNeedsRti(currentClass)) { | 1621 if (backend.classNeedsRti(currentClass)) { |
| 1640 // If [currentClass] needs RTI, we add the type variables as | 1622 // If [currentClass] needs RTI, we add the type variables as |
| 1641 // parameters of the generative constructor body. | 1623 // parameters of the generative constructor body. |
| 1642 currentClass.typeVariables.forEach((DartType argument) { | 1624 currentClass.typeVariables.forEach((DartType argument) { |
| 1643 bodyCallInputs.add(localsHandler.readLocal(argument.element)); | 1625 bodyCallInputs.add(localsHandler.readLocal(argument.element)); |
| 1644 }); | 1626 }); |
| 1645 } | 1627 } |
| 1646 | 1628 |
| 1647 // If there are locals that escape (ie mutated in closures), we | 1629 // If there are locals that escape (ie mutated in closures), we |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1663 } | 1645 } |
| 1664 if (inliningStack.isEmpty) { | 1646 if (inliningStack.isEmpty) { |
| 1665 closeAndGotoExit(new HReturn(newObject)); | 1647 closeAndGotoExit(new HReturn(newObject)); |
| 1666 return closeFunction(); | 1648 return closeFunction(); |
| 1667 } else { | 1649 } else { |
| 1668 localsHandler.updateLocal(returnElement, newObject); | 1650 localsHandler.updateLocal(returnElement, newObject); |
| 1669 return null; | 1651 return null; |
| 1670 } | 1652 } |
| 1671 } | 1653 } |
| 1672 | 1654 |
| 1673 void addParameterCheckInstruction(Element element) { | |
| 1674 HInstruction check; | |
| 1675 Element checkResultElement = | |
| 1676 localsHandler.closureData.parametersWithSentinel[element]; | |
| 1677 if (currentElement.isGenerativeConstructorBody()) { | |
| 1678 // A generative constructor body receives extra parameters that | |
| 1679 // indicate if a parameter was passed to the factory. | |
| 1680 check = addParameter(checkResultElement); | |
| 1681 } else { | |
| 1682 // This is the code we emit for a parameter that is being checked | |
| 1683 // on whether it was given at value at the call site: | |
| 1684 // | |
| 1685 // foo([a = 42]) { | |
| 1686 // if (?a) print('parameter passed $a'); | |
| 1687 // } | |
| 1688 // | |
| 1689 // foo([a = 42]) { | |
| 1690 // var t1 = identical(a, sentinel); | |
| 1691 // if (t1) a = 42; | |
| 1692 // if (!t1) print('parameter passed ' + a); | |
| 1693 // } | |
| 1694 | |
| 1695 // Fetch the original default value of [element]; | |
| 1696 Constant constant = compileVariable(element); | |
| 1697 HConstant defaultValue = constant == null | |
| 1698 ? graph.addConstantNull(compiler) | |
| 1699 : graph.addConstant(constant, compiler); | |
| 1700 | |
| 1701 // Emit the equality check with the sentinel. | |
| 1702 HConstant sentinel = | |
| 1703 graph.addConstant(SentinelConstant.SENTINEL, compiler); | |
| 1704 HInstruction operand = parameters[element]; | |
| 1705 check = new HIdentity(sentinel, operand); | |
| 1706 add(check); | |
| 1707 | |
| 1708 // If the check succeeds, we must update the parameter with the | |
| 1709 // default value. | |
| 1710 handleIf(element.parseNode(compiler), | |
| 1711 () => stack.add(check), | |
| 1712 () => localsHandler.updateLocal(element, defaultValue), | |
| 1713 null); | |
| 1714 | |
| 1715 // Create the instruction that parameter checks will use. | |
| 1716 check = new HNot(check); | |
| 1717 add(check); | |
| 1718 } | |
| 1719 | |
| 1720 localsHandler.updateLocal(checkResultElement, check); | |
| 1721 } | |
| 1722 | |
| 1723 /** | 1655 /** |
| 1724 * Documentation wanted -- johnniwinther | 1656 * Documentation wanted -- johnniwinther |
| 1725 * | 1657 * |
| 1726 * Invariant: [functionElement] must be the implementation element. | 1658 * Invariant: [functionElement] must be the implementation element. |
| 1727 */ | 1659 */ |
| 1728 void openFunction(Element element, Expression node) { | 1660 void openFunction(Element element, Expression node) { |
| 1729 assert(invariant(element, element.isImplementation)); | 1661 assert(invariant(element, element.isImplementation)); |
| 1730 HBasicBlock block = graph.addNewBlock(); | 1662 HBasicBlock block = graph.addNewBlock(); |
| 1731 open(graph.entry); | 1663 open(graph.entry); |
| 1732 | 1664 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1743 && backend.classNeedsRti(enclosing)) { | 1675 && backend.classNeedsRti(enclosing)) { |
| 1744 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1676 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1745 HParameterValue param = addParameter(typeVariable.element); | 1677 HParameterValue param = addParameter(typeVariable.element); |
| 1746 localsHandler.directLocals[typeVariable.element] = param; | 1678 localsHandler.directLocals[typeVariable.element] = param; |
| 1747 }); | 1679 }); |
| 1748 } | 1680 } |
| 1749 | 1681 |
| 1750 if (element is FunctionElement) { | 1682 if (element is FunctionElement) { |
| 1751 FunctionElement functionElement = element; | 1683 FunctionElement functionElement = element; |
| 1752 FunctionSignature signature = functionElement.computeSignature(compiler); | 1684 FunctionSignature signature = functionElement.computeSignature(compiler); |
| 1753 signature.orderedForEachParameter((Element parameterElement) { | |
| 1754 if (elements.isParameterChecked(parameterElement)) { | |
| 1755 addParameterCheckInstruction(parameterElement); | |
| 1756 } | |
| 1757 }); | |
| 1758 | 1685 |
| 1759 // Put the type checks in the first successor of the entry, | 1686 // Put the type checks in the first successor of the entry, |
| 1760 // because that is where the type guards will also be inserted. | 1687 // because that is where the type guards will also be inserted. |
| 1761 // This way we ensure that a type guard will dominate the type | 1688 // This way we ensure that a type guard will dominate the type |
| 1762 // check. | 1689 // check. |
| 1763 signature.orderedForEachParameter((Element parameterElement) { | 1690 signature.orderedForEachParameter((Element parameterElement) { |
| 1764 if (element.isGenerativeConstructorBody()) { | 1691 if (element.isGenerativeConstructorBody()) { |
| 1765 ClosureScope scopeData = | 1692 ClosureScope scopeData = |
| 1766 localsHandler.closureData.capturingScopes[node]; | 1693 localsHandler.closureData.capturingScopes[node]; |
| 1767 if (scopeData != null | 1694 if (scopeData != null |
| (...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2525 } | 2452 } |
| 2526 | 2453 |
| 2527 void visitLogicalNot(Send node) { | 2454 void visitLogicalNot(Send node) { |
| 2528 assert(node.argumentsNode is Prefix); | 2455 assert(node.argumentsNode is Prefix); |
| 2529 visit(node.receiver); | 2456 visit(node.receiver); |
| 2530 HNot not = new HNot(popBoolified()); | 2457 HNot not = new HNot(popBoolified()); |
| 2531 pushWithPosition(not, node); | 2458 pushWithPosition(not, node); |
| 2532 } | 2459 } |
| 2533 | 2460 |
| 2534 void visitUnary(Send node, Operator op) { | 2461 void visitUnary(Send node, Operator op) { |
| 2535 if (node.isParameterCheck) { | |
| 2536 Element element = elements[node.receiver]; | |
| 2537 Node function = element.enclosingElement.parseNode(compiler); | |
| 2538 ClosureClassMap parameterClosureData = | |
| 2539 compiler.closureToClassMapper.getMappingForNestedFunction(function); | |
| 2540 Element fieldCheck = | |
| 2541 parameterClosureData.parametersWithSentinel[element]; | |
| 2542 stack.add(localsHandler.readLocal(fieldCheck)); | |
| 2543 return; | |
| 2544 } | |
| 2545 assert(node.argumentsNode is Prefix); | 2462 assert(node.argumentsNode is Prefix); |
| 2546 visit(node.receiver); | 2463 visit(node.receiver); |
| 2547 assert(!identical(op.token.kind, PLUS_TOKEN)); | 2464 assert(!identical(op.token.kind, PLUS_TOKEN)); |
| 2548 HInstruction operand = pop(); | 2465 HInstruction operand = pop(); |
| 2549 | 2466 |
| 2550 // See if we can constant-fold right away. This avoids rewrites later on. | 2467 // See if we can constant-fold right away. This avoids rewrites later on. |
| 2551 if (operand is HConstant) { | 2468 if (operand is HConstant) { |
| 2552 UnaryOperation operation = constantSystem.lookupUnary(op.source); | 2469 UnaryOperation operation = constantSystem.lookupUnary(op.source); |
| 2553 HConstant constant = operand; | 2470 HConstant constant = operand; |
| 2554 Constant folded = operation.fold(constant.constant); | 2471 Constant folded = operation.fold(constant.constant); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2935 // of instructions, in an order that can be shared with | 2852 // of instructions, in an order that can be shared with |
| 2936 // selectors with the same named arguments. | 2853 // selectors with the same named arguments. |
| 2937 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); | 2854 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); |
| 2938 for (SourceString name in orderedNames) { | 2855 for (SourceString name in orderedNames) { |
| 2939 list.add(instructions[name]); | 2856 list.add(instructions[name]); |
| 2940 } | 2857 } |
| 2941 } | 2858 } |
| 2942 } | 2859 } |
| 2943 | 2860 |
| 2944 HInstruction handleConstantForOptionalParameter(Element parameter) { | 2861 HInstruction handleConstantForOptionalParameter(Element parameter) { |
| 2945 Constant constant; | |
| 2946 Element element = parameter.enclosingElement; | 2862 Element element = parameter.enclosingElement; |
| 2947 TreeElements calleeElements = | 2863 TreeElements calleeElements = |
| 2948 compiler.enqueuer.resolution.getCachedElements(element); | 2864 compiler.enqueuer.resolution.getCachedElements(element); |
|
ngeoffray
2013/06/26 07:54:55
Remove calleeElements.
kasperl
2013/06/26 07:57:26
Done. Also got rid of the 'element' local variable
| |
| 2949 if (calleeElements.isParameterChecked(parameter)) { | 2865 Constant constant = compileConstant(parameter); |
| 2950 constant = SentinelConstant.SENTINEL; | |
| 2951 } else { | |
| 2952 constant = compileConstant(parameter); | |
| 2953 } | |
| 2954 return graph.addConstant(constant, compiler); | 2866 return graph.addConstant(constant, compiler); |
| 2955 } | 2867 } |
| 2956 | 2868 |
| 2957 /** | 2869 /** |
| 2958 * Returns true if the arguments were compatible with the function signature. | 2870 * Returns true if the arguments were compatible with the function signature. |
| 2959 * | 2871 * |
| 2960 * Invariant: [element] must be an implementation element. | 2872 * Invariant: [element] must be an implementation element. |
| 2961 */ | 2873 */ |
| 2962 bool addStaticSendArgumentsToList(Selector selector, | 2874 bool addStaticSendArgumentsToList(Selector selector, |
| 2963 Link<Node> arguments, | 2875 Link<Node> arguments, |
| (...skipping 2260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5224 tooDifficult = true; | 5136 tooDifficult = true; |
| 5225 } | 5137 } |
| 5226 | 5138 |
| 5227 void visitFunctionDeclaration(Node node) { | 5139 void visitFunctionDeclaration(Node node) { |
| 5228 if (!registerNode()) return; | 5140 if (!registerNode()) return; |
| 5229 tooDifficult = true; | 5141 tooDifficult = true; |
| 5230 } | 5142 } |
| 5231 | 5143 |
| 5232 void visitSend(Send node) { | 5144 void visitSend(Send node) { |
| 5233 if (!registerNode()) return; | 5145 if (!registerNode()) return; |
| 5234 if (node.isParameterCheck) { | |
| 5235 tooDifficult = true; | |
| 5236 return; | |
| 5237 } | |
| 5238 node.visitChildren(this); | 5146 node.visitChildren(this); |
| 5239 } | 5147 } |
| 5240 | 5148 |
| 5241 visitLoop(Node node) { | 5149 visitLoop(Node node) { |
| 5242 // It's actually not difficult to inline a method with a loop, but | 5150 // It's actually not difficult to inline a method with a loop, but |
| 5243 // our measurements show that it's currently better to not inline a | 5151 // our measurements show that it's currently better to not inline a |
| 5244 // method that contains a loop. | 5152 // method that contains a loop. |
| 5245 tooDifficult = true; | 5153 tooDifficult = true; |
| 5246 } | 5154 } |
| 5247 | 5155 |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5526 new HSubGraphBlockInformation(elseBranch.graph)); | 5434 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5527 | 5435 |
| 5528 HBasicBlock conditionStartBlock = conditionBranch.block; | 5436 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5529 conditionStartBlock.setBlockFlow(info, joinBlock); | 5437 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5530 SubGraph conditionGraph = conditionBranch.graph; | 5438 SubGraph conditionGraph = conditionBranch.graph; |
| 5531 HIf branch = conditionGraph.end.last; | 5439 HIf branch = conditionGraph.end.last; |
| 5532 assert(branch is HIf); | 5440 assert(branch is HIf); |
| 5533 branch.blockInformation = conditionStartBlock.blockFlow; | 5441 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5534 } | 5442 } |
| 5535 } | 5443 } |
| OLD | NEW |