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 2569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2580 bool assertTypeInContext(DartType type, [Spannable spannable]) { | 2580 bool assertTypeInContext(DartType type, [Spannable spannable]) { |
2581 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable, | 2581 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable, |
2582 () { | 2582 () { |
2583 ClassElement contextClass = Types.getClassContext(type); | 2583 ClassElement contextClass = Types.getClassContext(type); |
2584 return contextClass == null || contextClass == localsHandler.contextClass; | 2584 return contextClass == null || contextClass == localsHandler.contextClass; |
2585 }, | 2585 }, |
2586 message: "Type '$type' is not valid context of " | 2586 message: "Type '$type' is not valid context of " |
2587 "${localsHandler.contextClass}."); | 2587 "${localsHandler.contextClass}."); |
2588 } | 2588 } |
2589 | 2589 |
2590 /// Build a [HTypeConversion] for convertion [original] to type [type]. | 2590 /// Build a [HTypeConversion] for converting [original] to type [type]. |
2591 /// | 2591 /// |
2592 /// Invariant: [type] must be valid in the context. | 2592 /// Invariant: [type] must be valid in the context. |
2593 /// See [LocalsHandler.substInContext]. | 2593 /// See [LocalsHandler.substInContext]. |
2594 HInstruction buildTypeConversion( | 2594 HInstruction buildTypeConversion( |
2595 HInstruction original, DartType type, int kind) { | 2595 HInstruction original, DartType type, int kind) { |
2596 if (type == null) return original; | 2596 if (type == null) return original; |
| 2597 // GENERIC_METHODS: The following statement was added for parsing and |
| 2598 // ignoring method type variables; must be generalized for full support of |
| 2599 // generic methods. |
| 2600 type = type.dynamifyMethodTypeVariableType; |
2597 type = type.unaliased; | 2601 type = type.unaliased; |
2598 assert(assertTypeInContext(type, original)); | 2602 assert(assertTypeInContext(type, original)); |
2599 if (type.isInterfaceType && !type.treatAsRaw) { | 2603 if (type.isInterfaceType && !type.treatAsRaw) { |
2600 TypeMask subtype = new TypeMask.subtype(type.element, compiler.world); | 2604 TypeMask subtype = new TypeMask.subtype(type.element, compiler.world); |
2601 HInstruction representations = buildTypeArgumentRepresentations(type); | 2605 HInstruction representations = buildTypeArgumentRepresentations(type); |
2602 add(representations); | 2606 add(representations); |
2603 return new HTypeConversion.withTypeRepresentation( | 2607 return new HTypeConversion.withTypeRepresentation( |
2604 type, kind, subtype, original, representations); | 2608 type, kind, subtype, original, representations); |
2605 } else if (type.isTypeVariable) { | 2609 } else if (type.isTypeVariable) { |
2606 TypeMask subtype = original.instructionType; | 2610 TypeMask subtype = original.instructionType; |
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3807 code, backend.readableArrayType, inputs, | 3811 code, backend.readableArrayType, inputs, |
3808 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); | 3812 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); |
3809 return representation; | 3813 return representation; |
3810 } | 3814 } |
3811 } | 3815 } |
3812 | 3816 |
3813 @override | 3817 @override |
3814 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { | 3818 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { |
3815 HInstruction expressionInstruction = visitAndPop(expression); | 3819 HInstruction expressionInstruction = visitAndPop(expression); |
3816 if (type.isMalformed) { | 3820 if (type.isMalformed) { |
3817 ErroneousElement element = type.element; | 3821 String message; |
3818 generateTypeError(node, element.message); | 3822 if (type is MalformedType) { |
| 3823 ErroneousElement element = type.element; |
| 3824 message = element.message; |
| 3825 } else { |
| 3826 assert(type is MethodTypeVariableType); |
| 3827 message = "Method type variables are not reified."; |
| 3828 } |
| 3829 generateTypeError(node, message); |
3819 } else { | 3830 } else { |
3820 HInstruction converted = buildTypeConversion(expressionInstruction, | 3831 HInstruction converted = buildTypeConversion(expressionInstruction, |
3821 localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK); | 3832 localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK); |
3822 if (converted != expressionInstruction) add(converted); | 3833 if (converted != expressionInstruction) add(converted); |
3823 stack.add(converted); | 3834 stack.add(converted); |
3824 } | 3835 } |
3825 } | 3836 } |
3826 | 3837 |
3827 @override | 3838 @override |
3828 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { | 3839 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { |
3829 HInstruction expressionInstruction = visitAndPop(expression); | 3840 HInstruction expressionInstruction = visitAndPop(expression); |
3830 push(buildIsNode(node, type, expressionInstruction)); | 3841 push(buildIsNode(node, type, expressionInstruction)); |
3831 } | 3842 } |
3832 | 3843 |
3833 @override | 3844 @override |
3834 void visitIsNot(ast.Send node, ast.Node expression, DartType type, _) { | 3845 void visitIsNot(ast.Send node, ast.Node expression, DartType type, _) { |
3835 HInstruction expressionInstruction = visitAndPop(expression); | 3846 HInstruction expressionInstruction = visitAndPop(expression); |
3836 HInstruction instruction = buildIsNode(node, type, expressionInstruction); | 3847 HInstruction instruction = buildIsNode(node, type, expressionInstruction); |
3837 add(instruction); | 3848 add(instruction); |
3838 push(new HNot(instruction, backend.boolType)); | 3849 push(new HNot(instruction, backend.boolType)); |
3839 } | 3850 } |
3840 | 3851 |
3841 HInstruction buildIsNode( | 3852 HInstruction buildIsNode( |
3842 ast.Node node, DartType type, HInstruction expression) { | 3853 ast.Node node, DartType type, HInstruction expression) { |
3843 type = localsHandler.substInContext(type).unaliased; | 3854 type = localsHandler.substInContext(type).unaliased; |
3844 if (type.isFunctionType) { | 3855 if (type.isMalformed) { |
| 3856 String message; |
| 3857 if (type is MethodTypeVariableType) { |
| 3858 message = "Method type variables are not reified, " |
| 3859 "so they cannot be tested with an `is` expression."; |
| 3860 } else { |
| 3861 assert(type is MalformedType); |
| 3862 ErroneousElement element = type.element; |
| 3863 message = element.message; |
| 3864 } |
| 3865 generateTypeError(node, message); |
| 3866 HInstruction call = pop(); |
| 3867 return new HIs.compound(type, expression, call, backend.boolType); |
| 3868 } else if (type.isFunctionType) { |
3845 List arguments = [buildFunctionType(type), expression]; | 3869 List arguments = [buildFunctionType(type), expression]; |
3846 pushInvokeDynamic( | 3870 pushInvokeDynamic( |
3847 node, | 3871 node, |
3848 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), | 3872 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), |
3849 CallStructure.ONE_ARG), | 3873 CallStructure.ONE_ARG), |
3850 null, | 3874 null, |
3851 arguments); | 3875 arguments); |
3852 return new HIs.compound(type, expression, pop(), backend.boolType); | 3876 return new HIs.compound(type, expression, pop(), backend.boolType); |
3853 } else if (type.isTypeVariable) { | 3877 } else if (type.isTypeVariable) { |
3854 HInstruction runtimeType = addTypeVariableReference(type); | 3878 HInstruction runtimeType = addTypeVariableReference(type); |
(...skipping 14 matching lines...) Expand all Loading... |
3869 : graph.addConstantNull(compiler); | 3893 : graph.addConstantNull(compiler); |
3870 List<HInstruction> inputs = <HInstruction>[ | 3894 List<HInstruction> inputs = <HInstruction>[ |
3871 expression, | 3895 expression, |
3872 isFieldName, | 3896 isFieldName, |
3873 representations, | 3897 representations, |
3874 asFieldName | 3898 asFieldName |
3875 ]; | 3899 ]; |
3876 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); | 3900 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); |
3877 HInstruction call = pop(); | 3901 HInstruction call = pop(); |
3878 return new HIs.compound(type, expression, call, backend.boolType); | 3902 return new HIs.compound(type, expression, call, backend.boolType); |
3879 } else if (type.isMalformed) { | |
3880 ErroneousElement element = type.element; | |
3881 generateTypeError(node, element.message); | |
3882 HInstruction call = pop(); | |
3883 return new HIs.compound(type, expression, call, backend.boolType); | |
3884 } else { | 3903 } else { |
3885 if (backend.hasDirectCheckFor(type)) { | 3904 if (backend.hasDirectCheckFor(type)) { |
3886 return new HIs.direct(type, expression, backend.boolType); | 3905 return new HIs.direct(type, expression, backend.boolType); |
3887 } | 3906 } |
3888 // The interceptor is not always needed. It is removed by optimization | 3907 // The interceptor is not always needed. It is removed by optimization |
3889 // when the receiver type or tested type permit. | 3908 // when the receiver type or tested type permit. |
3890 return new HIs.raw( | 3909 return new HIs.raw( |
3891 type, expression, invokeInterceptor(expression), backend.boolType); | 3910 type, expression, invokeInterceptor(expression), backend.boolType); |
3892 } | 3911 } |
3893 } | 3912 } |
(...skipping 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5339 // identifier that refers to the class/typedef) as a constant. | 5358 // identifier that refers to the class/typedef) as a constant. |
5340 stack.add(addConstant(node.selector)); | 5359 stack.add(addConstant(node.selector)); |
5341 } else { | 5360 } else { |
5342 stack.add(addConstant(node)); | 5361 stack.add(addConstant(node)); |
5343 } | 5362 } |
5344 } | 5363 } |
5345 | 5364 |
5346 /// Generate the literal for [typeVariable] in the current context. | 5365 /// Generate the literal for [typeVariable] in the current context. |
5347 void generateTypeVariableLiteral( | 5366 void generateTypeVariableLiteral( |
5348 ast.Send node, TypeVariableType typeVariable) { | 5367 ast.Send node, TypeVariableType typeVariable) { |
5349 DartType type = localsHandler.substInContext(typeVariable); | 5368 // GENERIC_METHODS: This provides thin support for method type variables |
5350 HInstruction value = analyzeTypeArgument(type, | 5369 // by treating them as malformed when evaluated as a literal. For full |
5351 sourceInformation: sourceInformationBuilder.buildGet(node)); | 5370 // support of generic methods this must be revised. |
5352 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], | 5371 if (typeVariable is MethodTypeVariableType) { |
5353 typeMask: backend.stringType); | 5372 generateTypeError(node, "Method type variables are not reified"); |
5354 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); | 5373 } else { |
| 5374 DartType type = localsHandler.substInContext(typeVariable); |
| 5375 HInstruction value = analyzeTypeArgument(type, |
| 5376 sourceInformation: sourceInformationBuilder.buildGet(node)); |
| 5377 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], |
| 5378 typeMask: backend.stringType); |
| 5379 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); |
| 5380 } |
5355 } | 5381 } |
5356 | 5382 |
5357 /// Generate a call to a type literal. | 5383 /// Generate a call to a type literal. |
5358 void generateTypeLiteralCall(ast.Send node) { | 5384 void generateTypeLiteralCall(ast.Send node) { |
5359 // This send is of the form 'e(...)', where e is resolved to a type | 5385 // This send is of the form 'e(...)', where e is resolved to a type |
5360 // reference. We create a regular closure call on the result of the type | 5386 // reference. We create a regular closure call on the result of the type |
5361 // reference instead of creating a NoSuchMethodError to avoid pulling it | 5387 // reference instead of creating a NoSuchMethodError to avoid pulling it |
5362 // in if it is not used (e.g., in a try/catch). | 5388 // in if it is not used (e.g., in a try/catch). |
5363 HInstruction target = pop(); | 5389 HInstruction target = pop(); |
5364 generateCallInvoke(node, target, | 5390 generateCallInvoke(node, target, |
(...skipping 3241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8606 const _LoopTypeVisitor(); | 8632 const _LoopTypeVisitor(); |
8607 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 8633 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
8608 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 8634 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
8609 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 8635 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
8610 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 8636 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
8611 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8637 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8612 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8638 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8613 int visitSwitchStatement(ast.SwitchStatement node) => | 8639 int visitSwitchStatement(ast.SwitchStatement node) => |
8614 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 8640 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
8615 } | 8641 } |
OLD | NEW |