| 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 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 HGraph graph; | 805 HGraph graph; |
| 806 LocalsHandler localsHandler; | 806 LocalsHandler localsHandler; |
| 807 HInstruction rethrowableException; | 807 HInstruction rethrowableException; |
| 808 Map<Element, HParameterValue> parameters; | 808 Map<Element, HParameterValue> parameters; |
| 809 | 809 |
| 810 Map<TargetElement, JumpHandler> jumpTargets; | 810 Map<TargetElement, JumpHandler> jumpTargets; |
| 811 | 811 |
| 812 /** | 812 /** |
| 813 * Variables stored in the current activation. These variables are | 813 * Variables stored in the current activation. These variables are |
| 814 * being updated in try/catch blocks, and should be | 814 * being updated in try/catch blocks, and should be |
| 815 * accessed indirectly through HFieldGet and HFieldSet. | 815 * accessed indirectly through [HLocalGet] and [HLocalSet]. |
| 816 */ | 816 */ |
| 817 Map<Element, HLocalValue> activationVariables; | 817 Map<Element, HLocalValue> activationVariables; |
| 818 | 818 |
| 819 // We build the Ssa graph by simulating a stack machine. | 819 // We build the Ssa graph by simulating a stack machine. |
| 820 List<HInstruction> stack; | 820 List<HInstruction> stack; |
| 821 | 821 |
| 822 // The current block to add instructions to. Might be null, if we are | 822 // The current block to add instructions to. Might be null, if we are |
| 823 // visiting dead code. | 823 // visiting dead code. |
| 824 HBasicBlock current; | 824 HBasicBlock current; |
| 825 // The most recently opened block. Has the same value as [current] while | 825 // The most recently opened block. Has the same value as [current] while |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1219 // these selectors. Maybe the resolver can do more of the work | 1219 // these selectors. Maybe the resolver can do more of the work |
| 1220 // for us here? | 1220 // for us here? |
| 1221 LibraryElement library = body.getLibrary(); | 1221 LibraryElement library = body.getLibrary(); |
| 1222 Selector selector = new Selector.call(name, library, arity); | 1222 Selector selector = new Selector.call(name, library, arity); |
| 1223 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); | 1223 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); |
| 1224 } | 1224 } |
| 1225 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1225 close(new HReturn(newObject)).addSuccessor(graph.exit); |
| 1226 return closeFunction(); | 1226 return closeFunction(); |
| 1227 } | 1227 } |
| 1228 | 1228 |
| 1229 void addParameterCheckInstruction(Element element) { |
| 1230 // This is the code we emit for a parameter that is being checked |
| 1231 // on whether it was given at value at the call site: |
| 1232 // |
| 1233 // foo([a = 42) { |
| 1234 // if (?a) print('parameter passed $a'); |
| 1235 // } |
| 1236 // |
| 1237 // foo([a = 42]) { |
| 1238 // var t1 = a === sentinel; |
| 1239 // if (t1) a = 42; |
| 1240 // if (!t1) print('parameter passed ' + a); |
| 1241 // } |
| 1242 |
| 1243 // Fetch the original default value of [element]; |
| 1244 ConstantHandler handler = compiler.constantHandler; |
| 1245 Constant constant = handler.compileVariable(element); |
| 1246 HConstant defaultValue = constant == null |
| 1247 ? graph.addConstantNull() |
| 1248 : graph.addConstant(constant); |
| 1249 |
| 1250 // Emit the equality check with the sentinel. |
| 1251 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); |
| 1252 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); |
| 1253 HInstruction target = new HStatic(equalsHelper); |
| 1254 add(target); |
| 1255 HInstruction operand = parameters[element]; |
| 1256 HInstruction check = new HIdentity(target, sentinel, operand); |
| 1257 add(check); |
| 1258 |
| 1259 // If the check succeeds, we must update the parameter with the |
| 1260 // default value. |
| 1261 handleIf(element.parseNode(compiler), |
| 1262 () => stack.add(check), |
| 1263 () => localsHandler.updateLocal(element, defaultValue), |
| 1264 null); |
| 1265 |
| 1266 // Create the instruction that parameter checks will use. |
| 1267 check = new HNot(check); |
| 1268 add(check); |
| 1269 |
| 1270 ClosureClassMap closureData = localsHandler.closureData; |
| 1271 Element checkResultElement = closureData.parametersWithSentinel[element]; |
| 1272 localsHandler.updateLocal(checkResultElement, check); |
| 1273 } |
| 1274 |
| 1229 void openFunction(FunctionElement functionElement, | 1275 void openFunction(FunctionElement functionElement, |
| 1230 FunctionExpression node) { | 1276 FunctionExpression node) { |
| 1231 HBasicBlock block = graph.addNewBlock(); | 1277 HBasicBlock block = graph.addNewBlock(); |
| 1232 open(graph.entry); | 1278 open(graph.entry); |
| 1233 | 1279 |
| 1234 localsHandler.startFunction(functionElement, node); | 1280 localsHandler.startFunction(functionElement, node); |
| 1235 close(new HGoto()).addSuccessor(block); | 1281 close(new HGoto()).addSuccessor(block); |
| 1236 | 1282 |
| 1237 open(block); | 1283 open(block); |
| 1238 | 1284 |
| 1285 FunctionSignature params = functionElement.computeSignature(compiler); |
| 1286 params.forEachParameter((Element element) { |
| 1287 if (elements.isParameterChecked(element)) { |
| 1288 addParameterCheckInstruction(element); |
| 1289 } |
| 1290 }); |
| 1291 |
| 1239 // Put the type checks in the first successor of the entry, | 1292 // Put the type checks in the first successor of the entry, |
| 1240 // because that is where the type guards will also be inserted. | 1293 // because that is where the type guards will also be inserted. |
| 1241 // This way we ensure that a type guard will dominate the type | 1294 // This way we ensure that a type guard will dominate the type |
| 1242 // check. | 1295 // check. |
| 1243 FunctionSignature params = functionElement.computeSignature(compiler); | |
| 1244 params.forEachParameter((Element element) { | 1296 params.forEachParameter((Element element) { |
| 1245 HInstruction newParameter = potentiallyCheckType( | 1297 HInstruction newParameter = potentiallyCheckType( |
| 1246 localsHandler.directLocals[element], element); | 1298 localsHandler.directLocals[element], element); |
| 1247 localsHandler.directLocals[element] = newParameter; | 1299 localsHandler.directLocals[element] = newParameter; |
| 1248 }); | 1300 }); |
| 1249 | 1301 |
| 1250 // Add the type parameters of the class as parameters of this | 1302 // Add the type parameters of the class as parameters of this |
| 1251 // method. | 1303 // method. |
| 1252 if (functionElement.isFactoryConstructor() | 1304 if (functionElement.isFactoryConstructor() |
| 1253 || functionElement.isGenerativeConstructor()) { | 1305 || functionElement.isGenerativeConstructor()) { |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1771 | 1823 |
| 1772 | 1824 |
| 1773 void visitLogicalNot(Send node) { | 1825 void visitLogicalNot(Send node) { |
| 1774 assert(node.argumentsNode is Prefix); | 1826 assert(node.argumentsNode is Prefix); |
| 1775 visit(node.receiver); | 1827 visit(node.receiver); |
| 1776 HNot not = new HNot(popBoolified()); | 1828 HNot not = new HNot(popBoolified()); |
| 1777 pushWithPosition(not, node); | 1829 pushWithPosition(not, node); |
| 1778 } | 1830 } |
| 1779 | 1831 |
| 1780 void visitUnary(Send node, Operator op) { | 1832 void visitUnary(Send node, Operator op) { |
| 1781 String value = op.source.stringValue; | 1833 if (node.isParameterCheck) { |
| 1782 if (value === '?') { | 1834 Element element = elements[node.receiver]; |
| 1783 // TODO(ahe): Implement argument definition test. | 1835 Node function = element.enclosingElement.parseNode(compiler); |
| 1784 stack.add(graph.addConstantBool(true)); | 1836 ClosureClassMap parameterClosureData = |
| 1837 compiler.closureToClassMapper.getMappingForNestedFunction(function); |
| 1838 Element fieldCheck = |
| 1839 parameterClosureData.parametersWithSentinel[element]; |
| 1840 stack.add(localsHandler.readLocal(fieldCheck)); |
| 1785 return; | 1841 return; |
| 1786 } | 1842 } |
| 1787 assert(node.argumentsNode is Prefix); | 1843 assert(node.argumentsNode is Prefix); |
| 1788 visit(node.receiver); | 1844 visit(node.receiver); |
| 1789 assert(op.token.kind !== PLUS_TOKEN); | 1845 assert(op.token.kind !== PLUS_TOKEN); |
| 1790 HInstruction operand = pop(); | 1846 HInstruction operand = pop(); |
| 1791 | 1847 |
| 1792 HInstruction target = | 1848 HInstruction target = |
| 1793 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1849 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1794 add(target); | 1850 add(target); |
| 1795 HInvokeUnary result; | 1851 HInvokeUnary result; |
| 1852 String value = op.source.stringValue; |
| 1796 switch (value) { | 1853 switch (value) { |
| 1797 case "-": result = new HNegate(target, operand); break; | 1854 case "-": result = new HNegate(target, operand); break; |
| 1798 case "~": result = new HBitNot(target, operand); break; | 1855 case "~": result = new HBitNot(target, operand); break; |
| 1799 default: | 1856 default: |
| 1800 compiler.internalError('Unexpected unary operator: $value.', node: op); | 1857 compiler.internalError('Unexpected unary operator: $value.', node: op); |
| 1801 break; | 1858 break; |
| 1802 } | 1859 } |
| 1803 // See if we can constant-fold right away. This avoids rewrites later on. | 1860 // See if we can constant-fold right away. This avoids rewrites later on. |
| 1804 if (operand is HConstant) { | 1861 if (operand is HConstant) { |
| 1805 HConstant constant = operand; | 1862 HConstant constant = operand; |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2158 */ | 2215 */ |
| 2159 bool addStaticSendArgumentsToList(Selector selector, | 2216 bool addStaticSendArgumentsToList(Selector selector, |
| 2160 Link<Node> arguments, | 2217 Link<Node> arguments, |
| 2161 FunctionElement element, | 2218 FunctionElement element, |
| 2162 List<HInstruction> list) { | 2219 List<HInstruction> list) { |
| 2163 HInstruction compileArgument(Node argument) { | 2220 HInstruction compileArgument(Node argument) { |
| 2164 visit(argument); | 2221 visit(argument); |
| 2165 return pop(); | 2222 return pop(); |
| 2166 } | 2223 } |
| 2167 | 2224 |
| 2168 HInstruction compileConstant(Element constantElement) { | 2225 HInstruction compileConstant(Element parameter) { |
| 2169 Constant constant = compiler.compileVariable(constantElement); | 2226 Constant constant; |
| 2227 TreeElements calleeElements = |
| 2228 compiler.enqueuer.resolution.getCachedElements(element); |
| 2229 if (calleeElements.isParameterChecked(parameter)) { |
| 2230 constant = SentinelConstant.SENTINEL; |
| 2231 } else { |
| 2232 constant = compiler.compileVariable(parameter); |
| 2233 } |
| 2170 return graph.addConstant(constant); | 2234 return graph.addConstant(constant); |
| 2171 } | 2235 } |
| 2172 | 2236 |
| 2173 return selector.addArgumentsToList(arguments, | 2237 return selector.addArgumentsToList(arguments, |
| 2174 list, | 2238 list, |
| 2175 element, | 2239 element, |
| 2176 compileArgument, | 2240 compileArgument, |
| 2177 compileConstant, | 2241 compileConstant, |
| 2178 compiler); | 2242 compiler); |
| 2179 } | 2243 } |
| (...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3662 } | 3726 } |
| 3663 | 3727 |
| 3664 void visitFunctionExpression(Node node) { | 3728 void visitFunctionExpression(Node node) { |
| 3665 tooDifficult = true; | 3729 tooDifficult = true; |
| 3666 } | 3730 } |
| 3667 | 3731 |
| 3668 void visitFunctionDeclaration(Node node) { | 3732 void visitFunctionDeclaration(Node node) { |
| 3669 tooDifficult = true; | 3733 tooDifficult = true; |
| 3670 } | 3734 } |
| 3671 | 3735 |
| 3672 void visitSend(Node node) { | 3736 void visitSend(Send node) { |
| 3737 if (node.isParameterCheck) { |
| 3738 tooDifficult = true; |
| 3739 return; |
| 3740 } |
| 3673 node.visitChildren(this); | 3741 node.visitChildren(this); |
| 3674 } | 3742 } |
| 3675 | 3743 |
| 3676 visitLoop(Node node) { | 3744 visitLoop(Node node) { |
| 3677 node.visitChildren(this); | 3745 node.visitChildren(this); |
| 3678 if (seenReturn) tooDifficult = true; | 3746 if (seenReturn) tooDifficult = true; |
| 3679 } | 3747 } |
| 3680 | 3748 |
| 3681 void visitReturn(Node node) { | 3749 void visitReturn(Node node) { |
| 3682 if (seenReturn || node.getBeginToken().stringValue === 'native') { | 3750 if (seenReturn || node.getBeginToken().stringValue === 'native') { |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3933 new HSubGraphBlockInformation(elseBranch.graph)); | 4001 new HSubGraphBlockInformation(elseBranch.graph)); |
| 3934 | 4002 |
| 3935 HBasicBlock conditionStartBlock = conditionBranch.block; | 4003 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 3936 conditionStartBlock.setBlockFlow(info, joinBlock); | 4004 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 3937 SubGraph conditionGraph = conditionBranch.graph; | 4005 SubGraph conditionGraph = conditionBranch.graph; |
| 3938 HIf branch = conditionGraph.end.last; | 4006 HIf branch = conditionGraph.end.last; |
| 3939 assert(branch is HIf); | 4007 assert(branch is HIf); |
| 3940 branch.blockInformation = conditionStartBlock.blockFlow; | 4008 branch.blockInformation = conditionStartBlock.blockFlow; |
| 3941 } | 4009 } |
| 3942 } | 4010 } |
| OLD | NEW |