| 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 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 if (isAccessedDirectly(local)) { | 485 if (isAccessedDirectly(local)) { |
| 486 if (directLocals[local] == null) { | 486 if (directLocals[local] == null) { |
| 487 if (local is TypeVariableElement) { | 487 if (local is TypeVariableElement) { |
| 488 builder.compiler.internalError(builder.compiler.currentElement, | 488 builder.compiler.internalError(builder.compiler.currentElement, |
| 489 "Runtime type information not available for $local."); | 489 "Runtime type information not available for $local."); |
| 490 } else { | 490 } else { |
| 491 builder.compiler.internalError(local, | 491 builder.compiler.internalError(local, |
| 492 "Cannot find value $local."); | 492 "Cannot find value $local."); |
| 493 } | 493 } |
| 494 } | 494 } |
| 495 return directLocals[local]; | 495 HInstruction value = directLocals[local]; |
| 496 if (sourceInformation != null) { |
| 497 value = new HRef(value, sourceInformation); |
| 498 builder.add(value); |
| 499 } |
| 500 return value; |
| 496 } else if (isStoredInClosureField(local)) { | 501 } else if (isStoredInClosureField(local)) { |
| 497 ClosureFieldElement redirect = redirectionMapping[local]; | 502 ClosureFieldElement redirect = redirectionMapping[local]; |
| 498 HInstruction receiver = readLocal(closureData.closureElement); | 503 HInstruction receiver = readLocal(closureData.closureElement); |
| 499 TypeMask type = local is BoxLocal | 504 TypeMask type = local is BoxLocal |
| 500 ? builder.backend.nonNullType | 505 ? builder.backend.nonNullType |
| 501 : builder.getTypeOfCapturedVariable(redirect); | 506 : builder.getTypeOfCapturedVariable(redirect); |
| 502 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); | 507 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); |
| 503 builder.add(fieldGet); | 508 builder.add(fieldGet); |
| 504 return fieldGet..sourceInformation = sourceInformation; | 509 return fieldGet..sourceInformation = sourceInformation; |
| 505 } else if (isBoxed(local)) { | 510 } else if (isBoxed(local)) { |
| 506 BoxFieldElement redirect = redirectionMapping[local]; | 511 BoxFieldElement redirect = redirectionMapping[local]; |
| 507 // In the function that declares the captured variable the box is | 512 // In the function that declares the captured variable the box is |
| 508 // accessed as direct local. Inside the nested closure the box is | 513 // accessed as direct local. Inside the nested closure the box is |
| 509 // accessed through a closure-field. | 514 // accessed through a closure-field. |
| 510 // Calling [readLocal] makes sure we generate the correct code to get | 515 // Calling [readLocal] makes sure we generate the correct code to get |
| 511 // the box. | 516 // the box. |
| 512 HInstruction box = readLocal(redirect.box); | 517 HInstruction box = readLocal(redirect.box); |
| 513 HInstruction lookup = new HFieldGet( | 518 HInstruction lookup = new HFieldGet( |
| 514 redirect, box, builder.getTypeOfCapturedVariable(redirect)); | 519 redirect, box, builder.getTypeOfCapturedVariable(redirect)); |
| 515 builder.add(lookup); | 520 builder.add(lookup); |
| 516 return lookup..sourceInformation = sourceInformation; | 521 return lookup..sourceInformation = sourceInformation; |
| 517 } else { | 522 } else { |
| 518 assert(isUsedInTryOrGenerator(local)); | 523 assert(isUsedInTryOrGenerator(local)); |
| 519 HLocalValue localValue = getLocal(local); | 524 HLocalValue localValue = getLocal(local); |
| 520 HInstruction instruction = new HLocalGet( | 525 HInstruction instruction = new HLocalGet( |
| 521 local, localValue, builder.backend.dynamicType); | 526 local, localValue, builder.backend.dynamicType, sourceInformation); |
| 522 builder.add(instruction); | 527 builder.add(instruction); |
| 523 return instruction..sourceInformation = sourceInformation; | 528 return instruction; |
| 524 } | 529 } |
| 525 } | 530 } |
| 526 | 531 |
| 527 HInstruction readThis() { | 532 HInstruction readThis() { |
| 528 HInstruction res = readLocal(closureData.thisLocal); | 533 HInstruction res = readLocal(closureData.thisLocal); |
| 529 if (res.instructionType == null) { | 534 if (res.instructionType == null) { |
| 530 res.instructionType = builder.getTypeOfThis(); | 535 res.instructionType = builder.getTypeOfThis(); |
| 531 } | 536 } |
| 532 return res; | 537 return res; |
| 533 } | 538 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 555 return new TypeVariableLocal(type, executableContext); | 560 return new TypeVariableLocal(type, executableContext); |
| 556 }); | 561 }); |
| 557 } | 562 } |
| 558 | 563 |
| 559 /** | 564 /** |
| 560 * Sets the [element] to [value]. If the element is boxed or stored in a | 565 * Sets the [element] to [value]. If the element is boxed or stored in a |
| 561 * closure then the method generates code to set the value. | 566 * closure then the method generates code to set the value. |
| 562 */ | 567 */ |
| 563 void updateLocal(Local local, HInstruction value, | 568 void updateLocal(Local local, HInstruction value, |
| 564 {SourceInformation sourceInformation}) { | 569 {SourceInformation sourceInformation}) { |
| 570 if (value is HRef) { |
| 571 HRef ref = value; |
| 572 value = ref.value; |
| 573 } |
| 565 assert(!isStoredInClosureField(local)); | 574 assert(!isStoredInClosureField(local)); |
| 566 if (isAccessedDirectly(local)) { | 575 if (isAccessedDirectly(local)) { |
| 567 directLocals[local] = value; | 576 directLocals[local] = value; |
| 568 } else if (isBoxed(local)) { | 577 } else if (isBoxed(local)) { |
| 569 BoxFieldElement redirect = redirectionMapping[local]; | 578 BoxFieldElement redirect = redirectionMapping[local]; |
| 570 // The box itself could be captured, or be local. A local variable that | 579 // The box itself could be captured, or be local. A local variable that |
| 571 // is captured will be boxed, but the box itself will be a local. | 580 // is captured will be boxed, but the box itself will be a local. |
| 572 // Inside the closure the box is stored in a closure-field and cannot | 581 // Inside the closure the box is stored in a closure-field and cannot |
| 573 // be accessed directly. | 582 // be accessed directly. |
| 574 HInstruction box = readLocal(redirect.box); | 583 HInstruction box = readLocal(redirect.box); |
| (...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1642 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 1651 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 1643 handleIf( | 1652 handleIf( |
| 1644 function, | 1653 function, |
| 1645 visitCondition: () { | 1654 visitCondition: () { |
| 1646 HParameterValue parameter = parameters.values.first; | 1655 HParameterValue parameter = parameters.values.first; |
| 1647 push(new HIdentity( | 1656 push(new HIdentity( |
| 1648 parameter, graph.addConstantNull(compiler), null, | 1657 parameter, graph.addConstantNull(compiler), null, |
| 1649 backend.boolType)); | 1658 backend.boolType)); |
| 1650 }, | 1659 }, |
| 1651 visitThen: () { | 1660 visitThen: () { |
| 1652 // TODO(johnniwinther): Add source information. | |
| 1653 closeAndGotoExit(new HReturn( | 1661 closeAndGotoExit(new HReturn( |
| 1654 graph.addConstantBool(false, compiler), | 1662 graph.addConstantBool(false, compiler), |
| 1655 null)); | 1663 sourceInformationBuilder |
| 1664 .buildImplicitReturn(functionElement))); |
| 1656 }, | 1665 }, |
| 1657 visitElse: null); | 1666 visitElse: null, |
| 1667 sourceInformation: sourceInformationBuilder.buildIf(function.body)); |
| 1658 } | 1668 } |
| 1659 } | 1669 } |
| 1660 function.body.accept(this); | 1670 function.body.accept(this); |
| 1661 return closeFunction(); | 1671 return closeFunction(); |
| 1662 } | 1672 } |
| 1663 | 1673 |
| 1664 HGraph buildCheckedSetter(VariableElement field) { | 1674 HGraph buildCheckedSetter(VariableElement field) { |
| 1665 openFunction(field, field.node); | 1675 openFunction(field, field.node); |
| 1666 HInstruction thisInstruction = localsHandler.readThis(); | 1676 HInstruction thisInstruction = localsHandler.readThis(); |
| 1667 // Use dynamic type because the type computed by the inferrer is | 1677 // Use dynamic type because the type computed by the inferrer is |
| (...skipping 3222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4890 pushInvokeStatic( | 4900 pushInvokeStatic( |
| 4891 null, | 4901 null, |
| 4892 typeInfoSetterElement, | 4902 typeInfoSetterElement, |
| 4893 <HInstruction>[newObject, typeInfo], | 4903 <HInstruction>[newObject, typeInfo], |
| 4894 typeMask: backend.dynamicType, | 4904 typeMask: backend.dynamicType, |
| 4895 sourceInformation: newObject.sourceInformation); | 4905 sourceInformation: newObject.sourceInformation); |
| 4896 | 4906 |
| 4897 // The new object will now be referenced through the | 4907 // The new object will now be referenced through the |
| 4898 // `setRuntimeTypeInfo` call. We therefore set the type of that | 4908 // `setRuntimeTypeInfo` call. We therefore set the type of that |
| 4899 // instruction to be of the object's type. | 4909 // instruction to be of the object's type. |
| 4900 assert(stack.last is HInvokeStatic || stack.last == newObject); | 4910 assert(invariant( |
| 4911 CURRENT_ELEMENT_SPANNABLE, |
| 4912 stack.last is HInvokeStatic || stack.last == newObject, |
| 4913 message: |
| 4914 "Unexpected `stack.last`: Found ${stack.last}, " |
| 4915 "expected ${newObject} or an HInvokeStatic. " |
| 4916 "State: element=$element, rtiInputs=$rtiInputs, stack=$stack.")); |
| 4901 stack.last.instructionType = newObject.instructionType; | 4917 stack.last.instructionType = newObject.instructionType; |
| 4902 return pop(); | 4918 return pop(); |
| 4903 } | 4919 } |
| 4904 | 4920 |
| 4905 void handleNewSend(ast.NewExpression node) { | 4921 void handleNewSend(ast.NewExpression node) { |
| 4906 ast.Send send = node.send; | 4922 ast.Send send = node.send; |
| 4907 generateIsDeferredLoadedCheckOfSend(send); | 4923 generateIsDeferredLoadedCheckOfSend(send); |
| 4908 | 4924 |
| 4909 bool isFixedList = false; | 4925 bool isFixedList = false; |
| 4910 bool isFixedListConstructorCall = | 4926 bool isFixedListConstructorCall = |
| (...skipping 3948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8859 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8875 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 8860 unaliased.accept(this, builder); | 8876 unaliased.accept(this, builder); |
| 8861 } | 8877 } |
| 8862 | 8878 |
| 8863 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8879 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 8864 JavaScriptBackend backend = builder.compiler.backend; | 8880 JavaScriptBackend backend = builder.compiler.backend; |
| 8865 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8881 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 8866 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8882 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 8867 } | 8883 } |
| 8868 } | 8884 } |
| OLD | NEW |