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