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 |