| 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 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 * | 1016 * |
| 1017 * Invariant: [functionElement] must be an implementation element. | 1017 * Invariant: [functionElement] must be an implementation element. |
| 1018 */ | 1018 */ |
| 1019 HGraph buildMethod(FunctionElement functionElement) { | 1019 HGraph buildMethod(FunctionElement functionElement) { |
| 1020 assert(invariant(functionElement, functionElement.isImplementation)); | 1020 assert(invariant(functionElement, functionElement.isImplementation)); |
| 1021 FunctionExpression function = functionElement.parseNode(compiler); | 1021 FunctionExpression function = functionElement.parseNode(compiler); |
| 1022 assert(function != null); | 1022 assert(function != null); |
| 1023 assert(!function.modifiers.isExternal()); | 1023 assert(!function.modifiers.isExternal()); |
| 1024 assert(elements[function] != null); | 1024 assert(elements[function] != null); |
| 1025 openFunction(functionElement, function); | 1025 openFunction(functionElement, function); |
| 1026 SourceString name = functionElement.name; |
| 1027 // If [functionElement] is operator== we explicitely add a null |
| 1028 // check at the beginning of the method. This is to avoid having |
| 1029 // call sites do the null check. |
| 1030 if (name == const SourceString('==')) { |
| 1031 handleIf( |
| 1032 function, |
| 1033 () { |
| 1034 HParameterValue parameter = parameters.values.first; |
| 1035 push(new HIdentity( |
| 1036 parameter, graph.addConstantNull(constantSystem))); |
| 1037 }, |
| 1038 () { |
| 1039 HReturn ret = new HReturn( |
| 1040 graph.addConstantBool(false, constantSystem)); |
| 1041 close(ret).addSuccessor(graph.exit); |
| 1042 }, |
| 1043 null); |
| 1044 } |
| 1026 function.body.accept(this); | 1045 function.body.accept(this); |
| 1027 return closeFunction(); | 1046 return closeFunction(); |
| 1028 } | 1047 } |
| 1029 | 1048 |
| 1030 HGraph buildLazyInitializer(VariableElement variable) { | 1049 HGraph buildLazyInitializer(VariableElement variable) { |
| 1031 SendSet node = variable.parseNode(compiler); | 1050 SendSet node = variable.parseNode(compiler); |
| 1032 openFunction(variable, node); | 1051 openFunction(variable, node); |
| 1033 Link<Node> link = node.arguments; | 1052 Link<Node> link = node.arguments; |
| 1034 assert(!link.isEmpty && link.tail.isEmpty); | 1053 assert(!link.isEmpty && link.tail.isEmpty); |
| 1035 visit(link.head); | 1054 visit(link.head); |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 | 1559 |
| 1541 // Fetch the original default value of [element]; | 1560 // Fetch the original default value of [element]; |
| 1542 Constant constant = compileVariable(element); | 1561 Constant constant = compileVariable(element); |
| 1543 HConstant defaultValue = constant == null | 1562 HConstant defaultValue = constant == null |
| 1544 ? graph.addConstantNull(constantSystem) | 1563 ? graph.addConstantNull(constantSystem) |
| 1545 : graph.addConstant(constant); | 1564 : graph.addConstant(constant); |
| 1546 | 1565 |
| 1547 // Emit the equality check with the sentinel. | 1566 // Emit the equality check with the sentinel. |
| 1548 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); | 1567 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); |
| 1549 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); | 1568 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); |
| 1550 HInstruction target = new HStatic(equalsHelper); | |
| 1551 add(target); | |
| 1552 HInstruction operand = parameters[element]; | 1569 HInstruction operand = parameters[element]; |
| 1553 check = new HIdentity(target, sentinel, operand); | 1570 check = new HIdentity(sentinel, operand); |
| 1554 add(check); | 1571 add(check); |
| 1555 | 1572 |
| 1556 // If the check succeeds, we must update the parameter with the | 1573 // If the check succeeds, we must update the parameter with the |
| 1557 // default value. | 1574 // default value. |
| 1558 handleIf(element.parseNode(compiler), | 1575 handleIf(element.parseNode(compiler), |
| 1559 () => stack.add(check), | 1576 () => stack.add(check), |
| 1560 () => localsHandler.updateLocal(element, defaultValue), | 1577 () => localsHandler.updateLocal(element, defaultValue), |
| 1561 null); | 1578 null); |
| 1562 | 1579 |
| 1563 // Create the instruction that parameter checks will use. | 1580 // Create the instruction that parameter checks will use. |
| (...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 selector = new Selector.binaryOperator(const SourceString('|')); | 2372 selector = new Selector.binaryOperator(const SourceString('|')); |
| 2356 break; | 2373 break; |
| 2357 case "&": | 2374 case "&": |
| 2358 case "&=": | 2375 case "&=": |
| 2359 selector = new Selector.binaryOperator(const SourceString('&')); | 2376 selector = new Selector.binaryOperator(const SourceString('&')); |
| 2360 break; | 2377 break; |
| 2361 case "^": | 2378 case "^": |
| 2362 case "^=": | 2379 case "^=": |
| 2363 selector = new Selector.binaryOperator(const SourceString('^')); | 2380 selector = new Selector.binaryOperator(const SourceString('^')); |
| 2364 break; | 2381 break; |
| 2382 case "==": |
| 2383 case "!=": |
| 2384 selector = new Selector.binaryOperator(const SourceString('==')); |
| 2385 break; |
| 2386 case "<": |
| 2387 selector = new Selector.binaryOperator(const SourceString('<')); |
| 2388 break; |
| 2389 case "<=": |
| 2390 selector = new Selector.binaryOperator(const SourceString('<=')); |
| 2391 break; |
| 2392 case ">": |
| 2393 selector = new Selector.binaryOperator(const SourceString('>')); |
| 2394 break; |
| 2395 case ">=": |
| 2396 selector = new Selector.binaryOperator(const SourceString('>=')); |
| 2397 break; |
| 2398 case "===": |
| 2399 pushWithPosition(new HIdentity(left, right), op); |
| 2400 return; |
| 2401 case "!==": |
| 2402 HIdentity eq = new HIdentity(left, right); |
| 2403 add(eq); |
| 2404 pushWithPosition(new HNot(eq), op); |
| 2405 return; |
| 2365 default: | 2406 default: |
| 2366 break; | 2407 break; |
| 2367 } | 2408 } |
| 2368 | 2409 |
| 2369 if (selector != null) { | 2410 if (selector != null) { |
| 2370 pushWithPosition( | 2411 pushWithPosition( |
| 2371 buildInvokeDynamic(send, selector, left, [right]), | 2412 buildInvokeDynamic(send, selector, left, [right]), |
| 2372 op); | 2413 op); |
| 2414 if (op.source.stringValue == '!=') { |
| 2415 HBoolify bl = new HBoolify(pop()); |
| 2416 add(bl); |
| 2417 pushWithPosition(new HNot(bl), op); |
| 2418 } |
| 2373 return; | 2419 return; |
| 2374 } | 2420 } |
| 2375 Element element = interceptors.getOperatorInterceptor(op); | 2421 Element element = interceptors.getOperatorInterceptor(op); |
| 2376 assert(element != null); | 2422 assert(element != null); |
| 2377 HInstruction target = new HStatic(element); | 2423 HInstruction target = new HStatic(element); |
| 2378 add(target); | 2424 add(target); |
| 2379 switch (op.source.stringValue) { | 2425 switch (op.source.stringValue) { |
| 2380 case "==": | |
| 2381 pushWithPosition(new HEquals(target, left, right), op); | |
| 2382 break; | |
| 2383 case "===": | |
| 2384 pushWithPosition(new HIdentity(target, left, right), op); | |
| 2385 break; | |
| 2386 case "!==": | |
| 2387 HIdentity eq = new HIdentity(target, left, right); | |
| 2388 add(eq); | |
| 2389 pushWithPosition(new HNot(eq), op); | |
| 2390 break; | |
| 2391 case "<": | |
| 2392 pushWithPosition(new HLess(target, left, right), op); | |
| 2393 break; | |
| 2394 case "<=": | |
| 2395 pushWithPosition(new HLessEqual(target, left, right), op); | |
| 2396 break; | |
| 2397 case ">": | |
| 2398 pushWithPosition(new HGreater(target, left, right), op); | |
| 2399 break; | |
| 2400 case ">=": | |
| 2401 pushWithPosition(new HGreaterEqual(target, left, right), op); | |
| 2402 break; | |
| 2403 case "!=": | |
| 2404 HEquals eq = new HEquals(target, left, right); | |
| 2405 add(eq); | |
| 2406 HBoolify bl = new HBoolify(eq); | |
| 2407 add(bl); | |
| 2408 pushWithPosition(new HNot(bl), op); | |
| 2409 break; | |
| 2410 default: compiler.unimplemented("SsaBuilder.visitBinary"); | 2426 default: compiler.unimplemented("SsaBuilder.visitBinary"); |
| 2411 } | 2427 } |
| 2412 } | 2428 } |
| 2413 | 2429 |
| 2414 HInstruction generateInstanceSendReceiver(Send send) { | 2430 HInstruction generateInstanceSendReceiver(Send send) { |
| 2415 assert(Elements.isInstanceSend(send, elements)); | 2431 assert(Elements.isInstanceSend(send, elements)); |
| 2416 if (send.receiver == null) { | 2432 if (send.receiver == null) { |
| 2417 return localsHandler.readThis(); | 2433 return localsHandler.readThis(); |
| 2418 } | 2434 } |
| 2419 visit(send.receiver); | 2435 visit(send.receiver); |
| (...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3472 // calling [addStaticSendArgumentsToList]. | 3488 // calling [addStaticSendArgumentsToList]. |
| 3473 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 3489 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 3474 element.implementation, | 3490 element.implementation, |
| 3475 inputs); | 3491 inputs); |
| 3476 if (!succeeded) { | 3492 if (!succeeded) { |
| 3477 generateWrongArgumentCountError(node, element, node.arguments); | 3493 generateWrongArgumentCountError(node, element, node.arguments); |
| 3478 return; | 3494 return; |
| 3479 } | 3495 } |
| 3480 | 3496 |
| 3481 if (isIdenticalFunction) { | 3497 if (isIdenticalFunction) { |
| 3482 pushWithPosition(new HIdentity(target, inputs[1], inputs[2]), node); | 3498 pushWithPosition(new HIdentity(inputs[1], inputs[2]), node); |
| 3483 return; | 3499 return; |
| 3484 } | 3500 } |
| 3485 | 3501 |
| 3486 HInvokeStatic instruction = new HInvokeStatic(inputs); | 3502 HInvokeStatic instruction = new HInvokeStatic(inputs); |
| 3487 // TODO(ngeoffray): Only do this if knowing the return type is | 3503 // TODO(ngeoffray): Only do this if knowing the return type is |
| 3488 // useful. | 3504 // useful. |
| 3489 HType returnType = | 3505 HType returnType = |
| 3490 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( | 3506 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( |
| 3491 work.element, element); | 3507 work.element, element); |
| 3492 if (returnType != null) instruction.guaranteedType = returnType; | 3508 if (returnType != null) instruction.guaranteedType = returnType; |
| (...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4449 // This must be the final case (otherwise "default" would be invalid), | 4465 // This must be the final case (otherwise "default" would be invalid), |
| 4450 // so we don't need to check for fallthrough. | 4466 // so we don't need to check for fallthrough. |
| 4451 return; | 4467 return; |
| 4452 } | 4468 } |
| 4453 | 4469 |
| 4454 // Recursively build the test conditions. Leaves the result on the | 4470 // Recursively build the test conditions. Leaves the result on the |
| 4455 // expression stack. | 4471 // expression stack. |
| 4456 void buildTests(Link<Node> remainingCases) { | 4472 void buildTests(Link<Node> remainingCases) { |
| 4457 // Build comparison for one case expression. | 4473 // Build comparison for one case expression. |
| 4458 void left() { | 4474 void left() { |
| 4459 Element equalsHelper = interceptors.getEqualsInterceptor(); | |
| 4460 HInstruction target = new HStatic(equalsHelper); | |
| 4461 add(target); | |
| 4462 CaseMatch match = remainingCases.head; | 4475 CaseMatch match = remainingCases.head; |
| 4463 // TODO(lrn): Move the constant resolution to the resolver, so | 4476 // TODO(lrn): Move the constant resolution to the resolver, so |
| 4464 // we can report an error before reaching the backend. | 4477 // we can report an error before reaching the backend. |
| 4465 Constant constant = | 4478 Constant constant = |
| 4466 compiler.constantHandler.tryCompileNodeWithDefinitions( | 4479 compiler.constantHandler.tryCompileNodeWithDefinitions( |
| 4467 match.expression, elements); | 4480 match.expression, elements); |
| 4468 if (constant != null) { | 4481 if (constant != null) { |
| 4469 stack.add(graph.addConstant(constant)); | 4482 stack.add(graph.addConstant(constant)); |
| 4470 } else { | 4483 } else { |
| 4471 visit(match.expression); | 4484 visit(match.expression); |
| 4472 } | 4485 } |
| 4473 push(new HEquals(target, pop(), expression)); | 4486 push(new HIdentity(pop(), expression)); |
| 4474 } | 4487 } |
| 4475 | 4488 |
| 4476 // If this is the last expression, just return it. | 4489 // If this is the last expression, just return it. |
| 4477 Link<Node> tail = skipLabels(remainingCases.tail); | 4490 Link<Node> tail = skipLabels(remainingCases.tail); |
| 4478 if (tail.isEmpty) { | 4491 if (tail.isEmpty) { |
| 4479 left(); | 4492 left(); |
| 4480 return; | 4493 return; |
| 4481 } | 4494 } |
| 4482 | 4495 |
| 4483 void right() { | 4496 void right() { |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5119 new HSubGraphBlockInformation(elseBranch.graph)); | 5132 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5120 | 5133 |
| 5121 HBasicBlock conditionStartBlock = conditionBranch.block; | 5134 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5122 conditionStartBlock.setBlockFlow(info, joinBlock); | 5135 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5123 SubGraph conditionGraph = conditionBranch.graph; | 5136 SubGraph conditionGraph = conditionBranch.graph; |
| 5124 HIf branch = conditionGraph.end.last; | 5137 HIf branch = conditionGraph.end.last; |
| 5125 assert(branch is HIf); | 5138 assert(branch is HIf); |
| 5126 branch.blockInformation = conditionStartBlock.blockFlow; | 5139 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5127 } | 5140 } |
| 5128 } | 5141 } |
| OLD | NEW |