| 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 final SsaCodeGeneratorTask generator; | 8 final SsaCodeGeneratorTask generator; |
| 9 final SsaBuilderTask builder; | 9 final SsaBuilderTask builder; |
| 10 final SsaOptimizerTask optimizer; | 10 final SsaOptimizerTask optimizer; |
| (...skipping 1673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1684 }, | 1684 }, |
| 1685 visitElse: null, | 1685 visitElse: null, |
| 1686 sourceInformation: sourceInformationBuilder.buildIf(function.body)); | 1686 sourceInformation: sourceInformationBuilder.buildIf(function.body)); |
| 1687 } | 1687 } |
| 1688 } | 1688 } |
| 1689 if (const bool.fromEnvironment('unreachable-throw') == true) { | 1689 if (const bool.fromEnvironment('unreachable-throw') == true) { |
| 1690 var emptyParameters = parameters.values.where((p) => | 1690 var emptyParameters = parameters.values.where((p) => |
| 1691 p.instructionType.isEmpty && !p.instructionType.isNullable); | 1691 p.instructionType.isEmpty && !p.instructionType.isNullable); |
| 1692 if (emptyParameters.length > 0) { | 1692 if (emptyParameters.length > 0) { |
| 1693 addComment('${emptyParameters} inferred as [empty]'); | 1693 addComment('${emptyParameters} inferred as [empty]'); |
| 1694 pushInvokeStatic(function.body, backend.assertUnreachableMethod, []); | 1694 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); |
| 1695 pop(); | 1695 pop(); |
| 1696 return closeFunction(); | 1696 return closeFunction(); |
| 1697 } | 1697 } |
| 1698 } | 1698 } |
| 1699 function.body.accept(this); | 1699 function.body.accept(this); |
| 1700 return closeFunction(); | 1700 return closeFunction(); |
| 1701 } | 1701 } |
| 1702 | 1702 |
| 1703 /// Adds a JavaScript comment to the output. The comment will be omitted in | 1703 /// Adds a JavaScript comment to the output. The comment will be omitted in |
| 1704 /// minified mode. Each line in [text] is preceded with `//` and indented. | 1704 /// minified mode. Each line in [text] is preceded with `//` and indented. |
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2554 original, typeVariable); | 2554 original, typeVariable); |
| 2555 } else if (type.isFunctionType) { | 2555 } else if (type.isFunctionType) { |
| 2556 String name = kind == HTypeConversion.CAST_TYPE_CHECK | 2556 String name = kind == HTypeConversion.CAST_TYPE_CHECK |
| 2557 ? '_asCheck' : '_assertCheck'; | 2557 ? '_asCheck' : '_assertCheck'; |
| 2558 | 2558 |
| 2559 List<HInstruction> arguments = | 2559 List<HInstruction> arguments = |
| 2560 <HInstruction>[buildFunctionType(type), original]; | 2560 <HInstruction>[buildFunctionType(type), original]; |
| 2561 pushInvokeDynamic( | 2561 pushInvokeDynamic( |
| 2562 null, | 2562 null, |
| 2563 new Selector.call( | 2563 new Selector.call( |
| 2564 new Name(name, backend.jsHelperLibrary), CallStructure.ONE_ARG), | 2564 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG), |
| 2565 null, | 2565 null, |
| 2566 arguments); | 2566 arguments); |
| 2567 | 2567 |
| 2568 return new HTypeConversion(type, kind, original.instructionType, pop()); | 2568 return new HTypeConversion(type, kind, original.instructionType, pop()); |
| 2569 } else { | 2569 } else { |
| 2570 return original.convertType(compiler, type, kind); | 2570 return original.convertType(compiler, type, kind); |
| 2571 } | 2571 } |
| 2572 } | 2572 } |
| 2573 | 2573 |
| 2574 HInstruction _trustType(HInstruction original, DartType type) { | 2574 HInstruction _trustType(HInstruction original, DartType type) { |
| (...skipping 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3868 | 3868 |
| 3869 HInstruction buildIsNode(ast.Node node, | 3869 HInstruction buildIsNode(ast.Node node, |
| 3870 DartType type, | 3870 DartType type, |
| 3871 HInstruction expression) { | 3871 HInstruction expression) { |
| 3872 type = localsHandler.substInContext(type).unaliased; | 3872 type = localsHandler.substInContext(type).unaliased; |
| 3873 if (type.isFunctionType) { | 3873 if (type.isFunctionType) { |
| 3874 List arguments = [buildFunctionType(type), expression]; | 3874 List arguments = [buildFunctionType(type), expression]; |
| 3875 pushInvokeDynamic( | 3875 pushInvokeDynamic( |
| 3876 node, | 3876 node, |
| 3877 new Selector.call( | 3877 new Selector.call( |
| 3878 new PrivateName('_isTest', backend.jsHelperLibrary), | 3878 new PrivateName('_isTest', helpers.jsHelperLibrary), |
| 3879 CallStructure.ONE_ARG), | 3879 CallStructure.ONE_ARG), |
| 3880 null, | 3880 null, |
| 3881 arguments); | 3881 arguments); |
| 3882 return new HIs.compound(type, expression, pop(), backend.boolType); | 3882 return new HIs.compound(type, expression, pop(), backend.boolType); |
| 3883 } else if (type.isTypeVariable) { | 3883 } else if (type.isTypeVariable) { |
| 3884 HInstruction runtimeType = addTypeVariableReference(type); | 3884 HInstruction runtimeType = addTypeVariableReference(type); |
| 3885 Element helper = helpers.checkSubtypeOfRuntimeType; | 3885 Element helper = helpers.checkSubtypeOfRuntimeType; |
| 3886 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3886 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 3887 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 3887 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); |
| 3888 HInstruction call = pop(); | 3888 HInstruction call = pop(); |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4195 // If the isolate library is not used, we just generate code | 4195 // If the isolate library is not used, we just generate code |
| 4196 // to fetch the static state. | 4196 // to fetch the static state. |
| 4197 String name = backend.namer.staticStateHolder; | 4197 String name = backend.namer.staticStateHolder; |
| 4198 push(new HForeignCode(js.js.parseForeignJS(name), | 4198 push(new HForeignCode(js.js.parseForeignJS(name), |
| 4199 backend.dynamicType, | 4199 backend.dynamicType, |
| 4200 <HInstruction>[])); | 4200 <HInstruction>[])); |
| 4201 } else { | 4201 } else { |
| 4202 // Call a helper method from the isolate library. The isolate | 4202 // Call a helper method from the isolate library. The isolate |
| 4203 // library uses its own isolate structure, that encapsulates | 4203 // library uses its own isolate structure, that encapsulates |
| 4204 // Leg's isolate. | 4204 // Leg's isolate. |
| 4205 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); | 4205 Element element = helpers.currentIsolate; |
| 4206 if (element == null) { | 4206 if (element == null) { |
| 4207 reporter.internalError(node, | 4207 reporter.internalError(node, |
| 4208 'Isolate library and compiler mismatch.'); | 4208 'Isolate library and compiler mismatch.'); |
| 4209 } | 4209 } |
| 4210 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); | 4210 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 4211 } | 4211 } |
| 4212 } | 4212 } |
| 4213 | 4213 |
| 4214 void handleForeignJsGetFlag(ast.Send node) { | 4214 void handleForeignJsGetFlag(ast.Send node) { |
| 4215 List<ast.Node> arguments = node.arguments.toList(); | 4215 List<ast.Node> arguments = node.arguments.toList(); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4270 for (int i = 1; i < arguments.length; i++) { | 4270 for (int i = 1; i < arguments.length; i++) { |
| 4271 reporter.reportErrorMessage( | 4271 reporter.reportErrorMessage( |
| 4272 arguments[i], MessageKind.GENERIC, | 4272 arguments[i], MessageKind.GENERIC, |
| 4273 {'text': 'Error: Extra argument to JS_GET_NAME.'}); | 4273 {'text': 'Error: Extra argument to JS_GET_NAME.'}); |
| 4274 } | 4274 } |
| 4275 return; | 4275 return; |
| 4276 } | 4276 } |
| 4277 Element element = elements[argument]; | 4277 Element element = elements[argument]; |
| 4278 if (element == null || | 4278 if (element == null || |
| 4279 element is! FieldElement || | 4279 element is! FieldElement || |
| 4280 element.enclosingClass != backend.jsGetNameEnum) { | 4280 element.enclosingClass != helpers.jsGetNameEnum) { |
| 4281 reporter.reportErrorMessage( | 4281 reporter.reportErrorMessage( |
| 4282 argument, MessageKind.GENERIC, | 4282 argument, MessageKind.GENERIC, |
| 4283 {'text': 'Error: Expected a JsGetName enum value.'}); | 4283 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 4284 } | 4284 } |
| 4285 EnumClassElement enumClass = element.enclosingClass; | 4285 EnumClassElement enumClass = element.enclosingClass; |
| 4286 int index = enumClass.enumValues.indexOf(element); | 4286 int index = enumClass.enumValues.indexOf(element); |
| 4287 stack.add( | 4287 stack.add( |
| 4288 addConstantStringFromName( | 4288 addConstantStringFromName( |
| 4289 backend.namer.getNameForJsGetName( | 4289 backend.namer.getNameForJsGetName( |
| 4290 argument, JsGetName.values[index]))); | 4290 argument, JsGetName.values[index]))); |
| 4291 } | 4291 } |
| 4292 | 4292 |
| 4293 void handleForeignJsBuiltin(ast.Send node) { | 4293 void handleForeignJsBuiltin(ast.Send node) { |
| 4294 List<ast.Node> arguments = node.arguments.toList(); | 4294 List<ast.Node> arguments = node.arguments.toList(); |
| 4295 ast.Node argument; | 4295 ast.Node argument; |
| 4296 if (arguments.length < 2) { | 4296 if (arguments.length < 2) { |
| 4297 reporter.reportErrorMessage( | 4297 reporter.reportErrorMessage( |
| 4298 node, MessageKind.GENERIC, | 4298 node, MessageKind.GENERIC, |
| 4299 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); | 4299 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); |
| 4300 } | 4300 } |
| 4301 | 4301 |
| 4302 Element builtinElement = elements[arguments[1]]; | 4302 Element builtinElement = elements[arguments[1]]; |
| 4303 if (builtinElement == null || | 4303 if (builtinElement == null || |
| 4304 (builtinElement is! FieldElement) || | 4304 (builtinElement is! FieldElement) || |
| 4305 builtinElement.enclosingClass != backend.jsBuiltinEnum) { | 4305 builtinElement.enclosingClass != helpers.jsBuiltinEnum) { |
| 4306 reporter.reportErrorMessage( | 4306 reporter.reportErrorMessage( |
| 4307 argument, MessageKind.GENERIC, | 4307 argument, MessageKind.GENERIC, |
| 4308 {'text': 'Error: Expected a JsBuiltin enum value.'}); | 4308 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 4309 } | 4309 } |
| 4310 EnumClassElement enumClass = builtinElement.enclosingClass; | 4310 EnumClassElement enumClass = builtinElement.enclosingClass; |
| 4311 int index = enumClass.enumValues.indexOf(builtinElement); | 4311 int index = enumClass.enumValues.indexOf(builtinElement); |
| 4312 | 4312 |
| 4313 js.Template template = | 4313 js.Template template = |
| 4314 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); | 4314 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); |
| 4315 | 4315 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4404 Link<ast.Node> link = node.arguments; | 4404 Link<ast.Node> link = node.arguments; |
| 4405 if (!compiler.hasIsolateSupport) { | 4405 if (!compiler.hasIsolateSupport) { |
| 4406 // If the isolate library is not used, we just invoke the | 4406 // If the isolate library is not used, we just invoke the |
| 4407 // closure. | 4407 // closure. |
| 4408 visit(link.tail.head); | 4408 visit(link.tail.head); |
| 4409 push(new HInvokeClosure(new Selector.callClosure(0), | 4409 push(new HInvokeClosure(new Selector.callClosure(0), |
| 4410 <HInstruction>[pop()], | 4410 <HInstruction>[pop()], |
| 4411 backend.dynamicType)); | 4411 backend.dynamicType)); |
| 4412 } else { | 4412 } else { |
| 4413 // Call a helper method from the isolate library. | 4413 // Call a helper method from the isolate library. |
| 4414 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); | 4414 Element element = helpers.callInIsolate; |
| 4415 if (element == null) { | 4415 if (element == null) { |
| 4416 reporter.internalError(node, | 4416 reporter.internalError(node, |
| 4417 'Isolate library and compiler mismatch.'); | 4417 'Isolate library and compiler mismatch.'); |
| 4418 } | 4418 } |
| 4419 List<HInstruction> inputs = <HInstruction>[]; | 4419 List<HInstruction> inputs = <HInstruction>[]; |
| 4420 addGenericSendArgumentsToList(link, inputs); | 4420 addGenericSendArgumentsToList(link, inputs); |
| 4421 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); | 4421 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); |
| 4422 } | 4422 } |
| 4423 } | 4423 } |
| 4424 | 4424 |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5081 | 5081 |
| 5082 Element constructor = elements[send]; | 5082 Element constructor = elements[send]; |
| 5083 CallStructure callStructure = elements.getSelector(send).callStructure; | 5083 CallStructure callStructure = elements.getSelector(send).callStructure; |
| 5084 ConstructorElement constructorDeclaration = constructor; | 5084 ConstructorElement constructorDeclaration = constructor; |
| 5085 ConstructorElement constructorImplementation = constructor.implementation; | 5085 ConstructorElement constructorImplementation = constructor.implementation; |
| 5086 constructor = constructorImplementation.effectiveTarget; | 5086 constructor = constructorImplementation.effectiveTarget; |
| 5087 | 5087 |
| 5088 final bool isSymbolConstructor = | 5088 final bool isSymbolConstructor = |
| 5089 constructorDeclaration == compiler.symbolConstructor; | 5089 constructorDeclaration == compiler.symbolConstructor; |
| 5090 final bool isJSArrayTypedConstructor = | 5090 final bool isJSArrayTypedConstructor = |
| 5091 constructorDeclaration == backend.jsArrayTypedConstructor; | 5091 constructorDeclaration == helpers.jsArrayTypedConstructor; |
| 5092 | 5092 |
| 5093 if (isSymbolConstructor) { | 5093 if (isSymbolConstructor) { |
| 5094 constructor = compiler.symbolValidatedConstructor; | 5094 constructor = compiler.symbolValidatedConstructor; |
| 5095 assert(invariant(send, constructor != null, | 5095 assert(invariant(send, constructor != null, |
| 5096 message: 'Constructor Symbol.validated is missing')); | 5096 message: 'Constructor Symbol.validated is missing')); |
| 5097 callStructure = compiler.symbolValidatedConstructorSelector.callStructure; | 5097 callStructure = compiler.symbolValidatedConstructorSelector.callStructure; |
| 5098 assert(invariant(send, callStructure != null, | 5098 assert(invariant(send, callStructure != null, |
| 5099 message: 'Constructor Symbol.validated is missing')); | 5099 message: 'Constructor Symbol.validated is missing')); |
| 5100 } | 5100 } |
| 5101 | 5101 |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5775 // We prefer to not inline certain operations on indexables, | 5775 // We prefer to not inline certain operations on indexables, |
| 5776 // because the constant folder will handle them better and turn | 5776 // because the constant folder will handle them better and turn |
| 5777 // them into simpler instructions that allow further | 5777 // them into simpler instructions that allow further |
| 5778 // optimizations. | 5778 // optimizations. |
| 5779 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 5779 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
| 5780 bool isLength = selector.isGetter | 5780 bool isLength = selector.isGetter |
| 5781 && selector.name == "length"; | 5781 && selector.name == "length"; |
| 5782 if (isLength || selector.isIndex) { | 5782 if (isLength || selector.isIndex) { |
| 5783 return compiler.world.isSubtypeOf( | 5783 return compiler.world.isSubtypeOf( |
| 5784 element.enclosingClass.declaration, | 5784 element.enclosingClass.declaration, |
| 5785 backend.jsIndexableClass); | 5785 helpers.jsIndexableClass); |
| 5786 } else if (selector.isIndexSet) { | 5786 } else if (selector.isIndexSet) { |
| 5787 return compiler.world.isSubtypeOf( | 5787 return compiler.world.isSubtypeOf( |
| 5788 element.enclosingClass.declaration, | 5788 element.enclosingClass.declaration, |
| 5789 backend.jsMutableIndexableClass); | 5789 helpers.jsMutableIndexableClass); |
| 5790 } else { | 5790 } else { |
| 5791 return false; | 5791 return false; |
| 5792 } | 5792 } |
| 5793 } | 5793 } |
| 5794 | 5794 |
| 5795 bool isOptimizableOperation(Selector selector, Element element) { | 5795 bool isOptimizableOperation(Selector selector, Element element) { |
| 5796 ClassElement cls = element.enclosingClass; | 5796 ClassElement cls = element.enclosingClass; |
| 5797 if (isOptimizableOperationOnIndexable(selector, element)) return true; | 5797 if (isOptimizableOperationOnIndexable(selector, element)) return true; |
| 5798 if (!backend.interceptedClasses.contains(cls)) return false; | 5798 if (!backend.interceptedClasses.contains(cls)) return false; |
| 5799 if (selector.isOperator) return true; | 5799 if (selector.isOperator) return true; |
| 5800 if (selector.isSetter) return true; | 5800 if (selector.isSetter) return true; |
| 5801 if (selector.isIndex) return true; | 5801 if (selector.isIndex) return true; |
| 5802 if (selector.isIndexSet) return true; | 5802 if (selector.isIndexSet) return true; |
| 5803 if (element == backend.jsArrayAdd | 5803 if (element == helpers.jsArrayAdd || |
| 5804 || element == backend.jsArrayRemoveLast | 5804 element == helpers.jsArrayRemoveLast || |
| 5805 || element == backend.jsStringSplit) { | 5805 element == helpers.jsStringSplit) { |
| 5806 return true; | 5806 return true; |
| 5807 } | 5807 } |
| 5808 return false; | 5808 return false; |
| 5809 } | 5809 } |
| 5810 | 5810 |
| 5811 Element element = compiler.world.locateSingleElement(selector, mask); | 5811 Element element = compiler.world.locateSingleElement(selector, mask); |
| 5812 if (element != null && | 5812 if (element != null && |
| 5813 !element.isField && | 5813 !element.isField && |
| 5814 !(element.isGetter && selector.isCall) && | 5814 !(element.isGetter && selector.isCall) && |
| 5815 !(element.isFunction && selector.isGetter) && | 5815 !(element.isFunction && selector.isGetter) && |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5915 if (element.isConstructor) { | 5915 if (element.isConstructor) { |
| 5916 codeTemplate = js.js.parseForeignJS("new #(${argsStub.join(",")})"); | 5916 codeTemplate = js.js.parseForeignJS("new #(${argsStub.join(",")})"); |
| 5917 } else { | 5917 } else { |
| 5918 codeTemplate = js.js.parseForeignJS("#(${argsStub.join(",")})"); | 5918 codeTemplate = js.js.parseForeignJS("#(${argsStub.join(",")})"); |
| 5919 } | 5919 } |
| 5920 } | 5920 } |
| 5921 | 5921 |
| 5922 var nativeBehavior = new native.NativeBehavior() | 5922 var nativeBehavior = new native.NativeBehavior() |
| 5923 ..codeTemplate = codeTemplate | 5923 ..codeTemplate = codeTemplate |
| 5924 ..typesReturned.add( | 5924 ..typesReturned.add( |
| 5925 backend.jsJavaScriptObjectClass.thisType) | 5925 helpers.jsJavaScriptObjectClass.thisType) |
| 5926 ..typesInstantiated.add( | 5926 ..typesInstantiated.add( |
| 5927 backend.jsJavaScriptObjectClass.thisType) | 5927 helpers.jsJavaScriptObjectClass.thisType) |
| 5928 ..sideEffects.setAllSideEffects(); | 5928 ..sideEffects.setAllSideEffects(); |
| 5929 return new HForeignCode( | 5929 return new HForeignCode( |
| 5930 codeTemplate, | 5930 codeTemplate, |
| 5931 backend.dynamicType, inputs, | 5931 backend.dynamicType, inputs, |
| 5932 nativeBehavior: nativeBehavior) | 5932 nativeBehavior: nativeBehavior) |
| 5933 ..sourceInformation = sourceInformation; | 5933 ..sourceInformation = sourceInformation; |
| 5934 } | 5934 } |
| 5935 | 5935 |
| 5936 void pushInvokeStatic(ast.Node location, | 5936 void pushInvokeStatic(ast.Node location, |
| 5937 Element element, | 5937 Element element, |
| (...skipping 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7434 // This scheme recognizes for-in on direct lists. It does not recognize all | 7434 // This scheme recognizes for-in on direct lists. It does not recognize all |
| 7435 // uses of ArrayIterator. They still occur when the receiver is an Iterable | 7435 // uses of ArrayIterator. They still occur when the receiver is an Iterable |
| 7436 // with a `get iterator` method that delegate to another Iterable and the | 7436 // with a `get iterator` method that delegate to another Iterable and the |
| 7437 // method is inlined. We would require full scalar replacement in that | 7437 // method is inlined. We would require full scalar replacement in that |
| 7438 // case. | 7438 // case. |
| 7439 | 7439 |
| 7440 Selector selector = elements.getIteratorSelector(node); | 7440 Selector selector = elements.getIteratorSelector(node); |
| 7441 TypeMask mask = elements.getIteratorTypeMask(node); | 7441 TypeMask mask = elements.getIteratorTypeMask(node); |
| 7442 | 7442 |
| 7443 ClassWorld classWorld = compiler.world; | 7443 ClassWorld classWorld = compiler.world; |
| 7444 if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) { | 7444 if (mask != null && mask.satisfies(helpers.jsIndexableClass, classWorld)) { |
| 7445 return buildSyncForInIndexable(node, mask); | 7445 return buildSyncForInIndexable(node, mask); |
| 7446 } | 7446 } |
| 7447 buildSyncForInIterator(node); | 7447 buildSyncForInIterator(node); |
| 7448 } | 7448 } |
| 7449 | 7449 |
| 7450 buildSyncForInIterator(ast.SyncForIn node) { | 7450 buildSyncForInIterator(ast.SyncForIn node) { |
| 7451 // Generate a structure equivalent to: | 7451 // Generate a structure equivalent to: |
| 7452 // Iterator<E> $iter = <iterable>.iterator; | 7452 // Iterator<E> $iter = <iterable>.iterator; |
| 7453 // while ($iter.moveNext()) { | 7453 // while ($iter.moveNext()) { |
| 7454 // <declaredIdentifier> = $iter.current; | 7454 // <declaredIdentifier> = $iter.current; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7521 Element loopVariable = elements.getForInVariable(node); | 7521 Element loopVariable = elements.getForInVariable(node); |
| 7522 SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable); | 7522 SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable); |
| 7523 TypeMask boolType = backend.boolType; | 7523 TypeMask boolType = backend.boolType; |
| 7524 | 7524 |
| 7525 // These variables are shared by initializer, condition, body and update. | 7525 // These variables are shared by initializer, condition, body and update. |
| 7526 HInstruction array; // Set in buildInitializer. | 7526 HInstruction array; // Set in buildInitializer. |
| 7527 bool isFixed; // Set in buildInitializer. | 7527 bool isFixed; // Set in buildInitializer. |
| 7528 HInstruction originalLength = null; // Set for growable lists. | 7528 HInstruction originalLength = null; // Set for growable lists. |
| 7529 | 7529 |
| 7530 HInstruction buildGetLength() { | 7530 HInstruction buildGetLength() { |
| 7531 Element lengthElement = backend.jsIndexableLength; | 7531 Element lengthElement = helpers.jsIndexableLength; |
| 7532 HFieldGet result = new HFieldGet( | 7532 HFieldGet result = new HFieldGet( |
| 7533 lengthElement, array, backend.positiveIntType, | 7533 lengthElement, array, backend.positiveIntType, |
| 7534 isAssignable: !isFixed); | 7534 isAssignable: !isFixed); |
| 7535 add(result); | 7535 add(result); |
| 7536 return result; | 7536 return result; |
| 7537 } | 7537 } |
| 7538 | 7538 |
| 7539 void buildConcurrentModificationErrorCheck() { | 7539 void buildConcurrentModificationErrorCheck() { |
| 7540 if (originalLength == null) return; | 7540 if (originalLength == null) return; |
| 7541 // The static call checkConcurrentModificationError() is expanded in | 7541 // The static call checkConcurrentModificationError() is expanded in |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7667 link = link.tail) { | 7667 link = link.tail) { |
| 7668 visit(link.head); | 7668 visit(link.head); |
| 7669 listInputs.add(pop()); | 7669 listInputs.add(pop()); |
| 7670 listInputs.add(pop()); | 7670 listInputs.add(pop()); |
| 7671 } | 7671 } |
| 7672 | 7672 |
| 7673 Element constructor; | 7673 Element constructor; |
| 7674 List<HInstruction> inputs = <HInstruction>[]; | 7674 List<HInstruction> inputs = <HInstruction>[]; |
| 7675 | 7675 |
| 7676 if (listInputs.isEmpty) { | 7676 if (listInputs.isEmpty) { |
| 7677 constructor = backend.mapLiteralConstructorEmpty; | 7677 constructor = helpers.mapLiteralConstructorEmpty; |
| 7678 } else { | 7678 } else { |
| 7679 constructor = backend.mapLiteralConstructor; | 7679 constructor = helpers.mapLiteralConstructor; |
| 7680 HLiteralList keyValuePairs = buildLiteralList(listInputs); | 7680 HLiteralList keyValuePairs = buildLiteralList(listInputs); |
| 7681 add(keyValuePairs); | 7681 add(keyValuePairs); |
| 7682 inputs.add(keyValuePairs); | 7682 inputs.add(keyValuePairs); |
| 7683 } | 7683 } |
| 7684 | 7684 |
| 7685 assert(constructor.isFactoryConstructor); | 7685 assert(constructor.isFactoryConstructor); |
| 7686 | 7686 |
| 7687 ConstructorElement functionElement = constructor; | 7687 ConstructorElement functionElement = constructor; |
| 7688 constructor = functionElement.effectiveTarget; | 7688 constructor = functionElement.effectiveTarget; |
| 7689 | 7689 |
| 7690 InterfaceType type = elements.getType(node); | 7690 InterfaceType type = elements.getType(node); |
| 7691 InterfaceType expectedType = | 7691 InterfaceType expectedType = |
| 7692 functionElement.computeEffectiveTargetType(type); | 7692 functionElement.computeEffectiveTargetType(type); |
| 7693 expectedType = localsHandler.substInContext(expectedType); | 7693 expectedType = localsHandler.substInContext(expectedType); |
| 7694 | 7694 |
| 7695 ClassElement cls = constructor.enclosingClass; | 7695 ClassElement cls = constructor.enclosingClass; |
| 7696 | 7696 |
| 7697 if (backend.classNeedsRti(cls)) { | 7697 if (backend.classNeedsRti(cls)) { |
| 7698 List<HInstruction> typeInputs = <HInstruction>[]; | 7698 List<HInstruction> typeInputs = <HInstruction>[]; |
| 7699 expectedType.typeArguments.forEach((DartType argument) { | 7699 expectedType.typeArguments.forEach((DartType argument) { |
| 7700 typeInputs.add(analyzeTypeArgument(argument)); | 7700 typeInputs.add(analyzeTypeArgument(argument)); |
| 7701 }); | 7701 }); |
| 7702 | 7702 |
| 7703 // We lift this common call pattern into a helper function to save space | 7703 // We lift this common call pattern into a helper function to save space |
| 7704 // in the output. | 7704 // in the output. |
| 7705 if (typeInputs.every((HInstruction input) => input.isNull())) { | 7705 if (typeInputs.every((HInstruction input) => input.isNull())) { |
| 7706 if (listInputs.isEmpty) { | 7706 if (listInputs.isEmpty) { |
| 7707 constructor = backend.mapLiteralUntypedEmptyMaker; | 7707 constructor = helpers.mapLiteralUntypedEmptyMaker; |
| 7708 } else { | 7708 } else { |
| 7709 constructor = backend.mapLiteralUntypedMaker; | 7709 constructor = helpers.mapLiteralUntypedMaker; |
| 7710 } | 7710 } |
| 7711 } else { | 7711 } else { |
| 7712 inputs.addAll(typeInputs); | 7712 inputs.addAll(typeInputs); |
| 7713 } | 7713 } |
| 7714 } | 7714 } |
| 7715 | 7715 |
| 7716 // If rti is needed and the map literal has no type parameters, | 7716 // If rti is needed and the map literal has no type parameters, |
| 7717 // 'constructor' is a static function that forwards the call to the factory | 7717 // 'constructor' is a static function that forwards the call to the factory |
| 7718 // constructor without type parameters. | 7718 // constructor without type parameters. |
| 7719 assert(constructor is ConstructorElement || constructor is FunctionElement); | 7719 assert(constructor is ConstructorElement || constructor is FunctionElement); |
| 7720 | 7720 |
| 7721 // The instruction type will always be a subtype of the mapLiteralClass, but | 7721 // The instruction type will always be a subtype of the mapLiteralClass, but |
| 7722 // type inference might discover a more specific type, or find nothing (in | 7722 // type inference might discover a more specific type, or find nothing (in |
| 7723 // dart2js unit tests). | 7723 // dart2js unit tests). |
| 7724 TypeMask mapType = | 7724 TypeMask mapType = |
| 7725 new TypeMask.nonNullSubtype(backend.mapLiteralClass, compiler.world); | 7725 new TypeMask.nonNullSubtype(helpers.mapLiteralClass, compiler.world); |
| 7726 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( | 7726 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( |
| 7727 constructor, compiler); | 7727 constructor, compiler); |
| 7728 TypeMask instructionType = | 7728 TypeMask instructionType = |
| 7729 mapType.intersection(returnTypeMask, compiler.world); | 7729 mapType.intersection(returnTypeMask, compiler.world); |
| 7730 | 7730 |
| 7731 addInlinedInstantiation(expectedType); | 7731 addInlinedInstantiation(expectedType); |
| 7732 pushInvokeStatic(node, constructor, inputs, | 7732 pushInvokeStatic(node, constructor, inputs, |
| 7733 typeMask: instructionType, instanceType: expectedType); | 7733 typeMask: instructionType, instanceType: expectedType); |
| 7734 removeInlinedInstantiation(expectedType); | 7734 removeInlinedInstantiation(expectedType); |
| 7735 } | 7735 } |
| (...skipping 1321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9057 } | 9057 } |
| 9058 | 9058 |
| 9059 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { | 9059 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { |
| 9060 final ClassWorld classWorld; | 9060 final ClassWorld classWorld; |
| 9061 | 9061 |
| 9062 TypeBuilder(this.classWorld); | 9062 TypeBuilder(this.classWorld); |
| 9063 | 9063 |
| 9064 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder); | 9064 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder); |
| 9065 | 9065 |
| 9066 void visitVoidType(VoidType type, SsaBuilder builder) { | 9066 void visitVoidType(VoidType type, SsaBuilder builder) { |
| 9067 ClassElement cls = builder.backend.findHelper('VoidRuntimeType'); | 9067 ClassElement cls = builder.backend.helpers.VoidRuntimeType; |
| 9068 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld))); | 9068 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld))); |
| 9069 } | 9069 } |
| 9070 | 9070 |
| 9071 void visitTypeVariableType(TypeVariableType type, | 9071 void visitTypeVariableType(TypeVariableType type, |
| 9072 SsaBuilder builder) { | 9072 SsaBuilder builder) { |
| 9073 ClassElement cls = builder.backend.findHelper('RuntimeType'); | 9073 ClassElement cls = builder.backend.helpers.RuntimeType; |
| 9074 TypeMask instructionType = new TypeMask.subclass(cls, classWorld); | 9074 TypeMask instructionType = new TypeMask.subclass(cls, classWorld); |
| 9075 if (!builder.sourceElement.enclosingElement.isClosure && | 9075 if (!builder.sourceElement.enclosingElement.isClosure && |
| 9076 builder.sourceElement.isInstanceMember) { | 9076 builder.sourceElement.isInstanceMember) { |
| 9077 HInstruction receiver = builder.localsHandler.readThis(); | 9077 HInstruction receiver = builder.localsHandler.readThis(); |
| 9078 builder.push(new HReadTypeVariable(type, receiver, instructionType)); | 9078 builder.push(new HReadTypeVariable(type, receiver, instructionType)); |
| 9079 } else { | 9079 } else { |
| 9080 builder.push( | 9080 builder.push( |
| 9081 new HReadTypeVariable.noReceiver( | 9081 new HReadTypeVariable.noReceiver( |
| 9082 type, builder.addTypeVariableReference(type), instructionType)); | 9082 type, builder.addTypeVariableReference(type), instructionType)); |
| 9083 } | 9083 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 9101 List<DartType> namedParameterTypes = type.namedParameterTypes; | 9101 List<DartType> namedParameterTypes = type.namedParameterTypes; |
| 9102 List<String> names = type.namedParameters; | 9102 List<String> names = type.namedParameters; |
| 9103 for (int index = 0; index < names.length; index++) { | 9103 for (int index = 0; index < names.length; index++) { |
| 9104 ast.DartString dartString = new ast.DartString.literal(names[index]); | 9104 ast.DartString dartString = new ast.DartString.literal(names[index]); |
| 9105 inputs.add( | 9105 inputs.add( |
| 9106 builder.graph.addConstantString(dartString, builder.compiler)); | 9106 builder.graph.addConstantString(dartString, builder.compiler)); |
| 9107 namedParameterTypes[index].accept(this, builder); | 9107 namedParameterTypes[index].accept(this, builder); |
| 9108 inputs.add(builder.pop()); | 9108 inputs.add(builder.pop()); |
| 9109 } | 9109 } |
| 9110 | 9110 |
| 9111 ClassElement cls = builder.backend.findHelper('RuntimeFunctionType'); | 9111 ClassElement cls = builder.backend.helpers.RuntimeFunctionType; |
| 9112 builder.push(new HFunctionType(inputs, type, | 9112 builder.push(new HFunctionType(inputs, type, |
| 9113 new TypeMask.exact(cls, classWorld))); | 9113 new TypeMask.exact(cls, classWorld))); |
| 9114 } | 9114 } |
| 9115 | 9115 |
| 9116 void visitMalformedType(MalformedType type, SsaBuilder builder) { | 9116 void visitMalformedType(MalformedType type, SsaBuilder builder) { |
| 9117 visitDynamicType(const DynamicType(), builder); | 9117 visitDynamicType(const DynamicType(), builder); |
| 9118 } | 9118 } |
| 9119 | 9119 |
| 9120 void visitStatementType(StatementType type, SsaBuilder builder) { | 9120 void visitStatementType(StatementType type, SsaBuilder builder) { |
| 9121 throw 'not implemented visitStatementType($type)'; | 9121 throw 'not implemented visitStatementType($type)'; |
| 9122 } | 9122 } |
| 9123 | 9123 |
| 9124 void visitInterfaceType(InterfaceType type, SsaBuilder builder) { | 9124 void visitInterfaceType(InterfaceType type, SsaBuilder builder) { |
| 9125 List<HInstruction> inputs = <HInstruction>[]; | 9125 List<HInstruction> inputs = <HInstruction>[]; |
| 9126 for (DartType typeArgument in type.typeArguments) { | 9126 for (DartType typeArgument in type.typeArguments) { |
| 9127 typeArgument.accept(this, builder); | 9127 typeArgument.accept(this, builder); |
| 9128 inputs.add(builder.pop()); | 9128 inputs.add(builder.pop()); |
| 9129 } | 9129 } |
| 9130 ClassElement cls; | 9130 ClassElement cls; |
| 9131 if (type.typeArguments.isEmpty) { | 9131 if (type.typeArguments.isEmpty) { |
| 9132 cls = builder.backend.findHelper('RuntimeTypePlain'); | 9132 cls = builder.backend.helpers.RuntimeTypePlain; |
| 9133 } else { | 9133 } else { |
| 9134 cls = builder.backend.findHelper('RuntimeTypeGeneric'); | 9134 cls = builder.backend.helpers.RuntimeTypeGeneric; |
| 9135 } | 9135 } |
| 9136 builder.push(new HInterfaceType(inputs, type, | 9136 builder.push(new HInterfaceType(inputs, type, |
| 9137 new TypeMask.exact(cls, classWorld))); | 9137 new TypeMask.exact(cls, classWorld))); |
| 9138 } | 9138 } |
| 9139 | 9139 |
| 9140 void visitTypedefType(TypedefType type, SsaBuilder builder) { | 9140 void visitTypedefType(TypedefType type, SsaBuilder builder) { |
| 9141 DartType unaliased = type.unaliased; | 9141 DartType unaliased = type.unaliased; |
| 9142 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 9142 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 9143 unaliased.accept(this, builder); | 9143 unaliased.accept(this, builder); |
| 9144 } | 9144 } |
| 9145 | 9145 |
| 9146 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 9146 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 9147 JavaScriptBackend backend = builder.compiler.backend; | 9147 JavaScriptBackend backend = builder.compiler.backend; |
| 9148 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 9148 ClassElement cls = backend.helpers.DynamicRuntimeType; |
| 9149 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 9149 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 9150 } | 9150 } |
| 9151 } | 9151 } |
| OLD | NEW |