| 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 import 'dart:collection'; | 5 import 'dart:collection'; |
| 6 | 6 |
| 7 import 'package:js_runtime/shared/embedded_names.dart'; | 7 import 'package:js_runtime/shared/embedded_names.dart'; |
| 8 | 8 |
| 9 import '../closure.dart'; | 9 import '../closure.dart'; |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 work.registry.worldImpact | 80 work.registry.worldImpact |
| 81 .registerConstantUse(new ConstantUse.init(initialValue)); | 81 .registerConstantUse(new ConstantUse.init(initialValue)); |
| 82 // We don't need to generate code for static or top-level | 82 // We don't need to generate code for static or top-level |
| 83 // variables. For instance variables, we may need to generate | 83 // variables. For instance variables, we may need to generate |
| 84 // the checked setter. | 84 // the checked setter. |
| 85 if (field.isStatic || field.isTopLevel) { | 85 if (field.isStatic || field.isTopLevel) { |
| 86 /// No code is created for this field. | 86 /// No code is created for this field. |
| 87 return true; | 87 return true; |
| 88 } | 88 } |
| 89 } else { | 89 } else { |
| 90 assert(invariant( | 90 assert( |
| 91 field, | |
| 92 field.isInstanceMember || | 91 field.isInstanceMember || |
| 93 constant.isImplicit || | 92 constant.isImplicit || |
| 94 constant.isPotential, | 93 constant.isPotential, |
| 95 message: "Constant expression without value: " | 94 failedAt( |
| 95 field, |
| 96 "Constant expression without value: " |
| 96 "${constant.toStructuredText()}.")); | 97 "${constant.toStructuredText()}.")); |
| 97 } | 98 } |
| 98 } else { | 99 } else { |
| 99 // If the constant-handler was not able to produce a result we have to | 100 // If the constant-handler was not able to produce a result we have to |
| 100 // go through the builder (below) to generate the lazy initializer for | 101 // go through the builder (below) to generate the lazy initializer for |
| 101 // the static variable. | 102 // the static variable. |
| 102 // We also need to register the use of the cyclic-error helper. | 103 // We also need to register the use of the cyclic-error helper. |
| 103 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke( | 104 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke( |
| 104 backend.commonElements.cyclicThrowHelper, CallStructure.ONE_ARG)); | 105 backend.commonElements.cyclicThrowHelper, CallStructure.ONE_ARG)); |
| 105 } | 106 } |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 /// | 319 /// |
| 319 /// Note: this helper is used selectively. When we know that we are in a | 320 /// Note: this helper is used selectively. When we know that we are in a |
| 320 /// context were we don't expect to see a constructor body element, we | 321 /// context were we don't expect to see a constructor body element, we |
| 321 /// directly fetch the data from the global inference results. | 322 /// directly fetch the data from the global inference results. |
| 322 GlobalTypeInferenceElementResult _resultOf(MemberElement element) => | 323 GlobalTypeInferenceElementResult _resultOf(MemberElement element) => |
| 323 globalInferenceResults.resultOfMember( | 324 globalInferenceResults.resultOfMember( |
| 324 element is ConstructorBodyElementX ? element.constructor : element); | 325 element is ConstructorBodyElementX ? element.constructor : element); |
| 325 | 326 |
| 326 /// Build the graph for [target]. | 327 /// Build the graph for [target]. |
| 327 HGraph build() { | 328 HGraph build() { |
| 328 assert(invariant(target, target.isImplementation)); | 329 assert(target.isImplementation, failedAt(target)); |
| 329 HInstruction.idCounter = 0; | 330 HInstruction.idCounter = 0; |
| 330 // TODO(sigmund): remove `result` and return graph directly, need to ensure | 331 // TODO(sigmund): remove `result` and return graph directly, need to ensure |
| 331 // that it can never be null (see result in buildFactory for instance). | 332 // that it can never be null (see result in buildFactory for instance). |
| 332 var result; | 333 var result; |
| 333 if (target.isGenerativeConstructor) { | 334 if (target.isGenerativeConstructor) { |
| 334 result = buildFactory(resolvedAst); | 335 result = buildFactory(resolvedAst); |
| 335 } else if (target.isGenerativeConstructorBody || | 336 } else if (target.isGenerativeConstructorBody || |
| 336 target.isFactoryConstructor || | 337 target.isFactoryConstructor || |
| 337 target.isFunction || | 338 target.isFunction || |
| 338 target.isGetter || | 339 target.isGetter || |
| (...skipping 18 matching lines...) Expand all Loading... |
| 357 } | 358 } |
| 358 | 359 |
| 359 /** | 360 /** |
| 360 * Returns a complete argument list for a call of [function]. | 361 * Returns a complete argument list for a call of [function]. |
| 361 */ | 362 */ |
| 362 List<HInstruction> completeSendArgumentsList( | 363 List<HInstruction> completeSendArgumentsList( |
| 363 FunctionElement function, | 364 FunctionElement function, |
| 364 Selector selector, | 365 Selector selector, |
| 365 List<HInstruction> providedArguments, | 366 List<HInstruction> providedArguments, |
| 366 ast.Node currentNode) { | 367 ast.Node currentNode) { |
| 367 assert(invariant(function, function.isImplementation)); | 368 assert(function.isImplementation, failedAt(function)); |
| 368 assert(providedArguments != null); | 369 assert(providedArguments != null); |
| 369 | 370 |
| 370 bool isInstanceMember = function.isInstanceMember; | 371 bool isInstanceMember = function.isInstanceMember; |
| 371 // For static calls, [providedArguments] is complete, default arguments | 372 // For static calls, [providedArguments] is complete, default arguments |
| 372 // have been included if necessary, see [makeStaticArgumentList]. | 373 // have been included if necessary, see [makeStaticArgumentList]. |
| 373 if (!isInstanceMember || | 374 if (!isInstanceMember || |
| 374 currentNode == null || // In erroneous code, currentNode can be null. | 375 currentNode == null || // In erroneous code, currentNode can be null. |
| 375 providedArgumentsKnownToBeComplete(currentNode) || | 376 providedArgumentsKnownToBeComplete(currentNode) || |
| 376 function.isGenerativeConstructorBody || | 377 function.isGenerativeConstructorBody || |
| 377 selector.isGetter) { | 378 selector.isGetter) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 | 479 |
| 479 // Bail out early if the inlining decision is in the cache and we can't | 480 // Bail out early if the inlining decision is in the cache and we can't |
| 480 // inline (no need to check the hard constraints). | 481 // inline (no need to check the hard constraints). |
| 481 bool cachedCanBeInlined = | 482 bool cachedCanBeInlined = |
| 482 inlineCache.canInline(declaration, insideLoop: insideLoop); | 483 inlineCache.canInline(declaration, insideLoop: insideLoop); |
| 483 if (cachedCanBeInlined == false) return false; | 484 if (cachedCanBeInlined == false) return false; |
| 484 | 485 |
| 485 bool meetsHardConstraints() { | 486 bool meetsHardConstraints() { |
| 486 if (options.disableInlining) return false; | 487 if (options.disableInlining) return false; |
| 487 | 488 |
| 488 assert(invariant( | 489 assert( |
| 489 currentNode != null ? currentNode : function, | |
| 490 selector != null || | 490 selector != null || |
| 491 Elements.isStaticOrTopLevel(function) || | 491 Elements.isStaticOrTopLevel(function) || |
| 492 function.isGenerativeConstructorBody, | 492 function.isGenerativeConstructorBody, |
| 493 message: "Missing selector for inlining of $function.")); | 493 failedAt(currentNode ?? function, |
| 494 "Missing selector for inlining of $function.")); |
| 494 if (selector != null) { | 495 if (selector != null) { |
| 495 if (!selector.applies(function)) return false; | 496 if (!selector.applies(function)) return false; |
| 496 if (mask != null && !mask.canHit(function, selector, closedWorld)) { | 497 if (mask != null && !mask.canHit(function, selector, closedWorld)) { |
| 497 return false; | 498 return false; |
| 498 } | 499 } |
| 499 } | 500 } |
| 500 | 501 |
| 501 if (nativeData.isJsInteropMember(function)) return false; | 502 if (nativeData.isJsInteropMember(function)) return false; |
| 502 | 503 |
| 503 // Don't inline operator== methods if the parameter can be null. | 504 // Don't inline operator== methods if the parameter can be null. |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 /** | 678 /** |
| 678 * Return null so it is simple to remove the optional parameters completely | 679 * Return null so it is simple to remove the optional parameters completely |
| 679 * from interop methods to match JavaScript semantics for omitted arguments. | 680 * from interop methods to match JavaScript semantics for omitted arguments. |
| 680 */ | 681 */ |
| 681 HInstruction handleConstantForOptionalParameterJsInterop(Element parameter) => | 682 HInstruction handleConstantForOptionalParameterJsInterop(Element parameter) => |
| 682 null; | 683 null; |
| 683 | 684 |
| 684 HInstruction handleConstantForOptionalParameter(ParameterElement parameter) { | 685 HInstruction handleConstantForOptionalParameter(ParameterElement parameter) { |
| 685 ConstantValue constantValue = | 686 ConstantValue constantValue = |
| 686 constants.getConstantValue(parameter.constant); | 687 constants.getConstantValue(parameter.constant); |
| 687 assert(invariant(parameter, constantValue != null, | 688 assert(constantValue != null, |
| 688 message: 'No constant computed for $parameter')); | 689 failedAt(parameter, 'No constant computed for $parameter')); |
| 689 return graph.addConstant(constantValue, closedWorld); | 690 return graph.addConstant(constantValue, closedWorld); |
| 690 } | 691 } |
| 691 | 692 |
| 692 ClassElement get currentNonClosureClass { | 693 ClassElement get currentNonClosureClass { |
| 693 ClassElement cls = sourceElement.enclosingClass; | 694 ClassElement cls = sourceElement.enclosingClass; |
| 694 if (cls != null && cls.isClosure) { | 695 if (cls != null && cls.isClosure) { |
| 695 dynamic closureClass = cls; | 696 dynamic closureClass = cls; |
| 696 // ignore: UNDEFINED_GETTER | 697 // ignore: UNDEFINED_GETTER |
| 697 return closureClass.methodElement.enclosingClass; | 698 return closureClass.methodElement.enclosingClass; |
| 698 } else { | 699 } else { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 710 <ResolutionDartType>[]; | 711 <ResolutionDartType>[]; |
| 711 | 712 |
| 712 final List<AstInliningState> inliningStack = <AstInliningState>[]; | 713 final List<AstInliningState> inliningStack = <AstInliningState>[]; |
| 713 | 714 |
| 714 Local returnLocal; | 715 Local returnLocal; |
| 715 ResolutionDartType returnType; | 716 ResolutionDartType returnType; |
| 716 | 717 |
| 717 ConstantValue getConstantForNode(ast.Node node) { | 718 ConstantValue getConstantForNode(ast.Node node) { |
| 718 ConstantValue constantValue = | 719 ConstantValue constantValue = |
| 719 constants.getConstantValueForNode(node, elements); | 720 constants.getConstantValueForNode(node, elements); |
| 720 assert(invariant(node, constantValue != null, | 721 assert(constantValue != null, |
| 721 message: 'No constant computed for $node')); | 722 failedAt(node, 'No constant computed for $node')); |
| 722 return constantValue; | 723 return constantValue; |
| 723 } | 724 } |
| 724 | 725 |
| 725 HInstruction addConstant(ast.Node node) { | 726 HInstruction addConstant(ast.Node node) { |
| 726 return graph.addConstant(getConstantForNode(node), closedWorld); | 727 return graph.addConstant(getConstantForNode(node), closedWorld); |
| 727 } | 728 } |
| 728 | 729 |
| 729 /** | 730 /** |
| 730 * Documentation wanted -- johnniwinther | 731 * Documentation wanted -- johnniwinther |
| 731 * | 732 * |
| 732 * Invariant: [functionElement] must be an implementation element. | 733 * Invariant: [functionElement] must be an implementation element. |
| 733 */ | 734 */ |
| 734 HGraph buildMethod(MethodElement functionElement) { | 735 HGraph buildMethod(MethodElement functionElement) { |
| 735 assert(invariant(functionElement, functionElement.isImplementation)); | 736 assert(functionElement.isImplementation, failedAt(functionElement)); |
| 736 graph.calledInLoop = | 737 graph.calledInLoop = |
| 737 closedWorld.isCalledInLoop(functionElement.declaration); | 738 closedWorld.isCalledInLoop(functionElement.declaration); |
| 738 ast.FunctionExpression function = resolvedAst.node; | 739 ast.FunctionExpression function = resolvedAst.node; |
| 739 assert(function != null); | 740 assert(function != null); |
| 740 assert(elements.getFunctionDefinition(function) != null); | 741 assert(elements.getFunctionDefinition(function) != null); |
| 741 openFunction(functionElement, function); | 742 openFunction(functionElement, function); |
| 742 String name = functionElement.name; | 743 String name = functionElement.name; |
| 743 if (nativeData.isJsInteropMember(functionElement)) { | 744 if (nativeData.isJsInteropMember(functionElement)) { |
| 744 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), | 745 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), |
| 745 sourceInformationBuilder.buildGeneric(function))); | 746 sourceInformationBuilder.buildGeneric(function))); |
| 746 var value = pop(); | 747 var value = pop(); |
| 747 closeAndGotoExit(new HReturn( | 748 closeAndGotoExit(new HReturn( |
| 748 value, sourceInformationBuilder.buildReturn(functionElement.node))); | 749 value, sourceInformationBuilder.buildReturn(functionElement.node))); |
| 749 return closeFunction(); | 750 return closeFunction(); |
| 750 } | 751 } |
| 751 assert(invariant(functionElement, !function.modifiers.isExternal)); | 752 assert(!function.modifiers.isExternal, failedAt(functionElement)); |
| 752 | 753 |
| 753 // If [functionElement] is `operator==` we explicitly add a null check at | 754 // If [functionElement] is `operator==` we explicitly add a null check at |
| 754 // the beginning of the method. This is to avoid having call sites do the | 755 // the beginning of the method. This is to avoid having call sites do the |
| 755 // null check. | 756 // null check. |
| 756 if (name == '==') { | 757 if (name == '==') { |
| 757 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 758 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 758 handleIf( | 759 handleIf( |
| 759 node: function, | 760 node: function, |
| 760 visitCondition: () { | 761 visitCondition: () { |
| 761 HParameterValue parameter = parameters.values.first; | 762 HParameterValue parameter = parameters.values.first; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 // If the method is intercepted, we want the actual receiver | 811 // If the method is intercepted, we want the actual receiver |
| 811 // to be the first parameter. | 812 // to be the first parameter. |
| 812 graph.entry.addBefore(graph.entry.last, parameter); | 813 graph.entry.addBefore(graph.entry.last, parameter); |
| 813 HInstruction value = | 814 HInstruction value = |
| 814 typeBuilder.potentiallyCheckOrTrustType(parameter, field.type); | 815 typeBuilder.potentiallyCheckOrTrustType(parameter, field.type); |
| 815 add(new HFieldSet(field, thisInstruction, value)); | 816 add(new HFieldSet(field, thisInstruction, value)); |
| 816 return closeFunction(); | 817 return closeFunction(); |
| 817 } | 818 } |
| 818 | 819 |
| 819 HGraph buildLazyInitializer(FieldElement variable) { | 820 HGraph buildLazyInitializer(FieldElement variable) { |
| 820 assert(invariant(variable, resolvedAst.element == variable, | 821 assert(resolvedAst.element == variable, |
| 821 message: "Unexpected variable $variable for $resolvedAst.")); | 822 failedAt(variable, "Unexpected variable $variable for $resolvedAst.")); |
| 822 inLazyInitializerExpression = true; | 823 inLazyInitializerExpression = true; |
| 823 ast.VariableDefinitions node = resolvedAst.node; | 824 ast.VariableDefinitions node = resolvedAst.node; |
| 824 ast.Node initializer = resolvedAst.body; | 825 ast.Node initializer = resolvedAst.body; |
| 825 assert(invariant(variable, initializer != null, | 826 assert( |
| 826 message: "Non-constant variable $variable has no initializer.")); | 827 initializer != null, |
| 828 failedAt( |
| 829 variable, "Non-constant variable $variable has no initializer.")); |
| 827 openFunction(variable, node); | 830 openFunction(variable, node); |
| 828 visit(initializer); | 831 visit(initializer); |
| 829 HInstruction value = pop(); | 832 HInstruction value = pop(); |
| 830 value = typeBuilder.potentiallyCheckOrTrustType(value, variable.type); | 833 value = typeBuilder.potentiallyCheckOrTrustType(value, variable.type); |
| 831 // In the case of multiple declarations (and some definitions) on the same | 834 // In the case of multiple declarations (and some definitions) on the same |
| 832 // line, the source pointer needs to point to the right initialized | 835 // line, the source pointer needs to point to the right initialized |
| 833 // variable. So find the specific initialized variable we are referring to. | 836 // variable. So find the specific initialized variable we are referring to. |
| 834 ast.Node sourceInfoNode = initializer; | 837 ast.Node sourceInfoNode = initializer; |
| 835 for (var definition in node.definitions) { | 838 for (var definition in node.definitions) { |
| 836 if (definition is ast.SendSet && | 839 if (definition is ast.SendSet && |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 localsHandler.closureData = oldClosureData; | 1042 localsHandler.closureData = oldClosureData; |
| 1040 resolvedAst = oldResolvedAst; | 1043 resolvedAst = oldResolvedAst; |
| 1041 elementInferenceResults = oldElementInferenceResults; | 1044 elementInferenceResults = oldElementInferenceResults; |
| 1042 }); | 1045 }); |
| 1043 } | 1046 } |
| 1044 | 1047 |
| 1045 void buildInitializers( | 1048 void buildInitializers( |
| 1046 ConstructorElement constructor, | 1049 ConstructorElement constructor, |
| 1047 List<ResolvedAst> constructorResolvedAsts, | 1050 List<ResolvedAst> constructorResolvedAsts, |
| 1048 Map<Element, HInstruction> fieldValues) { | 1051 Map<Element, HInstruction> fieldValues) { |
| 1049 assert(invariant( | 1052 assert( |
| 1050 constructor, resolvedAst.element == constructor.declaration, | 1053 resolvedAst.element == constructor.declaration, |
| 1051 message: "Expected ResolvedAst for $constructor, found $resolvedAst")); | 1054 failedAt(constructor, |
| 1055 "Expected ResolvedAst for $constructor, found $resolvedAst")); |
| 1052 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 1056 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 1053 buildParsedInitializers( | 1057 buildParsedInitializers( |
| 1054 constructor, constructorResolvedAsts, fieldValues); | 1058 constructor, constructorResolvedAsts, fieldValues); |
| 1055 } else { | 1059 } else { |
| 1056 buildSynthesizedConstructorInitializers( | 1060 buildSynthesizedConstructorInitializers( |
| 1057 constructor, constructorResolvedAsts, fieldValues); | 1061 constructor, constructorResolvedAsts, fieldValues); |
| 1058 } | 1062 } |
| 1059 } | 1063 } |
| 1060 | 1064 |
| 1061 void buildSynthesizedConstructorInitializers( | 1065 void buildSynthesizedConstructorInitializers( |
| 1062 ConstructorElement constructor, | 1066 ConstructorElement constructor, |
| 1063 List<ResolvedAst> constructorResolvedAsts, | 1067 List<ResolvedAst> constructorResolvedAsts, |
| 1064 Map<Element, HInstruction> fieldValues) { | 1068 Map<Element, HInstruction> fieldValues) { |
| 1065 assert(invariant(constructor, constructor.isSynthesized, | 1069 assert( |
| 1066 message: "Unexpected unsynthesized constructor: $constructor")); | 1070 constructor.isSynthesized, |
| 1071 failedAt( |
| 1072 constructor, "Unexpected unsynthesized constructor: $constructor")); |
| 1067 List<HInstruction> arguments = <HInstruction>[]; | 1073 List<HInstruction> arguments = <HInstruction>[]; |
| 1068 HInstruction compileArgument(ParameterElement parameter) { | 1074 HInstruction compileArgument(ParameterElement parameter) { |
| 1069 return localsHandler.readLocal(parameter); | 1075 return localsHandler.readLocal(parameter); |
| 1070 } | 1076 } |
| 1071 | 1077 |
| 1072 ConstructorElement target = constructor.definingConstructor.implementation; | 1078 ConstructorElement target = constructor.definingConstructor.implementation; |
| 1073 bool match = !target.isMalformed && | 1079 bool match = !target.isMalformed && |
| 1074 Elements.addForwardingElementArgumentsToList<HInstruction>( | 1080 Elements.addForwardingElementArgumentsToList<HInstruction>( |
| 1075 constructor, | 1081 constructor, |
| 1076 arguments, | 1082 arguments, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1100 * with sub constructors having a lower index than super constructors. | 1106 * with sub constructors having a lower index than super constructors. |
| 1101 * | 1107 * |
| 1102 * Invariant: The [constructor] and elements in [constructors] must all be | 1108 * Invariant: The [constructor] and elements in [constructors] must all be |
| 1103 * implementation elements. | 1109 * implementation elements. |
| 1104 */ | 1110 */ |
| 1105 void buildParsedInitializers( | 1111 void buildParsedInitializers( |
| 1106 ConstructorElement constructor, | 1112 ConstructorElement constructor, |
| 1107 List<ResolvedAst> constructorResolvedAsts, | 1113 List<ResolvedAst> constructorResolvedAsts, |
| 1108 Map<Element, HInstruction> fieldValues) { | 1114 Map<Element, HInstruction> fieldValues) { |
| 1109 assert( | 1115 assert( |
| 1110 invariant(constructor, resolvedAst.element == constructor.declaration)); | 1116 resolvedAst.element == constructor.declaration, failedAt(constructor)); |
| 1111 assert(invariant(constructor, constructor.isImplementation)); | 1117 assert(constructor.isImplementation, failedAt(constructor)); |
| 1112 assert(invariant(constructor, !constructor.isSynthesized, | 1118 assert( |
| 1113 message: "Unexpected synthesized constructor: $constructor")); | 1119 !constructor.isSynthesized, |
| 1120 failedAt( |
| 1121 constructor, "Unexpected synthesized constructor: $constructor")); |
| 1114 ast.FunctionExpression functionNode = resolvedAst.node; | 1122 ast.FunctionExpression functionNode = resolvedAst.node; |
| 1115 | 1123 |
| 1116 bool foundSuperOrRedirect = false; | 1124 bool foundSuperOrRedirect = false; |
| 1117 if (functionNode.initializers != null) { | 1125 if (functionNode.initializers != null) { |
| 1118 Link<ast.Node> initializers = functionNode.initializers.nodes; | 1126 Link<ast.Node> initializers = functionNode.initializers.nodes; |
| 1119 for (Link<ast.Node> link = initializers; | 1127 for (Link<ast.Node> link = initializers; |
| 1120 !link.isEmpty; | 1128 !link.isEmpty; |
| 1121 link = link.tail) { | 1129 link = link.tail) { |
| 1122 assert(link.head is ast.Send); | 1130 assert(link.head is ast.Send); |
| 1123 if (link.head is! ast.SendSet) { | 1131 if (link.head is! ast.SendSet) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 } | 1185 } |
| 1178 | 1186 |
| 1179 /** | 1187 /** |
| 1180 * Run through the fields of [cls] and add their potential | 1188 * Run through the fields of [cls] and add their potential |
| 1181 * initializers. | 1189 * initializers. |
| 1182 * | 1190 * |
| 1183 * Invariant: [classElement] must be an implementation element. | 1191 * Invariant: [classElement] must be an implementation element. |
| 1184 */ | 1192 */ |
| 1185 void buildFieldInitializers( | 1193 void buildFieldInitializers( |
| 1186 ClassElement classElement, Map<Element, HInstruction> fieldValues) { | 1194 ClassElement classElement, Map<Element, HInstruction> fieldValues) { |
| 1187 assert(invariant(classElement, classElement.isImplementation)); | 1195 assert(classElement.isImplementation, failedAt(classElement)); |
| 1188 classElement.forEachInstanceField( | 1196 classElement.forEachInstanceField( |
| 1189 (ClassElement enclosingClass, FieldElement member) { | 1197 (ClassElement enclosingClass, FieldElement member) { |
| 1190 if (compiler.elementHasCompileTimeError(member)) return; | 1198 if (compiler.elementHasCompileTimeError(member)) return; |
| 1191 reporter.withCurrentElement(member, () { | 1199 reporter.withCurrentElement(member, () { |
| 1192 ResolvedAst fieldResolvedAst = member.resolvedAst; | 1200 ResolvedAst fieldResolvedAst = member.resolvedAst; |
| 1193 ast.Expression initializer = fieldResolvedAst.body; | 1201 ast.Expression initializer = fieldResolvedAst.body; |
| 1194 if (initializer == null) { | 1202 if (initializer == null) { |
| 1195 // Unassigned fields of native classes are not initialized to | 1203 // Unassigned fields of native classes are not initialized to |
| 1196 // prevent overwriting pre-initialized native properties. | 1204 // prevent overwriting pre-initialized native properties. |
| 1197 if (!nativeData.isNativeOrExtendsNative(classElement)) { | 1205 if (!nativeData.isNativeOrExtendsNative(classElement)) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 // Call the JavaScript constructor with the fields as argument. | 1280 // Call the JavaScript constructor with the fields as argument. |
| 1273 List<HInstruction> constructorArguments = <HInstruction>[]; | 1281 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 1274 List<FieldEntity> fields = <FieldEntity>[]; | 1282 List<FieldEntity> fields = <FieldEntity>[]; |
| 1275 | 1283 |
| 1276 classElement.forEachInstanceField( | 1284 classElement.forEachInstanceField( |
| 1277 (ClassElement enclosingClass, FieldElement member) { | 1285 (ClassElement enclosingClass, FieldElement member) { |
| 1278 HInstruction value = fieldValues[member]; | 1286 HInstruction value = fieldValues[member]; |
| 1279 if (value == null) { | 1287 if (value == null) { |
| 1280 // Uninitialized native fields are pre-initialized by the native | 1288 // Uninitialized native fields are pre-initialized by the native |
| 1281 // implementation. | 1289 // implementation. |
| 1282 assert(invariant( | 1290 assert(isNativeUpgradeFactory || reporter.hasReportedError, |
| 1283 member, isNativeUpgradeFactory || reporter.hasReportedError)); | 1291 failedAt(member)); |
| 1284 } else { | 1292 } else { |
| 1285 fields.add(member); | 1293 fields.add(member); |
| 1286 ResolutionDartType type = localsHandler.substInContext(member.type); | 1294 ResolutionDartType type = localsHandler.substInContext(member.type); |
| 1287 constructorArguments | 1295 constructorArguments |
| 1288 .add(typeBuilder.potentiallyCheckOrTrustType(value, type)); | 1296 .add(typeBuilder.potentiallyCheckOrTrustType(value, type)); |
| 1289 } | 1297 } |
| 1290 }, includeSuperAndInjectedMembers: true); | 1298 }, includeSuperAndInjectedMembers: true); |
| 1291 | 1299 |
| 1292 ResolutionInterfaceType type = classElement.thisType; | 1300 ResolutionInterfaceType type = classElement.thisType; |
| 1293 TypeMask ssaType = | 1301 TypeMask ssaType = |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 return null; | 1429 return null; |
| 1422 } | 1430 } |
| 1423 } | 1431 } |
| 1424 | 1432 |
| 1425 /** | 1433 /** |
| 1426 * Documentation wanted -- johnniwinther | 1434 * Documentation wanted -- johnniwinther |
| 1427 * | 1435 * |
| 1428 * Invariant: [functionElement] must be the implementation element. | 1436 * Invariant: [functionElement] must be the implementation element. |
| 1429 */ | 1437 */ |
| 1430 void openFunction(MemberElement element, ast.Node node) { | 1438 void openFunction(MemberElement element, ast.Node node) { |
| 1431 assert(invariant(element, element.isImplementation)); | 1439 assert(element.isImplementation, failedAt(element)); |
| 1432 HBasicBlock block = graph.addNewBlock(); | 1440 HBasicBlock block = graph.addNewBlock(); |
| 1433 open(graph.entry); | 1441 open(graph.entry); |
| 1434 | 1442 |
| 1435 localsHandler.startFunction(element, node, | 1443 localsHandler.startFunction(element, node, |
| 1436 isGenerativeConstructorBody: element.isGenerativeConstructorBody); | 1444 isGenerativeConstructorBody: element.isGenerativeConstructorBody); |
| 1437 close(new HGoto()).addSuccessor(block); | 1445 close(new HGoto()).addSuccessor(block); |
| 1438 | 1446 |
| 1439 open(block); | 1447 open(block); |
| 1440 | 1448 |
| 1441 // Add the type parameters of the class as parameters of this method. This | 1449 // Add the type parameters of the class as parameters of this method. This |
| (...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2118 sourceInformation: sourceInformation); | 2126 sourceInformation: sourceInformation); |
| 2119 } | 2127 } |
| 2120 | 2128 |
| 2121 /// Generate read access of an unresolved static or top level entity. | 2129 /// Generate read access of an unresolved static or top level entity. |
| 2122 void generateStaticUnresolvedGet(ast.Send node, Element element) { | 2130 void generateStaticUnresolvedGet(ast.Send node, Element element) { |
| 2123 if (element is ErroneousElement) { | 2131 if (element is ErroneousElement) { |
| 2124 // An erroneous element indicates an unresolved static getter. | 2132 // An erroneous element indicates an unresolved static getter. |
| 2125 handleInvalidStaticGet(node, element); | 2133 handleInvalidStaticGet(node, element); |
| 2126 } else { | 2134 } else { |
| 2127 // This happens when [element] has parse errors. | 2135 // This happens when [element] has parse errors. |
| 2128 assert(invariant(node, element == null || element.isMalformed)); | 2136 assert(element == null || element.isMalformed, failedAt(node)); |
| 2129 // TODO(ahe): Do something like the above, that is, emit a runtime | 2137 // TODO(ahe): Do something like the above, that is, emit a runtime |
| 2130 // error. | 2138 // error. |
| 2131 stack.add(graph.addConstantNull(closedWorld)); | 2139 stack.add(graph.addConstantNull(closedWorld)); |
| 2132 } | 2140 } |
| 2133 } | 2141 } |
| 2134 | 2142 |
| 2135 /// Read a static or top level [field] of constant value. | 2143 /// Read a static or top level [field] of constant value. |
| 2136 void generateStaticConstGet(ast.Send node, FieldElement field, | 2144 void generateStaticConstGet(ast.Send node, FieldElement field, |
| 2137 ConstantExpression constant, SourceInformation sourceInformation) { | 2145 ConstantExpression constant, SourceInformation sourceInformation) { |
| 2138 ConstantValue value = constants.getConstantValue(constant); | 2146 ConstantValue value = constants.getConstantValue(constant); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2311 } | 2319 } |
| 2312 | 2320 |
| 2313 @override | 2321 @override |
| 2314 void visitTopLevelGetterGet(ast.Send node, FunctionElement getter, _) { | 2322 void visitTopLevelGetterGet(ast.Send node, FunctionElement getter, _) { |
| 2315 generateStaticGetterGet(node, getter); | 2323 generateStaticGetterGet(node, getter); |
| 2316 } | 2324 } |
| 2317 | 2325 |
| 2318 void generateInstanceSetterWithCompiledReceiver( | 2326 void generateInstanceSetterWithCompiledReceiver( |
| 2319 ast.Send send, HInstruction receiver, HInstruction value, | 2327 ast.Send send, HInstruction receiver, HInstruction value, |
| 2320 {Selector selector, TypeMask mask, ast.Node location}) { | 2328 {Selector selector, TypeMask mask, ast.Node location}) { |
| 2321 assert(invariant(send == null ? location : send, | 2329 assert( |
| 2322 send == null || Elements.isInstanceSend(send, elements), | 2330 send == null || Elements.isInstanceSend(send, elements), |
| 2323 message: "Unexpected instance setter" | 2331 failedAt( |
| 2332 send ?? location, |
| 2333 "Unexpected instance setter" |
| 2324 "${send != null ? " element: ${elements[send]}" : ""}")); | 2334 "${send != null ? " element: ${elements[send]}" : ""}")); |
| 2325 if (selector == null) { | 2335 if (selector == null) { |
| 2326 assert(send != null); | 2336 assert(send != null); |
| 2327 selector = elements.getSelector(send); | 2337 selector = elements.getSelector(send); |
| 2328 mask ??= elementInferenceResults.typeOfSend(send); | 2338 mask ??= elementInferenceResults.typeOfSend(send); |
| 2329 } | 2339 } |
| 2330 if (location == null) { | 2340 if (location == null) { |
| 2331 assert(send != null); | 2341 assert(send != null); |
| 2332 location = send; | 2342 location = send; |
| 2333 } | 2343 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2348 argumentValues: arguments); | 2358 argumentValues: arguments); |
| 2349 } | 2359 } |
| 2350 | 2360 |
| 2351 void generateNonInstanceSetter( | 2361 void generateNonInstanceSetter( |
| 2352 ast.SendSet send, Element element, HInstruction value, | 2362 ast.SendSet send, Element element, HInstruction value, |
| 2353 {ast.Node location}) { | 2363 {ast.Node location}) { |
| 2354 if (location == null) { | 2364 if (location == null) { |
| 2355 assert(send != null); | 2365 assert(send != null); |
| 2356 location = send; | 2366 location = send; |
| 2357 } | 2367 } |
| 2358 assert(invariant( | 2368 assert(send == null || !Elements.isInstanceSend(send, elements), |
| 2359 location, send == null || !Elements.isInstanceSend(send, elements), | 2369 failedAt(location, "Unexpected non instance setter: $element.")); |
| 2360 message: "Unexpected non instance setter: $element.")); | |
| 2361 if (Elements.isStaticOrTopLevelField(element)) { | 2370 if (Elements.isStaticOrTopLevelField(element)) { |
| 2362 if (element.isSetter) { | 2371 if (element.isSetter) { |
| 2363 pushInvokeStatic(location, element, <HInstruction>[value]); | 2372 pushInvokeStatic(location, element, <HInstruction>[value]); |
| 2364 pop(); | 2373 pop(); |
| 2365 } else { | 2374 } else { |
| 2366 FieldElement field = element; | 2375 FieldElement field = element; |
| 2367 value = typeBuilder.potentiallyCheckOrTrustType(value, field.type); | 2376 value = typeBuilder.potentiallyCheckOrTrustType(value, field.type); |
| 2368 addWithPosition(new HStaticStore(field, value), location); | 2377 addWithPosition(new HStaticStore(field, value), location); |
| 2369 } | 2378 } |
| 2370 stack.add(value); | 2379 stack.add(value); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2541 } | 2550 } |
| 2542 | 2551 |
| 2543 /** | 2552 /** |
| 2544 * Returns a list with the evaluated [arguments] in the normalized order. | 2553 * Returns a list with the evaluated [arguments] in the normalized order. |
| 2545 * | 2554 * |
| 2546 * Precondition: `this.applies(element, world)`. | 2555 * Precondition: `this.applies(element, world)`. |
| 2547 * Invariant: [element] must be an implementation element. | 2556 * Invariant: [element] must be an implementation element. |
| 2548 */ | 2557 */ |
| 2549 List<HInstruction> makeStaticArgumentList(CallStructure callStructure, | 2558 List<HInstruction> makeStaticArgumentList(CallStructure callStructure, |
| 2550 Link<ast.Node> arguments, MethodElement element) { | 2559 Link<ast.Node> arguments, MethodElement element) { |
| 2551 assert(invariant(element, element.isDeclaration)); | 2560 assert(element.isDeclaration, failedAt(element)); |
| 2552 | 2561 |
| 2553 HInstruction compileArgument(ast.Node argument) { | 2562 HInstruction compileArgument(ast.Node argument) { |
| 2554 visit(argument); | 2563 visit(argument); |
| 2555 return pop(); | 2564 return pop(); |
| 2556 } | 2565 } |
| 2557 | 2566 |
| 2558 return Elements.makeArgumentsList<HInstruction>( | 2567 return Elements.makeArgumentsList<HInstruction>( |
| 2559 callStructure, | 2568 callStructure, |
| 2560 arguments, | 2569 arguments, |
| 2561 element.implementation, | 2570 element.implementation, |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2670 void handleForeignJs(ast.Send node) { | 2679 void handleForeignJs(ast.Send node) { |
| 2671 Link<ast.Node> link = node.arguments; | 2680 Link<ast.Node> link = node.arguments; |
| 2672 // Don't visit the first argument, which is the type, and the second | 2681 // Don't visit the first argument, which is the type, and the second |
| 2673 // argument, which is the foreign code. | 2682 // argument, which is the foreign code. |
| 2674 if (link.isEmpty || link.tail.isEmpty) { | 2683 if (link.isEmpty || link.tail.isEmpty) { |
| 2675 // We should not get here because the call should be compiled to NSM. | 2684 // We should not get here because the call should be compiled to NSM. |
| 2676 reporter.internalError( | 2685 reporter.internalError( |
| 2677 node.argumentsNode, 'At least two arguments expected.'); | 2686 node.argumentsNode, 'At least two arguments expected.'); |
| 2678 } | 2687 } |
| 2679 native.NativeBehavior nativeBehavior = elements.getNativeData(node); | 2688 native.NativeBehavior nativeBehavior = elements.getNativeData(node); |
| 2680 assert(invariant(node, nativeBehavior != null, | 2689 assert( |
| 2681 message: "No NativeBehavior for $node")); | 2690 nativeBehavior != null, failedAt(node, "No NativeBehavior for $node")); |
| 2682 | 2691 |
| 2683 List<HInstruction> inputs = <HInstruction>[]; | 2692 List<HInstruction> inputs = <HInstruction>[]; |
| 2684 addGenericSendArgumentsToList(link.tail.tail, inputs); | 2693 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 2685 | 2694 |
| 2686 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { | 2695 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
| 2687 reporter.reportErrorMessage(node, MessageKind.GENERIC, { | 2696 reporter.reportErrorMessage(node, MessageKind.GENERIC, { |
| 2688 'text': 'Mismatch between number of placeholders' | 2697 'text': 'Mismatch between number of placeholders' |
| 2689 ' and number of arguments.' | 2698 ' and number of arguments.' |
| 2690 }); | 2699 }); |
| 2691 // Result expected on stack. | 2700 // Result expected on stack. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2833 | 2842 |
| 2834 js.Template template = emitter.builtinTemplateFor(JsBuiltin.values[index]); | 2843 js.Template template = emitter.builtinTemplateFor(JsBuiltin.values[index]); |
| 2835 | 2844 |
| 2836 List<HInstruction> compiledArguments = <HInstruction>[]; | 2845 List<HInstruction> compiledArguments = <HInstruction>[]; |
| 2837 for (int i = 2; i < arguments.length; i++) { | 2846 for (int i = 2; i < arguments.length; i++) { |
| 2838 visit(arguments[i]); | 2847 visit(arguments[i]); |
| 2839 compiledArguments.add(pop()); | 2848 compiledArguments.add(pop()); |
| 2840 } | 2849 } |
| 2841 | 2850 |
| 2842 native.NativeBehavior nativeBehavior = elements.getNativeData(node); | 2851 native.NativeBehavior nativeBehavior = elements.getNativeData(node); |
| 2843 assert(invariant(node, nativeBehavior != null, | 2852 assert( |
| 2844 message: "No NativeBehavior for $node")); | 2853 nativeBehavior != null, failedAt(node, "No NativeBehavior for $node")); |
| 2845 | 2854 |
| 2846 TypeMask ssaType = | 2855 TypeMask ssaType = |
| 2847 TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld); | 2856 TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld); |
| 2848 | 2857 |
| 2849 push(new HForeignCode(template, ssaType, compiledArguments, | 2858 push(new HForeignCode(template, ssaType, compiledArguments, |
| 2850 nativeBehavior: nativeBehavior)); | 2859 nativeBehavior: nativeBehavior)); |
| 2851 } | 2860 } |
| 2852 | 2861 |
| 2853 void handleForeignJsEmbeddedGlobal(ast.Send node) { | 2862 void handleForeignJsEmbeddedGlobal(ast.Send node) { |
| 2854 List<ast.Node> arguments = node.arguments.toList(); | 2863 List<ast.Node> arguments = node.arguments.toList(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2879 'to JS_EMBEDDED_GLOBAL.' | 2888 'to JS_EMBEDDED_GLOBAL.' |
| 2880 }); | 2889 }); |
| 2881 return; | 2890 return; |
| 2882 } | 2891 } |
| 2883 HConstant hConstant = globalNameHNode; | 2892 HConstant hConstant = globalNameHNode; |
| 2884 StringConstantValue constant = hConstant.constant; | 2893 StringConstantValue constant = hConstant.constant; |
| 2885 String globalName = constant.primitiveValue; | 2894 String globalName = constant.primitiveValue; |
| 2886 js.Template expr = js.js.expressionTemplateYielding( | 2895 js.Template expr = js.js.expressionTemplateYielding( |
| 2887 emitter.generateEmbeddedGlobalAccess(globalName)); | 2896 emitter.generateEmbeddedGlobalAccess(globalName)); |
| 2888 native.NativeBehavior nativeBehavior = elements.getNativeData(node); | 2897 native.NativeBehavior nativeBehavior = elements.getNativeData(node); |
| 2889 assert(invariant(node, nativeBehavior != null, | 2898 assert( |
| 2890 message: "No NativeBehavior for $node")); | 2899 nativeBehavior != null, failedAt(node, "No NativeBehavior for $node")); |
| 2891 TypeMask ssaType = | 2900 TypeMask ssaType = |
| 2892 TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld); | 2901 TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld); |
| 2893 push(new HForeignCode(expr, ssaType, const [], | 2902 push(new HForeignCode(expr, ssaType, const [], |
| 2894 nativeBehavior: nativeBehavior)); | 2903 nativeBehavior: nativeBehavior)); |
| 2895 } | 2904 } |
| 2896 | 2905 |
| 2897 void handleJsInterceptorConstant(ast.Send node) { | 2906 void handleJsInterceptorConstant(ast.Send node) { |
| 2898 // Single argument must be a TypeConstant which is converted into a | 2907 // Single argument must be a TypeConstant which is converted into a |
| 2899 // InterceptorConstant. | 2908 // InterceptorConstant. |
| 2900 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { | 2909 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3033 } else if (name == 'JS_STRING_CONCAT') { | 3042 } else if (name == 'JS_STRING_CONCAT') { |
| 3034 handleJsStringConcat(node); | 3043 handleJsStringConcat(node); |
| 3035 } else { | 3044 } else { |
| 3036 reporter.internalError(node, "Unknown foreign: ${element}"); | 3045 reporter.internalError(node, "Unknown foreign: ${element}"); |
| 3037 } | 3046 } |
| 3038 } | 3047 } |
| 3039 | 3048 |
| 3040 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader, | 3049 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader, |
| 3041 SourceInformation sourceInformation) { | 3050 SourceInformation sourceInformation) { |
| 3042 // Until now we only handle these as getters. | 3051 // Until now we only handle these as getters. |
| 3043 invariant(node, deferredLoader.isDeferredLoaderGetter); | 3052 if (!deferredLoader.isDeferredLoaderGetter) { |
| 3053 failedAt(node); |
| 3054 } |
| 3044 FunctionEntity loadFunction = commonElements.loadLibraryWrapper; | 3055 FunctionEntity loadFunction = commonElements.loadLibraryWrapper; |
| 3045 PrefixElement prefixElement = deferredLoader.enclosingElement; | 3056 PrefixElement prefixElement = deferredLoader.enclosingElement; |
| 3046 String loadId = deferredLoadTask.getImportDeferName(node, prefixElement); | 3057 String loadId = deferredLoadTask.getImportDeferName(node, prefixElement); |
| 3047 var inputs = [graph.addConstantString(loadId, closedWorld)]; | 3058 var inputs = [graph.addConstantString(loadId, closedWorld)]; |
| 3048 push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType, | 3059 push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType, |
| 3049 targetCanThrow: false) | 3060 targetCanThrow: false) |
| 3050 ..sourceInformation = sourceInformation); | 3061 ..sourceInformation = sourceInformation); |
| 3051 } | 3062 } |
| 3052 | 3063 |
| 3053 generateSuperNoSuchMethodSend( | 3064 generateSuperNoSuchMethodSend( |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3108 push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs)); | 3119 push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs)); |
| 3109 } | 3120 } |
| 3110 | 3121 |
| 3111 /// Generate a call to a super method or constructor. | 3122 /// Generate a call to a super method or constructor. |
| 3112 void generateSuperInvoke(ast.Send node, MethodElement method, | 3123 void generateSuperInvoke(ast.Send node, MethodElement method, |
| 3113 SourceInformation sourceInformation) { | 3124 SourceInformation sourceInformation) { |
| 3114 // TODO(5347): Try to avoid the need for calling [implementation] before | 3125 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 3115 // calling [makeStaticArgumentList]. | 3126 // calling [makeStaticArgumentList]. |
| 3116 Selector selector = elements.getSelector(node); | 3127 Selector selector = elements.getSelector(node); |
| 3117 MethodElement implementation = method.implementation; | 3128 MethodElement implementation = method.implementation; |
| 3118 assert(invariant(node, selector.applies(implementation), | 3129 assert(selector.applies(implementation), |
| 3119 message: "$selector does not apply to ${implementation}")); | 3130 failedAt(node, "$selector does not apply to ${implementation}")); |
| 3120 List<HInstruction> inputs = | 3131 List<HInstruction> inputs = |
| 3121 makeStaticArgumentList(selector.callStructure, node.arguments, method); | 3132 makeStaticArgumentList(selector.callStructure, node.arguments, method); |
| 3122 push(buildInvokeSuper(selector, method, inputs, sourceInformation)); | 3133 push(buildInvokeSuper(selector, method, inputs, sourceInformation)); |
| 3123 } | 3134 } |
| 3124 | 3135 |
| 3125 /// Access the value from the super [element]. | 3136 /// Access the value from the super [element]. |
| 3126 void handleSuperGet(ast.Send node, Element element) { | 3137 void handleSuperGet(ast.Send node, Element element) { |
| 3127 Selector selector = elements.getSelector(node); | 3138 Selector selector = elements.getSelector(node); |
| 3128 SourceInformation sourceInformation = | 3139 SourceInformation sourceInformation = |
| 3129 sourceInformationBuilder.buildGet(node); | 3140 sourceInformationBuilder.buildGet(node); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3308 // Set the runtime type information on the object. | 3319 // Set the runtime type information on the object. |
| 3309 MethodElement typeInfoSetterElement = commonElements.setRuntimeTypeInfo; | 3320 MethodElement typeInfoSetterElement = commonElements.setRuntimeTypeInfo; |
| 3310 pushInvokeStatic( | 3321 pushInvokeStatic( |
| 3311 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], | 3322 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], |
| 3312 typeMask: commonMasks.dynamicType, | 3323 typeMask: commonMasks.dynamicType, |
| 3313 sourceInformation: newObject.sourceInformation); | 3324 sourceInformation: newObject.sourceInformation); |
| 3314 | 3325 |
| 3315 // The new object will now be referenced through the | 3326 // The new object will now be referenced through the |
| 3316 // `setRuntimeTypeInfo` call. We therefore set the type of that | 3327 // `setRuntimeTypeInfo` call. We therefore set the type of that |
| 3317 // instruction to be of the object's type. | 3328 // instruction to be of the object's type. |
| 3318 assert(invariant(CURRENT_ELEMENT_SPANNABLE, | 3329 assert( |
| 3319 stack.last is HInvokeStatic || stack.last == newObject, | 3330 stack.last is HInvokeStatic || stack.last == newObject, |
| 3320 message: "Unexpected `stack.last`: Found ${stack.last}, " | 3331 failedAt( |
| 3332 CURRENT_ELEMENT_SPANNABLE, |
| 3333 "Unexpected `stack.last`: Found ${stack.last}, " |
| 3321 "expected ${newObject} or an HInvokeStatic. " | 3334 "expected ${newObject} or an HInvokeStatic. " |
| 3322 "State: typeInfo=$typeInfo, stack=$stack.")); | 3335 "State: typeInfo=$typeInfo, stack=$stack.")); |
| 3323 stack.last.instructionType = newObject.instructionType; | 3336 stack.last.instructionType = newObject.instructionType; |
| 3324 return pop(); | 3337 return pop(); |
| 3325 } | 3338 } |
| 3326 | 3339 |
| 3327 void handleNewSend(ast.NewExpression node) { | 3340 void handleNewSend(ast.NewExpression node) { |
| 3328 ast.Send send = node.send; | 3341 ast.Send send = node.send; |
| 3329 generateIsDeferredLoadedCheckOfSend(send); | 3342 generateIsDeferredLoadedCheckOfSend(send); |
| 3330 | 3343 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3378 ConstructorElement constructorImplementation = constructor.implementation; | 3391 ConstructorElement constructorImplementation = constructor.implementation; |
| 3379 constructor = constructorImplementation.effectiveTarget; | 3392 constructor = constructorImplementation.effectiveTarget; |
| 3380 | 3393 |
| 3381 final bool isSymbolConstructor = | 3394 final bool isSymbolConstructor = |
| 3382 closedWorld.commonElements.isSymbolConstructor(constructorDeclaration); | 3395 closedWorld.commonElements.isSymbolConstructor(constructorDeclaration); |
| 3383 final bool isJSArrayTypedConstructor = constructorDeclaration == | 3396 final bool isJSArrayTypedConstructor = constructorDeclaration == |
| 3384 closedWorld.commonElements.jsArrayTypedConstructor; | 3397 closedWorld.commonElements.jsArrayTypedConstructor; |
| 3385 | 3398 |
| 3386 if (isSymbolConstructor) { | 3399 if (isSymbolConstructor) { |
| 3387 constructor = commonElements.symbolValidatedConstructor; | 3400 constructor = commonElements.symbolValidatedConstructor; |
| 3388 assert(invariant(send, constructor != null, | 3401 assert(constructor != null, |
| 3389 message: 'Constructor Symbol.validated is missing')); | 3402 failedAt(send, 'Constructor Symbol.validated is missing')); |
| 3390 callStructure = | 3403 callStructure = |
| 3391 commonElements.symbolValidatedConstructorSelector.callStructure; | 3404 commonElements.symbolValidatedConstructorSelector.callStructure; |
| 3392 assert(invariant(send, callStructure != null, | 3405 assert(callStructure != null, |
| 3393 message: 'Constructor Symbol.validated is missing')); | 3406 failedAt(send, 'Constructor Symbol.validated is missing')); |
| 3394 } | 3407 } |
| 3395 | 3408 |
| 3396 bool isRedirected = constructorDeclaration.isRedirectingFactory; | 3409 bool isRedirected = constructorDeclaration.isRedirectingFactory; |
| 3397 if (!constructorDeclaration.isCyclicRedirection) { | 3410 if (!constructorDeclaration.isCyclicRedirection) { |
| 3398 // Insert a check for every deferred redirection on the path to the | 3411 // Insert a check for every deferred redirection on the path to the |
| 3399 // final target. | 3412 // final target. |
| 3400 ConstructorElement target = constructorDeclaration; | 3413 ConstructorElement target = constructorDeclaration; |
| 3401 while (target.isRedirectingFactory) { | 3414 while (target.isRedirectingFactory) { |
| 3402 if (constructorDeclaration.redirectionDeferredPrefix != null) { | 3415 if (constructorDeclaration.redirectionDeferredPrefix != null) { |
| 3403 generateIsDeferredLoadedCheckIfNeeded( | 3416 generateIsDeferredLoadedCheckIfNeeded( |
| (...skipping 2654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6058 // to create the phis in [joinBlock]. | 6071 // to create the phis in [joinBlock]. |
| 6059 // If we never jump to the join block, [caseHandlers] will stay empty, and | 6072 // If we never jump to the join block, [caseHandlers] will stay empty, and |
| 6060 // the join block is never added to the graph. | 6073 // the join block is never added to the graph. |
| 6061 HBasicBlock joinBlock = new HBasicBlock(); | 6074 HBasicBlock joinBlock = new HBasicBlock(); |
| 6062 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; | 6075 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; |
| 6063 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { | 6076 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { |
| 6064 instruction.block.addSuccessor(joinBlock); | 6077 instruction.block.addSuccessor(joinBlock); |
| 6065 caseHandlers.add(locals); | 6078 caseHandlers.add(locals); |
| 6066 }); | 6079 }); |
| 6067 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 6080 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
| 6068 assert(invariant(errorNode, false, | 6081 assert(false, failedAt(errorNode, 'Continue cannot target a switch.')); |
| 6069 message: 'Continue cannot target a switch.')); | |
| 6070 }); | 6082 }); |
| 6071 if (!isAborted()) { | 6083 if (!isAborted()) { |
| 6072 current.close(new HGoto()); | 6084 current.close(new HGoto()); |
| 6073 lastOpenedBlock.addSuccessor(joinBlock); | 6085 lastOpenedBlock.addSuccessor(joinBlock); |
| 6074 caseHandlers.add(localsHandler); | 6086 caseHandlers.add(localsHandler); |
| 6075 } | 6087 } |
| 6076 if (!hasDefault) { | 6088 if (!hasDefault) { |
| 6077 // Always create a default case, to avoid a critical edge in the | 6089 // Always create a default case, to avoid a critical edge in the |
| 6078 // graph. | 6090 // graph. |
| 6079 HBasicBlock defaultCase = addNewBlock(); | 6091 HBasicBlock defaultCase = addNewBlock(); |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6812 this.oldReturnLocal, | 6824 this.oldReturnLocal, |
| 6813 this.oldReturnType, | 6825 this.oldReturnType, |
| 6814 this.oldResolvedAst, | 6826 this.oldResolvedAst, |
| 6815 this.oldStack, | 6827 this.oldStack, |
| 6816 this.oldLocalsHandler, | 6828 this.oldLocalsHandler, |
| 6817 this.inTryStatement, | 6829 this.inTryStatement, |
| 6818 this.allFunctionsCalledOnce, | 6830 this.allFunctionsCalledOnce, |
| 6819 this.oldElementInferenceResults) | 6831 this.oldElementInferenceResults) |
| 6820 : super(function); | 6832 : super(function); |
| 6821 } | 6833 } |
| OLD | NEW |