| 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 18 matching lines...) Expand all Loading... |
| 29 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; | 29 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; |
| 30 import '../native/native.dart' as native; | 30 import '../native/native.dart' as native; |
| 31 import '../resolution/operators.dart'; | 31 import '../resolution/operators.dart'; |
| 32 import '../resolution/semantic_visitor.dart'; | 32 import '../resolution/semantic_visitor.dart'; |
| 33 import '../resolution/tree_elements.dart' show TreeElements; | 33 import '../resolution/tree_elements.dart' show TreeElements; |
| 34 import '../tree/tree.dart' as ast; | 34 import '../tree/tree.dart' as ast; |
| 35 import '../types/types.dart'; | 35 import '../types/types.dart'; |
| 36 import '../universe/call_structure.dart' show CallStructure; | 36 import '../universe/call_structure.dart' show CallStructure; |
| 37 import '../universe/selector.dart' show Selector; | 37 import '../universe/selector.dart' show Selector; |
| 38 import '../universe/side_effects.dart' show SideEffects; | 38 import '../universe/side_effects.dart' show SideEffects; |
| 39 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse; | 39 import '../universe/use.dart' show DynamicUse, StaticUse; |
| 40 import '../util/util.dart'; | 40 import '../util/util.dart'; |
| 41 import '../world.dart' show ClosedWorld; | 41 import '../world.dart' show ClosedWorld; |
| 42 | 42 |
| 43 import 'graph_builder.dart'; | 43 import 'graph_builder.dart'; |
| 44 import 'jump_handler.dart'; | 44 import 'jump_handler.dart'; |
| 45 import 'locals_handler.dart'; | 45 import 'locals_handler.dart'; |
| 46 import 'loop_handler.dart'; | 46 import 'loop_handler.dart'; |
| 47 import 'nodes.dart'; | 47 import 'nodes.dart'; |
| 48 import 'optimize.dart'; | 48 import 'optimize.dart'; |
| 49 import 'ssa_branch_builder.dart'; | 49 import 'ssa_branch_builder.dart'; |
| 50 import 'type_builder.dart'; |
| 50 import 'types.dart'; | 51 import 'types.dart'; |
| 51 | 52 |
| 52 class SsaBuilderTask extends CompilerTask { | 53 class SsaBuilderTask extends CompilerTask { |
| 53 final CodeEmitterTask emitter; | 54 final CodeEmitterTask emitter; |
| 54 final JavaScriptBackend backend; | 55 final JavaScriptBackend backend; |
| 55 final SourceInformationStrategy sourceInformationFactory; | 56 final SourceInformationStrategy sourceInformationFactory; |
| 56 final Compiler compiler; | 57 final Compiler compiler; |
| 57 | 58 |
| 58 String get name => 'SSA builder'; | 59 String get name => 'SSA builder'; |
| 59 | 60 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 /// Returns `true` if the current element is an `async` function. | 182 /// Returns `true` if the current element is an `async` function. |
| 182 bool get isBuildingAsyncFunction { | 183 bool get isBuildingAsyncFunction { |
| 183 Element element = sourceElement; | 184 Element element = sourceElement; |
| 184 return (element is FunctionElement && | 185 return (element is FunctionElement && |
| 185 element.asyncMarker == AsyncMarker.ASYNC); | 186 element.asyncMarker == AsyncMarker.ASYNC); |
| 186 } | 187 } |
| 187 | 188 |
| 188 /// Handles the building of loops. | 189 /// Handles the building of loops. |
| 189 LoopHandler<ast.Node> loopHandler; | 190 LoopHandler<ast.Node> loopHandler; |
| 190 | 191 |
| 192 /// Handles type check building. |
| 193 TypeBuilder typeBuilder; |
| 194 |
| 191 // TODO(sigmund): make most args optional | 195 // TODO(sigmund): make most args optional |
| 192 SsaBuilder( | 196 SsaBuilder( |
| 193 this.target, | 197 this.target, |
| 194 this.resolvedAst, | 198 this.resolvedAst, |
| 195 this.registry, | 199 this.registry, |
| 196 JavaScriptBackend backend, | 200 JavaScriptBackend backend, |
| 197 this.nativeEmitter, | 201 this.nativeEmitter, |
| 198 SourceInformationStrategy sourceInformationFactory) | 202 SourceInformationStrategy sourceInformationFactory) |
| 199 : this.infoReporter = backend.compiler.dumpInfoTask, | 203 : this.infoReporter = backend.compiler.dumpInfoTask, |
| 200 this.backend = backend, | 204 this.backend = backend, |
| 201 this.constantSystem = backend.constantSystem, | 205 this.constantSystem = backend.constantSystem, |
| 202 this.rti = backend.rti, | 206 this.rti = backend.rti, |
| 203 this.inferenceResults = backend.compiler.globalInference.results { | 207 this.inferenceResults = backend.compiler.globalInference.results { |
| 204 assert(target.isImplementation); | 208 assert(target.isImplementation); |
| 205 compiler = backend.compiler; | 209 compiler = backend.compiler; |
| 206 elementInferenceResults = _resultOf(target); | 210 elementInferenceResults = _resultOf(target); |
| 207 assert(elementInferenceResults != null); | 211 assert(elementInferenceResults != null); |
| 208 graph.element = target; | 212 graph.element = target; |
| 209 sourceElementStack.add(target); | 213 sourceElementStack.add(target); |
| 210 sourceInformationBuilder = | 214 sourceInformationBuilder = |
| 211 sourceInformationFactory.createBuilderForContext(resolvedAst); | 215 sourceInformationFactory.createBuilderForContext(resolvedAst); |
| 212 graph.sourceInformation = | 216 graph.sourceInformation = |
| 213 sourceInformationBuilder.buildVariableDeclaration(); | 217 sourceInformationBuilder.buildVariableDeclaration(); |
| 214 localsHandler = new LocalsHandler(this, target, null, compiler); | 218 localsHandler = new LocalsHandler(this, target, null, compiler); |
| 215 loopHandler = new SsaLoopHandler(this); | 219 loopHandler = new SsaLoopHandler(this); |
| 220 typeBuilder = new TypeBuilder(this); |
| 216 } | 221 } |
| 217 | 222 |
| 218 BackendHelpers get helpers => backend.helpers; | 223 BackendHelpers get helpers => backend.helpers; |
| 219 | 224 |
| 220 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; | 225 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; |
| 221 | 226 |
| 222 DiagnosticReporter get reporter => compiler.reporter; | 227 DiagnosticReporter get reporter => compiler.reporter; |
| 223 | 228 |
| 224 CoreClasses get coreClasses => compiler.coreClasses; | 229 CoreClasses get coreClasses => compiler.coreClasses; |
| 225 | 230 |
| 231 Element get targetElement => target; |
| 232 |
| 226 /// Reference to resolved elements in [target]'s AST. | 233 /// Reference to resolved elements in [target]'s AST. |
| 227 TreeElements get elements => resolvedAst.elements; | 234 TreeElements get elements => resolvedAst.elements; |
| 228 | 235 |
| 229 @override | 236 @override |
| 230 SemanticSendVisitor get sendVisitor => this; | 237 SemanticSendVisitor get sendVisitor => this; |
| 231 | 238 |
| 232 @override | 239 @override |
| 233 void visitNode(ast.Node node) { | 240 void visitNode(ast.Node node) { |
| 234 internalError(node, "Unhandled node: $node"); | 241 internalError(node, "Unhandled node: $node"); |
| 235 } | 242 } |
| 236 | 243 |
| 237 @override | 244 @override |
| 238 void apply(ast.Node node, [_]) { | 245 void apply(ast.Node node, [_]) { |
| 239 node.accept(this); | 246 node.accept(this); |
| 240 } | 247 } |
| 241 | 248 |
| 242 /// Returns the current source element. | 249 /// Returns the current source element. |
| 243 /// | 250 /// |
| 244 /// The returned element is a declaration element. | 251 /// The returned element is a declaration element. |
| 245 // TODO(johnniwinther): Check that all usages of sourceElement agree on | 252 // TODO(johnniwinther): Check that all usages of sourceElement agree on |
| 246 // implementation/declaration distinction. | 253 // implementation/declaration distinction. |
| 254 @override |
| 247 Element get sourceElement => sourceElementStack.last; | 255 Element get sourceElement => sourceElementStack.last; |
| 248 | 256 |
| 249 /// Helper to retrieve global inference results for [element] with special | 257 /// Helper to retrieve global inference results for [element] with special |
| 250 /// care for `ConstructorBodyElement`s which don't exist at the time the | 258 /// care for `ConstructorBodyElement`s which don't exist at the time the |
| 251 /// global analysis run. | 259 /// global analysis run. |
| 252 /// | 260 /// |
| 253 /// Note: this helper is used selectively. When we know that we are in a | 261 /// Note: this helper is used selectively. When we know that we are in a |
| 254 /// context were we don't expect to see a constructor body element, we | 262 /// context were we don't expect to see a constructor body element, we |
| 255 /// directly fetch the data from the global inference results. | 263 /// directly fetch the data from the global inference results. |
| 256 GlobalTypeInferenceElementResult _resultOf(AstElement element) => | 264 GlobalTypeInferenceElementResult _resultOf(AstElement element) => |
| 257 inferenceResults.resultOf( | 265 inferenceResults.resultOf( |
| 258 element is ConstructorBodyElementX ? element.constructor : element); | 266 element is ConstructorBodyElementX ? element.constructor : element); |
| 259 | 267 |
| 260 bool get _checkOrTrustTypes => | |
| 261 compiler.options.enableTypeAssertions || | |
| 262 compiler.options.trustTypeAnnotations; | |
| 263 | |
| 264 /// Build the graph for [target]. | 268 /// Build the graph for [target]. |
| 265 HGraph build() { | 269 HGraph build() { |
| 266 assert(invariant(target, target.isImplementation)); | 270 assert(invariant(target, target.isImplementation)); |
| 267 HInstruction.idCounter = 0; | 271 HInstruction.idCounter = 0; |
| 268 // TODO(sigmund): remove `result` and return graph directly, need to ensure | 272 // TODO(sigmund): remove `result` and return graph directly, need to ensure |
| 269 // that it can never be null (see result in buildFactory for instance). | 273 // that it can never be null (see result in buildFactory for instance). |
| 270 var result; | 274 var result; |
| 271 if (target.isGenerativeConstructor) { | 275 if (target.isGenerativeConstructor) { |
| 272 result = buildFactory(resolvedAst); | 276 result = buildFactory(resolvedAst); |
| 273 } else if (target.isGenerativeConstructorBody || | 277 } else if (target.isGenerativeConstructorBody || |
| (...skipping 13 matching lines...) Expand all Loading... |
| 287 reporter.internalError(target, 'Unexpected element kind $target.'); | 291 reporter.internalError(target, 'Unexpected element kind $target.'); |
| 288 } | 292 } |
| 289 assert(result.isValid()); | 293 assert(result.isValid()); |
| 290 return result; | 294 return result; |
| 291 } | 295 } |
| 292 | 296 |
| 293 void addWithPosition(HInstruction instruction, ast.Node node) { | 297 void addWithPosition(HInstruction instruction, ast.Node node) { |
| 294 add(attachPosition(instruction, node)); | 298 add(attachPosition(instruction, node)); |
| 295 } | 299 } |
| 296 | 300 |
| 301 HTypeConversion buildFunctionTypeConversion( |
| 302 HInstruction original, DartType type, int kind) { |
| 303 String name = |
| 304 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck'; |
| 305 |
| 306 List<HInstruction> arguments = <HInstruction>[ |
| 307 buildFunctionType(type), |
| 308 original |
| 309 ]; |
| 310 pushInvokeDynamic( |
| 311 null, |
| 312 new Selector.call( |
| 313 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG), |
| 314 null, |
| 315 arguments); |
| 316 |
| 317 return new HTypeConversion(type, kind, original.instructionType, pop()); |
| 318 } |
| 319 |
| 297 /** | 320 /** |
| 298 * Returns a complete argument list for a call of [function]. | 321 * Returns a complete argument list for a call of [function]. |
| 299 */ | 322 */ |
| 300 List<HInstruction> completeSendArgumentsList( | 323 List<HInstruction> completeSendArgumentsList( |
| 301 FunctionElement function, | 324 FunctionElement function, |
| 302 Selector selector, | 325 Selector selector, |
| 303 List<HInstruction> providedArguments, | 326 List<HInstruction> providedArguments, |
| 304 ast.Node currentNode) { | 327 ast.Node currentNode) { |
| 305 assert(invariant(function, function.isImplementation)); | 328 assert(invariant(function, function.isImplementation)); |
| 306 assert(providedArguments != null); | 329 assert(providedArguments != null); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 ResolvedAst resolvedAst = field.resolvedAst; | 767 ResolvedAst resolvedAst = field.resolvedAst; |
| 745 openFunction(field, resolvedAst.node); | 768 openFunction(field, resolvedAst.node); |
| 746 HInstruction thisInstruction = localsHandler.readThis(); | 769 HInstruction thisInstruction = localsHandler.readThis(); |
| 747 // Use dynamic type because the type computed by the inferrer is | 770 // Use dynamic type because the type computed by the inferrer is |
| 748 // narrowed to the type annotation. | 771 // narrowed to the type annotation. |
| 749 HInstruction parameter = new HParameterValue(field, backend.dynamicType); | 772 HInstruction parameter = new HParameterValue(field, backend.dynamicType); |
| 750 // Add the parameter as the last instruction of the entry block. | 773 // Add the parameter as the last instruction of the entry block. |
| 751 // If the method is intercepted, we want the actual receiver | 774 // If the method is intercepted, we want the actual receiver |
| 752 // to be the first parameter. | 775 // to be the first parameter. |
| 753 graph.entry.addBefore(graph.entry.last, parameter); | 776 graph.entry.addBefore(graph.entry.last, parameter); |
| 754 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); | 777 HInstruction value = |
| 778 typeBuilder.potentiallyCheckOrTrustType(parameter, field.type); |
| 755 add(new HFieldSet(field, thisInstruction, value)); | 779 add(new HFieldSet(field, thisInstruction, value)); |
| 756 return closeFunction(); | 780 return closeFunction(); |
| 757 } | 781 } |
| 758 | 782 |
| 759 HGraph buildLazyInitializer(VariableElement variable) { | 783 HGraph buildLazyInitializer(VariableElement variable) { |
| 760 assert(invariant(variable, resolvedAst.element == variable, | 784 assert(invariant(variable, resolvedAst.element == variable, |
| 761 message: "Unexpected variable $variable for $resolvedAst.")); | 785 message: "Unexpected variable $variable for $resolvedAst.")); |
| 762 inLazyInitializerExpression = true; | 786 inLazyInitializerExpression = true; |
| 763 ast.VariableDefinitions node = resolvedAst.node; | 787 ast.VariableDefinitions node = resolvedAst.node; |
| 764 ast.Node initializer = resolvedAst.body; | 788 ast.Node initializer = resolvedAst.body; |
| 765 assert(invariant(variable, initializer != null, | 789 assert(invariant(variable, initializer != null, |
| 766 message: "Non-constant variable $variable has no initializer.")); | 790 message: "Non-constant variable $variable has no initializer.")); |
| 767 openFunction(variable, node); | 791 openFunction(variable, node); |
| 768 visit(initializer); | 792 visit(initializer); |
| 769 HInstruction value = pop(); | 793 HInstruction value = pop(); |
| 770 value = potentiallyCheckOrTrustType(value, variable.type); | 794 value = typeBuilder.potentiallyCheckOrTrustType(value, variable.type); |
| 771 // In the case of multiple declarations (and some definitions) on the same | 795 // In the case of multiple declarations (and some definitions) on the same |
| 772 // line, the source pointer needs to point to the right initialized | 796 // line, the source pointer needs to point to the right initialized |
| 773 // variable. So find the specific initialized variable we are referring to. | 797 // variable. So find the specific initialized variable we are referring to. |
| 774 ast.Node sourceInfoNode = initializer; | 798 ast.Node sourceInfoNode = initializer; |
| 775 for (var definition in node.definitions) { | 799 for (var definition in node.definitions) { |
| 776 if (definition is ast.SendSet && | 800 if (definition is ast.SendSet && |
| 777 definition.selector.asIdentifier().source == variable.name) { | 801 definition.selector.asIdentifier().source == variable.name) { |
| 778 sourceInfoNode = definition.assignmentOperator; | 802 sourceInfoNode = definition.assignmentOperator; |
| 779 break; | 803 break; |
| 780 } | 804 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 elementInferenceResults = state.oldElementInferenceResults; | 916 elementInferenceResults = state.oldElementInferenceResults; |
| 893 returnType = state.oldReturnType; | 917 returnType = state.oldReturnType; |
| 894 assert(stack.isEmpty); | 918 assert(stack.isEmpty); |
| 895 stack = state.oldStack; | 919 stack = state.oldStack; |
| 896 } | 920 } |
| 897 | 921 |
| 898 /** | 922 /** |
| 899 * Run this builder on the body of the [function] to be inlined. | 923 * Run this builder on the body of the [function] to be inlined. |
| 900 */ | 924 */ |
| 901 void visitInlinedFunction(ResolvedAst resolvedAst) { | 925 void visitInlinedFunction(ResolvedAst resolvedAst) { |
| 902 potentiallyCheckInlinedParameterTypes(resolvedAst.element.implementation); | 926 typeBuilder.potentiallyCheckInlinedParameterTypes( |
| 927 resolvedAst.element.implementation); |
| 903 | 928 |
| 904 if (resolvedAst.element.isGenerativeConstructor) { | 929 if (resolvedAst.element.isGenerativeConstructor) { |
| 905 buildFactory(resolvedAst); | 930 buildFactory(resolvedAst); |
| 906 } else { | 931 } else { |
| 907 ast.FunctionExpression functionNode = resolvedAst.node; | 932 ast.FunctionExpression functionNode = resolvedAst.node; |
| 908 functionNode.body.accept(this); | 933 functionNode.body.accept(this); |
| 909 } | 934 } |
| 910 } | 935 } |
| 911 | 936 |
| 912 addInlinedInstantiation(DartType type) { | 937 addInlinedInstantiation(DartType type) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 925 /* When inlining the iterator methods generated for a [:for-in:] loop, the | 950 /* When inlining the iterator methods generated for a [:for-in:] loop, the |
| 926 * [currentNode] is the [ForIn] tree. The compiler-generated iterator | 951 * [currentNode] is the [ForIn] tree. The compiler-generated iterator |
| 927 * invocations are known to have fully specified argument lists, no default | 952 * invocations are known to have fully specified argument lists, no default |
| 928 * arguments are used. See invocations of [pushInvokeDynamic] in | 953 * arguments are used. See invocations of [pushInvokeDynamic] in |
| 929 * [visitForIn]. | 954 * [visitForIn]. |
| 930 */ | 955 */ |
| 931 return currentNode.asForIn() != null; | 956 return currentNode.asForIn() != null; |
| 932 } | 957 } |
| 933 | 958 |
| 934 /** | 959 /** |
| 935 * In checked mode, generate type tests for the parameters of the inlined | |
| 936 * function. | |
| 937 */ | |
| 938 void potentiallyCheckInlinedParameterTypes(FunctionElement function) { | |
| 939 if (!_checkOrTrustTypes) return; | |
| 940 | |
| 941 FunctionSignature signature = function.functionSignature; | |
| 942 signature.orderedForEachParameter((ParameterElement parameter) { | |
| 943 HInstruction argument = localsHandler.readLocal(parameter); | |
| 944 potentiallyCheckOrTrustType(argument, parameter.type); | |
| 945 }); | |
| 946 } | |
| 947 | |
| 948 /** | |
| 949 * Documentation wanted -- johnniwinther | 960 * Documentation wanted -- johnniwinther |
| 950 * | 961 * |
| 951 * Invariant: [constructors] must contain only implementation elements. | 962 * Invariant: [constructors] must contain only implementation elements. |
| 952 */ | 963 */ |
| 953 void inlineSuperOrRedirect( | 964 void inlineSuperOrRedirect( |
| 954 ResolvedAst constructorResolvedAst, | 965 ResolvedAst constructorResolvedAst, |
| 955 List<HInstruction> compiledArguments, | 966 List<HInstruction> compiledArguments, |
| 956 List<ResolvedAst> constructorResolvedAsts, | 967 List<ResolvedAst> constructorResolvedAsts, |
| 957 Map<Element, HInstruction> fieldValues, | 968 Map<Element, HInstruction> fieldValues, |
| 958 FunctionElement caller) { | 969 FunctionElement caller) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 973 List<DartType> arguments = type.typeArguments; | 984 List<DartType> arguments = type.typeArguments; |
| 974 List<DartType> typeVariables = enclosingClass.typeVariables; | 985 List<DartType> typeVariables = enclosingClass.typeVariables; |
| 975 if (!type.isRaw) { | 986 if (!type.isRaw) { |
| 976 assert(arguments.length == typeVariables.length); | 987 assert(arguments.length == typeVariables.length); |
| 977 Iterator<DartType> variables = typeVariables.iterator; | 988 Iterator<DartType> variables = typeVariables.iterator; |
| 978 type.typeArguments.forEach((DartType argument) { | 989 type.typeArguments.forEach((DartType argument) { |
| 979 variables.moveNext(); | 990 variables.moveNext(); |
| 980 TypeVariableType typeVariable = variables.current; | 991 TypeVariableType typeVariable = variables.current; |
| 981 localsHandler.updateLocal( | 992 localsHandler.updateLocal( |
| 982 localsHandler.getTypeVariableAsLocal(typeVariable), | 993 localsHandler.getTypeVariableAsLocal(typeVariable), |
| 983 analyzeTypeArgument(argument)); | 994 typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 984 }); | 995 }); |
| 985 } else { | 996 } else { |
| 986 // If the supertype is a raw type, we need to set to null the | 997 // If the supertype is a raw type, we need to set to null the |
| 987 // type variables. | 998 // type variables. |
| 988 for (TypeVariableType variable in typeVariables) { | 999 for (TypeVariableType variable in typeVariables) { |
| 989 localsHandler.updateLocal( | 1000 localsHandler.updateLocal( |
| 990 localsHandler.getTypeVariableAsLocal(variable), | 1001 localsHandler.getTypeVariableAsLocal(variable), |
| 991 graph.addConstantNull(compiler)); | 1002 graph.addConstantNull(compiler)); |
| 992 } | 1003 } |
| 993 } | 1004 } |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 (ClassElement enclosingClass, FieldElement member) { | 1286 (ClassElement enclosingClass, FieldElement member) { |
| 1276 HInstruction value = fieldValues[member]; | 1287 HInstruction value = fieldValues[member]; |
| 1277 if (value == null) { | 1288 if (value == null) { |
| 1278 // Uninitialized native fields are pre-initialized by the native | 1289 // Uninitialized native fields are pre-initialized by the native |
| 1279 // implementation. | 1290 // implementation. |
| 1280 assert(invariant( | 1291 assert(invariant( |
| 1281 member, isNativeUpgradeFactory || compiler.compilationFailed)); | 1292 member, isNativeUpgradeFactory || compiler.compilationFailed)); |
| 1282 } else { | 1293 } else { |
| 1283 fields.add(member); | 1294 fields.add(member); |
| 1284 DartType type = localsHandler.substInContext(member.type); | 1295 DartType type = localsHandler.substInContext(member.type); |
| 1285 constructorArguments.add(potentiallyCheckOrTrustType(value, type)); | 1296 constructorArguments |
| 1297 .add(typeBuilder.potentiallyCheckOrTrustType(value, type)); |
| 1286 } | 1298 } |
| 1287 }, includeSuperAndInjectedMembers: true); | 1299 }, includeSuperAndInjectedMembers: true); |
| 1288 | 1300 |
| 1289 InterfaceType type = classElement.thisType; | 1301 InterfaceType type = classElement.thisType; |
| 1290 TypeMask ssaType = new TypeMask.nonNullExact( | 1302 TypeMask ssaType = new TypeMask.nonNullExact( |
| 1291 classElement.declaration, compiler.closedWorld); | 1303 classElement.declaration, compiler.closedWorld); |
| 1292 List<DartType> instantiatedTypes; | 1304 List<DartType> instantiatedTypes; |
| 1293 addInlinedInstantiation(type); | 1305 addInlinedInstantiation(type); |
| 1294 if (!currentInlinedInstantiations.isEmpty) { | 1306 if (!currentInlinedInstantiations.isEmpty) { |
| 1295 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); | 1307 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1473 // | 1485 // |
| 1474 // class A { | 1486 // class A { |
| 1475 // A(String foo) = A.b; | 1487 // A(String foo) = A.b; |
| 1476 // A(int foo) { print(foo); } | 1488 // A(int foo) { print(foo); } |
| 1477 // } | 1489 // } |
| 1478 // main() { | 1490 // main() { |
| 1479 // new A(499); // valid even in checked mode. | 1491 // new A(499); // valid even in checked mode. |
| 1480 // new A("foo"); // invalid in checked mode. | 1492 // new A("foo"); // invalid in checked mode. |
| 1481 // | 1493 // |
| 1482 // Only the final target is allowed to check for the argument types. | 1494 // Only the final target is allowed to check for the argument types. |
| 1483 newParameter = | 1495 newParameter = typeBuilder.potentiallyCheckOrTrustType( |
| 1484 potentiallyCheckOrTrustType(newParameter, parameterElement.type); | 1496 newParameter, parameterElement.type); |
| 1485 } | 1497 } |
| 1486 localsHandler.directLocals[parameterElement] = newParameter; | 1498 localsHandler.directLocals[parameterElement] = newParameter; |
| 1487 }); | 1499 }); |
| 1488 | 1500 |
| 1489 returnType = signature.type.returnType; | 1501 returnType = signature.type.returnType; |
| 1490 } else { | 1502 } else { |
| 1491 // Otherwise it is a lazy initializer which does not have parameters. | 1503 // Otherwise it is a lazy initializer which does not have parameters. |
| 1492 assert(element is VariableElement); | 1504 assert(element is VariableElement); |
| 1493 } | 1505 } |
| 1494 | 1506 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1512 if (JavaScriptBackend.TRACE_METHOD == 'post') { | 1524 if (JavaScriptBackend.TRACE_METHOD == 'post') { |
| 1513 if (element == backend.traceHelper) return; | 1525 if (element == backend.traceHelper) return; |
| 1514 // TODO(sigmund): create a better uuid for elements. | 1526 // TODO(sigmund): create a better uuid for elements. |
| 1515 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); | 1527 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); |
| 1516 HConstant nameConstant = addConstantString(element.name); | 1528 HConstant nameConstant = addConstantString(element.name); |
| 1517 add(new HInvokeStatic(backend.traceHelper, | 1529 add(new HInvokeStatic(backend.traceHelper, |
| 1518 <HInstruction>[idConstant, nameConstant], backend.dynamicType)); | 1530 <HInstruction>[idConstant, nameConstant], backend.dynamicType)); |
| 1519 } | 1531 } |
| 1520 } | 1532 } |
| 1521 | 1533 |
| 1522 /// Check that [type] is valid in the context of `localsHandler.contextClass`. | |
| 1523 /// This should only be called in assertions. | |
| 1524 bool assertTypeInContext(DartType type, [Spannable spannable]) { | |
| 1525 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable, | |
| 1526 () { | |
| 1527 ClassElement contextClass = Types.getClassContext(type); | |
| 1528 return contextClass == null || contextClass == localsHandler.contextClass; | |
| 1529 }, | |
| 1530 message: "Type '$type' is not valid context of " | |
| 1531 "${localsHandler.contextClass}."); | |
| 1532 } | |
| 1533 | |
| 1534 /// Build a [HTypeConversion] for converting [original] to type [type]. | |
| 1535 /// | |
| 1536 /// Invariant: [type] must be valid in the context. | |
| 1537 /// See [LocalsHandler.substInContext]. | |
| 1538 HInstruction buildTypeConversion( | |
| 1539 HInstruction original, DartType type, int kind) { | |
| 1540 if (type == null) return original; | |
| 1541 // GENERIC_METHODS: The following statement was added for parsing and | |
| 1542 // ignoring method type variables; must be generalized for full support of | |
| 1543 // generic methods. | |
| 1544 type = type.dynamifyMethodTypeVariableType; | |
| 1545 type = type.unaliased; | |
| 1546 assert(assertTypeInContext(type, original)); | |
| 1547 if (type.isInterfaceType && !type.treatAsRaw) { | |
| 1548 TypeMask subtype = | |
| 1549 new TypeMask.subtype(type.element, compiler.closedWorld); | |
| 1550 HInstruction representations = buildTypeArgumentRepresentations(type); | |
| 1551 add(representations); | |
| 1552 return new HTypeConversion.withTypeRepresentation( | |
| 1553 type, kind, subtype, original, representations); | |
| 1554 } else if (type.isTypeVariable) { | |
| 1555 TypeMask subtype = original.instructionType; | |
| 1556 HInstruction typeVariable = addTypeVariableReference(type); | |
| 1557 return new HTypeConversion.withTypeRepresentation( | |
| 1558 type, kind, subtype, original, typeVariable); | |
| 1559 } else if (type.isFunctionType) { | |
| 1560 String name = | |
| 1561 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck'; | |
| 1562 | |
| 1563 List<HInstruction> arguments = <HInstruction>[ | |
| 1564 buildFunctionType(type), | |
| 1565 original | |
| 1566 ]; | |
| 1567 pushInvokeDynamic( | |
| 1568 null, | |
| 1569 new Selector.call( | |
| 1570 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG), | |
| 1571 null, | |
| 1572 arguments); | |
| 1573 | |
| 1574 return new HTypeConversion(type, kind, original.instructionType, pop()); | |
| 1575 } else { | |
| 1576 return original.convertType(compiler, type, kind); | |
| 1577 } | |
| 1578 } | |
| 1579 | |
| 1580 HInstruction _trustType(HInstruction original, DartType type) { | |
| 1581 assert(compiler.options.trustTypeAnnotations); | |
| 1582 assert(type != null); | |
| 1583 type = localsHandler.substInContext(type); | |
| 1584 type = type.unaliased; | |
| 1585 if (type.isDynamic) return original; | |
| 1586 if (!type.isInterfaceType) return original; | |
| 1587 if (type.isObject) return original; | |
| 1588 // The type element is either a class or the void element. | |
| 1589 Element element = type.element; | |
| 1590 TypeMask mask = new TypeMask.subtype(element, compiler.closedWorld); | |
| 1591 return new HTypeKnown.pinned(mask, original); | |
| 1592 } | |
| 1593 | |
| 1594 HInstruction _checkType(HInstruction original, DartType type, int kind) { | |
| 1595 assert(compiler.options.enableTypeAssertions); | |
| 1596 assert(type != null); | |
| 1597 type = localsHandler.substInContext(type); | |
| 1598 HInstruction other = buildTypeConversion(original, type, kind); | |
| 1599 // TODO(johnniwinther): This operation on `registry` may be inconsistent. | |
| 1600 // If it is needed then it seems likely that similar invocations of | |
| 1601 // `buildTypeConversion` in `SsaBuilder.visitAs` should also be followed by | |
| 1602 // a similar operation on `registry`; otherwise, this one might not be | |
| 1603 // needed. | |
| 1604 registry?.registerTypeUse(new TypeUse.isCheck(type)); | |
| 1605 return other; | |
| 1606 } | |
| 1607 | |
| 1608 HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type, | |
| 1609 {int kind: HTypeConversion.CHECKED_MODE_CHECK}) { | |
| 1610 if (type == null) return original; | |
| 1611 HInstruction checkedOrTrusted = original; | |
| 1612 if (compiler.options.trustTypeAnnotations) { | |
| 1613 checkedOrTrusted = _trustType(original, type); | |
| 1614 } else if (compiler.options.enableTypeAssertions) { | |
| 1615 checkedOrTrusted = _checkType(original, type, kind); | |
| 1616 } | |
| 1617 if (checkedOrTrusted == original) return original; | |
| 1618 add(checkedOrTrusted); | |
| 1619 return checkedOrTrusted; | |
| 1620 } | |
| 1621 | |
| 1622 void assertIsSubtype( | 1534 void assertIsSubtype( |
| 1623 ast.Node node, DartType subtype, DartType supertype, String message) { | 1535 ast.Node node, DartType subtype, DartType supertype, String message) { |
| 1624 HInstruction subtypeInstruction = | 1536 HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument( |
| 1625 analyzeTypeArgument(localsHandler.substInContext(subtype)); | 1537 localsHandler.substInContext(subtype), sourceElement); |
| 1626 HInstruction supertypeInstruction = | 1538 HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument( |
| 1627 analyzeTypeArgument(localsHandler.substInContext(supertype)); | 1539 localsHandler.substInContext(supertype), sourceElement); |
| 1628 HInstruction messageInstruction = | 1540 HInstruction messageInstruction = |
| 1629 graph.addConstantString(new ast.DartString.literal(message), compiler); | 1541 graph.addConstantString(new ast.DartString.literal(message), compiler); |
| 1630 MethodElement element = helpers.assertIsSubtype; | 1542 MethodElement element = helpers.assertIsSubtype; |
| 1631 var inputs = <HInstruction>[ | 1543 var inputs = <HInstruction>[ |
| 1632 subtypeInstruction, | 1544 subtypeInstruction, |
| 1633 supertypeInstruction, | 1545 supertypeInstruction, |
| 1634 messageInstruction | 1546 messageInstruction |
| 1635 ]; | 1547 ]; |
| 1636 HInstruction assertIsSubtype = | 1548 HInstruction assertIsSubtype = |
| 1637 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType); | 1549 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType); |
| 1638 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); | 1550 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); |
| 1639 add(assertIsSubtype); | 1551 add(assertIsSubtype); |
| 1640 } | 1552 } |
| 1641 | 1553 |
| 1642 HGraph closeFunction() { | 1554 HGraph closeFunction() { |
| 1643 // TODO(kasperl): Make this goto an implicit return. | 1555 // TODO(kasperl): Make this goto an implicit return. |
| 1644 if (!isAborted()) closeAndGotoExit(new HGoto()); | 1556 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 1645 graph.finalize(); | 1557 graph.finalize(); |
| 1646 return graph; | 1558 return graph; |
| 1647 } | 1559 } |
| 1648 | 1560 |
| 1649 void pushWithPosition(HInstruction instruction, ast.Node node) { | 1561 void pushWithPosition(HInstruction instruction, ast.Node node) { |
| 1650 push(attachPosition(instruction, node)); | 1562 push(attachPosition(instruction, node)); |
| 1651 } | 1563 } |
| 1652 | 1564 |
| 1565 /// Pops the most recent instruction from the stack and 'boolifies' it. |
| 1566 /// |
| 1567 /// Boolification is checking if the value is '=== true'. |
| 1653 @override | 1568 @override |
| 1654 HInstruction popBoolified() { | 1569 HInstruction popBoolified() { |
| 1655 HInstruction value = pop(); | 1570 HInstruction value = pop(); |
| 1656 if (_checkOrTrustTypes) { | 1571 if (typeBuilder.checkOrTrustTypes) { |
| 1657 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType, | 1572 return typeBuilder.potentiallyCheckOrTrustType( |
| 1573 value, compiler.coreTypes.boolType, |
| 1658 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 1574 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
| 1659 } | 1575 } |
| 1660 HInstruction result = new HBoolify(value, backend.boolType); | 1576 HInstruction result = new HBoolify(value, backend.boolType); |
| 1661 add(result); | 1577 add(result); |
| 1662 return result; | 1578 return result; |
| 1663 } | 1579 } |
| 1664 | 1580 |
| 1665 HInstruction attachPosition(HInstruction target, ast.Node node) { | 1581 HInstruction attachPosition(HInstruction target, ast.Node node) { |
| 1666 if (node != null) { | 1582 if (node != null) { |
| 1667 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); | 1583 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2438 } | 2354 } |
| 2439 assert(invariant( | 2355 assert(invariant( |
| 2440 location, send == null || !Elements.isInstanceSend(send, elements), | 2356 location, send == null || !Elements.isInstanceSend(send, elements), |
| 2441 message: "Unexpected non instance setter: $element.")); | 2357 message: "Unexpected non instance setter: $element.")); |
| 2442 if (Elements.isStaticOrTopLevelField(element)) { | 2358 if (Elements.isStaticOrTopLevelField(element)) { |
| 2443 if (element.isSetter) { | 2359 if (element.isSetter) { |
| 2444 pushInvokeStatic(location, element, <HInstruction>[value]); | 2360 pushInvokeStatic(location, element, <HInstruction>[value]); |
| 2445 pop(); | 2361 pop(); |
| 2446 } else { | 2362 } else { |
| 2447 FieldElement field = element; | 2363 FieldElement field = element; |
| 2448 value = potentiallyCheckOrTrustType(value, field.type); | 2364 value = typeBuilder.potentiallyCheckOrTrustType(value, field.type); |
| 2449 addWithPosition(new HStaticStore(field, value), location); | 2365 addWithPosition(new HStaticStore(field, value), location); |
| 2450 } | 2366 } |
| 2451 stack.add(value); | 2367 stack.add(value); |
| 2452 } else if (Elements.isError(element)) { | 2368 } else if (Elements.isError(element)) { |
| 2453 generateNoSuchSetter(location, element, send == null ? null : value); | 2369 generateNoSuchSetter(location, element, send == null ? null : value); |
| 2454 } else if (Elements.isMalformed(element)) { | 2370 } else if (Elements.isMalformed(element)) { |
| 2455 // TODO(ahe): Do something like [generateWrongArgumentCountError]. | 2371 // TODO(ahe): Do something like [generateWrongArgumentCountError]. |
| 2456 stack.add(graph.addConstantNull(compiler)); | 2372 stack.add(graph.addConstantNull(compiler)); |
| 2457 } else { | 2373 } else { |
| 2458 stack.add(value); | 2374 stack.add(value); |
| 2459 LocalElement local = element; | 2375 LocalElement local = element; |
| 2460 // If the value does not already have a name, give it here. | 2376 // If the value does not already have a name, give it here. |
| 2461 if (value.sourceElement == null) { | 2377 if (value.sourceElement == null) { |
| 2462 value.sourceElement = local; | 2378 value.sourceElement = local; |
| 2463 } | 2379 } |
| 2464 HInstruction checkedOrTrusted = | 2380 HInstruction checkedOrTrusted = |
| 2465 potentiallyCheckOrTrustType(value, local.type); | 2381 typeBuilder.potentiallyCheckOrTrustType(value, local.type); |
| 2466 if (!identical(checkedOrTrusted, value)) { | 2382 if (!identical(checkedOrTrusted, value)) { |
| 2467 pop(); | 2383 pop(); |
| 2468 stack.add(checkedOrTrusted); | 2384 stack.add(checkedOrTrusted); |
| 2469 } | 2385 } |
| 2470 | 2386 |
| 2471 localsHandler.updateLocal(local, checkedOrTrusted, | 2387 localsHandler.updateLocal(local, checkedOrTrusted, |
| 2472 sourceInformation: | 2388 sourceInformation: |
| 2473 sourceInformationBuilder.buildAssignment(location)); | 2389 sourceInformationBuilder.buildAssignment(location)); |
| 2474 } | 2390 } |
| 2475 } | 2391 } |
| 2476 | 2392 |
| 2477 HInstruction invokeInterceptor(HInstruction receiver) { | 2393 HInstruction invokeInterceptor(HInstruction receiver) { |
| 2478 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); | 2394 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); |
| 2479 add(interceptor); | 2395 add(interceptor); |
| 2480 return interceptor; | 2396 return interceptor; |
| 2481 } | 2397 } |
| 2482 | 2398 |
| 2483 HLiteralList buildLiteralList(List<HInstruction> inputs) { | 2399 HLiteralList buildLiteralList(List<HInstruction> inputs) { |
| 2484 return new HLiteralList(inputs, backend.extendableArrayType); | 2400 return new HLiteralList(inputs, backend.extendableArrayType); |
| 2485 } | 2401 } |
| 2486 | 2402 |
| 2487 HInstruction buildTypeArgumentRepresentations(DartType type) { | |
| 2488 assert(!type.isTypeVariable); | |
| 2489 // Compute the representation of the type arguments, including access | |
| 2490 // to the runtime type information for type variables as instructions. | |
| 2491 assert(type.element.isClass); | |
| 2492 InterfaceType interface = type; | |
| 2493 List<HInstruction> inputs = <HInstruction>[]; | |
| 2494 for (DartType argument in interface.typeArguments) { | |
| 2495 inputs.add(analyzeTypeArgument(argument)); | |
| 2496 } | |
| 2497 HInstruction representation = new HTypeInfoExpression( | |
| 2498 TypeInfoExpressionKind.INSTANCE, | |
| 2499 interface.element.thisType, | |
| 2500 inputs, | |
| 2501 backend.dynamicType); | |
| 2502 return representation; | |
| 2503 } | |
| 2504 | |
| 2505 @override | 2403 @override |
| 2506 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { | 2404 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { |
| 2507 HInstruction expressionInstruction = visitAndPop(expression); | 2405 HInstruction expressionInstruction = visitAndPop(expression); |
| 2508 if (type.isMalformed) { | 2406 if (type.isMalformed) { |
| 2509 if (type is MalformedType) { | 2407 if (type is MalformedType) { |
| 2510 ErroneousElement element = type.element; | 2408 ErroneousElement element = type.element; |
| 2511 generateTypeError(node, element.message); | 2409 generateTypeError(node, element.message); |
| 2512 } else { | 2410 } else { |
| 2513 assert(type is MethodTypeVariableType); | 2411 assert(type is MethodTypeVariableType); |
| 2514 stack.add(expressionInstruction); | 2412 stack.add(expressionInstruction); |
| 2515 } | 2413 } |
| 2516 } else { | 2414 } else { |
| 2517 HInstruction converted = buildTypeConversion(expressionInstruction, | 2415 HInstruction converted = typeBuilder.buildTypeConversion( |
| 2518 localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK); | 2416 expressionInstruction, |
| 2417 localsHandler.substInContext(type), |
| 2418 HTypeConversion.CAST_TYPE_CHECK); |
| 2519 if (converted != expressionInstruction) add(converted); | 2419 if (converted != expressionInstruction) add(converted); |
| 2520 stack.add(converted); | 2420 stack.add(converted); |
| 2521 } | 2421 } |
| 2522 } | 2422 } |
| 2523 | 2423 |
| 2524 @override | 2424 @override |
| 2525 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { | 2425 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { |
| 2526 HInstruction expressionInstruction = visitAndPop(expression); | 2426 HInstruction expressionInstruction = visitAndPop(expression); |
| 2527 push(buildIsNode(node, type, expressionInstruction)); | 2427 push(buildIsNode(node, type, expressionInstruction)); |
| 2528 } | 2428 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2554 } else if (type.isFunctionType) { | 2454 } else if (type.isFunctionType) { |
| 2555 List arguments = [buildFunctionType(type), expression]; | 2455 List arguments = [buildFunctionType(type), expression]; |
| 2556 pushInvokeDynamic( | 2456 pushInvokeDynamic( |
| 2557 node, | 2457 node, |
| 2558 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), | 2458 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), |
| 2559 CallStructure.ONE_ARG), | 2459 CallStructure.ONE_ARG), |
| 2560 null, | 2460 null, |
| 2561 arguments); | 2461 arguments); |
| 2562 return new HIs.compound(type, expression, pop(), backend.boolType); | 2462 return new HIs.compound(type, expression, pop(), backend.boolType); |
| 2563 } else if (type.isTypeVariable) { | 2463 } else if (type.isTypeVariable) { |
| 2564 HInstruction runtimeType = addTypeVariableReference(type); | 2464 HInstruction runtimeType = |
| 2465 typeBuilder.addTypeVariableReference(type, sourceElement); |
| 2565 Element helper = helpers.checkSubtypeOfRuntimeType; | 2466 Element helper = helpers.checkSubtypeOfRuntimeType; |
| 2566 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2467 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 2567 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 2468 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); |
| 2568 HInstruction call = pop(); | 2469 HInstruction call = pop(); |
| 2569 return new HIs.variable(type, expression, call, backend.boolType); | 2470 return new HIs.variable(type, expression, call, backend.boolType); |
| 2570 } else if (RuntimeTypes.hasTypeArguments(type)) { | 2471 } else if (RuntimeTypes.hasTypeArguments(type)) { |
| 2571 ClassElement element = type.element; | 2472 ClassElement element = type.element; |
| 2572 Element helper = helpers.checkSubtype; | 2473 Element helper = helpers.checkSubtype; |
| 2573 HInstruction representations = buildTypeArgumentRepresentations(type); | 2474 HInstruction representations = |
| 2475 typeBuilder.buildTypeArgumentRepresentations(type, sourceElement); |
| 2574 add(representations); | 2476 add(representations); |
| 2575 js.Name operator = backend.namer.operatorIs(element); | 2477 js.Name operator = backend.namer.operatorIs(element); |
| 2576 HInstruction isFieldName = addConstantStringFromName(operator); | 2478 HInstruction isFieldName = addConstantStringFromName(operator); |
| 2577 HInstruction asFieldName = compiler.closedWorld | 2479 HInstruction asFieldName = compiler.closedWorld |
| 2578 .hasAnyStrictSubtype(element) | 2480 .hasAnyStrictSubtype(element) |
| 2579 ? addConstantStringFromName(backend.namer.substitutionName(element)) | 2481 ? addConstantStringFromName(backend.namer.substitutionName(element)) |
| 2580 : graph.addConstantNull(compiler); | 2482 : graph.addConstantNull(compiler); |
| 2581 List<HInstruction> inputs = <HInstruction>[ | 2483 List<HInstruction> inputs = <HInstruction>[ |
| 2582 expression, | 2484 expression, |
| 2583 isFieldName, | 2485 isFieldName, |
| 2584 representations, | 2486 representations, |
| 2585 asFieldName | 2487 asFieldName |
| 2586 ]; | 2488 ]; |
| 2587 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); | 2489 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); |
| 2588 HInstruction call = pop(); | 2490 HInstruction call = pop(); |
| 2589 return new HIs.compound(type, expression, call, backend.boolType); | 2491 return new HIs.compound(type, expression, call, backend.boolType); |
| 2590 } else { | 2492 } else { |
| 2591 if (backend.hasDirectCheckFor(type)) { | 2493 if (backend.hasDirectCheckFor(type)) { |
| 2592 return new HIs.direct(type, expression, backend.boolType); | 2494 return new HIs.direct(type, expression, backend.boolType); |
| 2593 } | 2495 } |
| 2594 // The interceptor is not always needed. It is removed by optimization | 2496 // The interceptor is not always needed. It is removed by optimization |
| 2595 // when the receiver type or tested type permit. | 2497 // when the receiver type or tested type permit. |
| 2596 return new HIs.raw( | 2498 return new HIs.raw( |
| 2597 type, expression, invokeInterceptor(expression), backend.boolType); | 2499 type, expression, invokeInterceptor(expression), backend.boolType); |
| 2598 } | 2500 } |
| 2599 } | 2501 } |
| 2600 | 2502 |
| 2601 HInstruction buildFunctionType(FunctionType type) { | |
| 2602 type.accept(new TypeBuilder(compiler.closedWorld), this); | |
| 2603 return pop(); | |
| 2604 } | |
| 2605 | |
| 2606 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) { | 2503 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) { |
| 2607 CallStructure callStructure = elements.getSelector(node).callStructure; | 2504 CallStructure callStructure = elements.getSelector(node).callStructure; |
| 2608 if (callStructure.namedArgumentCount == 0) { | 2505 if (callStructure.namedArgumentCount == 0) { |
| 2609 addGenericSendArgumentsToList(node.arguments, list); | 2506 addGenericSendArgumentsToList(node.arguments, list); |
| 2610 } else { | 2507 } else { |
| 2611 // Visit positional arguments and add them to the list. | 2508 // Visit positional arguments and add them to the list. |
| 2612 Link<ast.Node> arguments = node.arguments; | 2509 Link<ast.Node> arguments = node.arguments; |
| 2613 int positionalArgumentCount = callStructure.positionalArgumentCount; | 2510 int positionalArgumentCount = callStructure.positionalArgumentCount; |
| 2614 for (int i = 0; | 2511 for (int i = 0; |
| 2615 i < positionalArgumentCount; | 2512 i < positionalArgumentCount; |
| (...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3382 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { | 3279 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { |
| 3383 ClosedWorld closedWorld = compiler.closedWorld; | 3280 ClosedWorld closedWorld = compiler.closedWorld; |
| 3384 if (closedWorld.isUsedAsMixin(cls)) return true; | 3281 if (closedWorld.isUsedAsMixin(cls)) return true; |
| 3385 | 3282 |
| 3386 return compiler.closedWorld.anyStrictSubclassOf(cls, | 3283 return compiler.closedWorld.anyStrictSubclassOf(cls, |
| 3387 (ClassElement subclass) { | 3284 (ClassElement subclass) { |
| 3388 return !rti.isTrivialSubstitution(subclass, cls); | 3285 return !rti.isTrivialSubstitution(subclass, cls); |
| 3389 }); | 3286 }); |
| 3390 } | 3287 } |
| 3391 | 3288 |
| 3392 /** | |
| 3393 * Generate code to extract the type argument from the object. | |
| 3394 */ | |
| 3395 HInstruction readTypeVariable(TypeVariableType variable, | |
| 3396 {SourceInformation sourceInformation}) { | |
| 3397 assert(sourceElement.isInstanceMember); | |
| 3398 assert(variable is! MethodTypeVariableType); | |
| 3399 HInstruction target = localsHandler.readThis(); | |
| 3400 push(new HTypeInfoReadVariable(variable, target, backend.dynamicType) | |
| 3401 ..sourceInformation = sourceInformation); | |
| 3402 return pop(); | |
| 3403 } | |
| 3404 | |
| 3405 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | |
| 3406 // not stored on a type annotation in the closure translator. Remove when | |
| 3407 // fixed. | |
| 3408 bool hasDirectLocal(Local local) { | |
| 3409 return !localsHandler.isAccessedDirectly(local) || | |
| 3410 localsHandler.directLocals[local] != null; | |
| 3411 } | |
| 3412 | |
| 3413 /** | |
| 3414 * Helper to create an instruction that gets the value of a type variable. | |
| 3415 */ | |
| 3416 HInstruction addTypeVariableReference(TypeVariableType type, | |
| 3417 {SourceInformation sourceInformation}) { | |
| 3418 assert(assertTypeInContext(type)); | |
| 3419 if (type is MethodTypeVariableType) { | |
| 3420 return graph.addConstantNull(compiler); | |
| 3421 } | |
| 3422 Element member = sourceElement; | |
| 3423 bool isClosure = member.enclosingElement.isClosure; | |
| 3424 if (isClosure) { | |
| 3425 ClosureClassElement closureClass = member.enclosingElement; | |
| 3426 member = closureClass.methodElement; | |
| 3427 member = member.outermostEnclosingMemberOrTopLevel; | |
| 3428 } | |
| 3429 bool isInConstructorContext = | |
| 3430 member.isConstructor || member.isGenerativeConstructorBody; | |
| 3431 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); | |
| 3432 if (isClosure) { | |
| 3433 if (member.isFactoryConstructor || | |
| 3434 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { | |
| 3435 // The type variable is used from a closure in a factory constructor. | |
| 3436 // The value of the type argument is stored as a local on the closure | |
| 3437 // itself. | |
| 3438 return localsHandler.readLocal(typeVariableLocal, | |
| 3439 sourceInformation: sourceInformation); | |
| 3440 } else if (member.isFunction || | |
| 3441 member.isGetter || | |
| 3442 member.isSetter || | |
| 3443 isInConstructorContext) { | |
| 3444 // The type variable is stored on the "enclosing object" and needs to be | |
| 3445 // accessed using the this-reference in the closure. | |
| 3446 return readTypeVariable(type, sourceInformation: sourceInformation); | |
| 3447 } else { | |
| 3448 assert(member.isField); | |
| 3449 // The type variable is stored in a parameter of the method. | |
| 3450 return localsHandler.readLocal(typeVariableLocal); | |
| 3451 } | |
| 3452 } else if (isInConstructorContext || | |
| 3453 // When [member] is a field, we can be either | |
| 3454 // generating a checked setter or inlining its | |
| 3455 // initializer in a constructor. An initializer is | |
| 3456 // never built standalone, so in that case [target] is not | |
| 3457 // the [member] itself. | |
| 3458 (member.isField && member != target)) { | |
| 3459 // The type variable is stored in a parameter of the method. | |
| 3460 return localsHandler.readLocal(typeVariableLocal, | |
| 3461 sourceInformation: sourceInformation); | |
| 3462 } else if (member.isInstanceMember) { | |
| 3463 // The type variable is stored on the object. | |
| 3464 return readTypeVariable(type, sourceInformation: sourceInformation); | |
| 3465 } else { | |
| 3466 reporter.internalError( | |
| 3467 type.element, 'Unexpected type variable in static context.'); | |
| 3468 return null; | |
| 3469 } | |
| 3470 } | |
| 3471 | |
| 3472 HInstruction analyzeTypeArgument(DartType argument, | |
| 3473 {SourceInformation sourceInformation}) { | |
| 3474 assert(assertTypeInContext(argument)); | |
| 3475 argument = argument.unaliased; | |
| 3476 if (argument.treatAsDynamic) { | |
| 3477 // Represent [dynamic] as [null]. | |
| 3478 return graph.addConstantNull(compiler); | |
| 3479 } | |
| 3480 | |
| 3481 if (argument.isTypeVariable) { | |
| 3482 return addTypeVariableReference(argument, | |
| 3483 sourceInformation: sourceInformation); | |
| 3484 } | |
| 3485 | |
| 3486 List<HInstruction> inputs = <HInstruction>[]; | |
| 3487 argument.forEachTypeVariable((variable) { | |
| 3488 if (variable is! MethodTypeVariableType) { | |
| 3489 inputs.add(analyzeTypeArgument(variable)); | |
| 3490 } | |
| 3491 }); | |
| 3492 HInstruction result = new HTypeInfoExpression( | |
| 3493 TypeInfoExpressionKind.COMPLETE, argument, inputs, backend.dynamicType) | |
| 3494 ..sourceInformation = sourceInformation; | |
| 3495 add(result); | |
| 3496 return result; | |
| 3497 } | |
| 3498 | |
| 3499 HInstruction handleListConstructor( | 3289 HInstruction handleListConstructor( |
| 3500 InterfaceType type, ast.Node currentNode, HInstruction newObject) { | 3290 InterfaceType type, ast.Node currentNode, HInstruction newObject) { |
| 3501 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 3291 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
| 3502 return newObject; | 3292 return newObject; |
| 3503 } | 3293 } |
| 3504 List<HInstruction> inputs = <HInstruction>[]; | 3294 List<HInstruction> inputs = <HInstruction>[]; |
| 3505 type = localsHandler.substInContext(type); | 3295 type = localsHandler.substInContext(type); |
| 3506 type.typeArguments.forEach((DartType argument) { | 3296 type.typeArguments.forEach((DartType argument) { |
| 3507 inputs.add(analyzeTypeArgument(argument)); | 3297 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 3508 }); | 3298 }); |
| 3509 // TODO(15489): Register at codegen. | 3299 // TODO(15489): Register at codegen. |
| 3510 registry?.registerInstantiation(type); | 3300 registry?.registerInstantiation(type); |
| 3511 return callSetRuntimeTypeInfoWithTypeArguments( | 3301 return callSetRuntimeTypeInfoWithTypeArguments( |
| 3512 type.element, inputs, newObject); | 3302 type.element, inputs, newObject); |
| 3513 } | 3303 } |
| 3514 | 3304 |
| 3515 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element, | 3305 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element, |
| 3516 List<HInstruction> rtiInputs, HInstruction newObject) { | 3306 List<HInstruction> rtiInputs, HInstruction newObject) { |
| 3517 if (!backend.classNeedsRti(element)) { | 3307 if (!backend.classNeedsRti(element)) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3745 if (backend.classNeedsRti(coreClasses.listClass) && | 3535 if (backend.classNeedsRti(coreClasses.listClass) && |
| 3746 (isFixedListConstructorCall || | 3536 (isFixedListConstructorCall || |
| 3747 isGrowableListConstructorCall || | 3537 isGrowableListConstructorCall || |
| 3748 isJSArrayTypedConstructor)) { | 3538 isJSArrayTypedConstructor)) { |
| 3749 newInstance = handleListConstructor(type, send, pop()); | 3539 newInstance = handleListConstructor(type, send, pop()); |
| 3750 stack.add(newInstance); | 3540 stack.add(newInstance); |
| 3751 } | 3541 } |
| 3752 | 3542 |
| 3753 // Finally, if we called a redirecting factory constructor, check the type. | 3543 // Finally, if we called a redirecting factory constructor, check the type. |
| 3754 if (isRedirected) { | 3544 if (isRedirected) { |
| 3755 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); | 3545 HInstruction checked = |
| 3546 typeBuilder.potentiallyCheckOrTrustType(newInstance, type); |
| 3756 if (checked != newInstance) { | 3547 if (checked != newInstance) { |
| 3757 pop(); | 3548 pop(); |
| 3758 stack.add(checked); | 3549 stack.add(checked); |
| 3759 } | 3550 } |
| 3760 } | 3551 } |
| 3761 } | 3552 } |
| 3762 | 3553 |
| 3763 void potentiallyAddTypeArguments( | 3554 void potentiallyAddTypeArguments( |
| 3764 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType, | 3555 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType, |
| 3765 {SourceInformation sourceInformation}) { | 3556 {SourceInformation sourceInformation}) { |
| 3766 if (!backend.classNeedsRti(cls)) return; | 3557 if (!backend.classNeedsRti(cls)) return; |
| 3767 assert(cls.typeVariables.length == expectedType.typeArguments.length); | 3558 assert(cls.typeVariables.length == expectedType.typeArguments.length); |
| 3768 expectedType.typeArguments.forEach((DartType argument) { | 3559 expectedType.typeArguments.forEach((DartType argument) { |
| 3769 inputs.add( | 3560 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement, |
| 3770 analyzeTypeArgument(argument, sourceInformation: sourceInformation)); | 3561 sourceInformation: sourceInformation)); |
| 3771 }); | 3562 }); |
| 3772 } | 3563 } |
| 3773 | 3564 |
| 3774 /// In checked mode checks the [type] of [node] to be well-bounded. The method | 3565 /// In checked mode checks the [type] of [node] to be well-bounded. The method |
| 3775 /// returns [:true:] if an error can be statically determined. | 3566 /// returns [:true:] if an error can be statically determined. |
| 3776 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { | 3567 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { |
| 3777 if (!compiler.options.enableTypeAssertions) return false; | 3568 if (!compiler.options.enableTypeAssertions) return false; |
| 3778 | 3569 |
| 3779 Map<DartType, Set<DartType>> seenChecksMap = | 3570 Map<DartType, Set<DartType>> seenChecksMap = |
| 3780 new Map<DartType, Set<DartType>>(); | 3571 new Map<DartType, Set<DartType>>(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4032 /// Generate the literal for [typeVariable] in the current context. | 3823 /// Generate the literal for [typeVariable] in the current context. |
| 4033 void generateTypeVariableLiteral( | 3824 void generateTypeVariableLiteral( |
| 4034 ast.Send node, TypeVariableType typeVariable) { | 3825 ast.Send node, TypeVariableType typeVariable) { |
| 4035 // GENERIC_METHODS: This provides thin support for method type variables | 3826 // GENERIC_METHODS: This provides thin support for method type variables |
| 4036 // by treating them as malformed when evaluated as a literal. For full | 3827 // by treating them as malformed when evaluated as a literal. For full |
| 4037 // support of generic methods this must be revised. | 3828 // support of generic methods this must be revised. |
| 4038 if (typeVariable is MethodTypeVariableType) { | 3829 if (typeVariable is MethodTypeVariableType) { |
| 4039 generateTypeError(node, "Method type variables are not reified"); | 3830 generateTypeError(node, "Method type variables are not reified"); |
| 4040 } else { | 3831 } else { |
| 4041 DartType type = localsHandler.substInContext(typeVariable); | 3832 DartType type = localsHandler.substInContext(typeVariable); |
| 4042 HInstruction value = analyzeTypeArgument(type, | 3833 HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement, |
| 4043 sourceInformation: sourceInformationBuilder.buildGet(node)); | 3834 sourceInformation: sourceInformationBuilder.buildGet(node)); |
| 4044 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], | 3835 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], |
| 4045 typeMask: backend.stringType); | 3836 typeMask: backend.stringType); |
| 4046 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); | 3837 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); |
| 4047 } | 3838 } |
| 4048 } | 3839 } |
| 4049 | 3840 |
| 4050 /// Generate a call to a type literal. | 3841 /// Generate a call to a type literal. |
| 4051 void generateTypeLiteralCall(ast.Send node) { | 3842 void generateTypeLiteralCall(ast.Send node) { |
| 4052 // This send is of the form 'e(...)', where e is resolved to a type | 3843 // This send is of the form 'e(...)', where e is resolved to a type |
| (...skipping 1305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5358 } | 5149 } |
| 5359 } | 5150 } |
| 5360 | 5151 |
| 5361 ClassElement targetClass = targetConstructor.enclosingClass; | 5152 ClassElement targetClass = targetConstructor.enclosingClass; |
| 5362 if (backend.classNeedsRti(targetClass)) { | 5153 if (backend.classNeedsRti(targetClass)) { |
| 5363 ClassElement cls = redirectingConstructor.enclosingClass; | 5154 ClassElement cls = redirectingConstructor.enclosingClass; |
| 5364 InterfaceType targetType = | 5155 InterfaceType targetType = |
| 5365 redirectingConstructor.computeEffectiveTargetType(cls.thisType); | 5156 redirectingConstructor.computeEffectiveTargetType(cls.thisType); |
| 5366 targetType = localsHandler.substInContext(targetType); | 5157 targetType = localsHandler.substInContext(targetType); |
| 5367 targetType.typeArguments.forEach((DartType argument) { | 5158 targetType.typeArguments.forEach((DartType argument) { |
| 5368 inputs.add(analyzeTypeArgument(argument)); | 5159 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 5369 }); | 5160 }); |
| 5370 } | 5161 } |
| 5371 pushInvokeStatic(node, targetConstructor.declaration, inputs); | 5162 pushInvokeStatic(node, targetConstructor.declaration, inputs); |
| 5372 HInstruction value = pop(); | 5163 HInstruction value = pop(); |
| 5373 emitReturn(value, node); | 5164 emitReturn(value, node); |
| 5374 } | 5165 } |
| 5375 | 5166 |
| 5376 /// Returns true if the [type] is a valid return type for an asynchronous | 5167 /// Returns true if the [type] is a valid return type for an asynchronous |
| 5377 /// function. | 5168 /// function. |
| 5378 /// | 5169 /// |
| (...skipping 29 matching lines...) Expand all Loading... |
| 5408 if (isBuildingAsyncFunction) { | 5199 if (isBuildingAsyncFunction) { |
| 5409 if (compiler.options.enableTypeAssertions && | 5200 if (compiler.options.enableTypeAssertions && |
| 5410 !isValidAsyncReturnType(returnType)) { | 5201 !isValidAsyncReturnType(returnType)) { |
| 5411 String message = "Async function returned a Future, " | 5202 String message = "Async function returned a Future, " |
| 5412 "was declared to return a $returnType."; | 5203 "was declared to return a $returnType."; |
| 5413 generateTypeError(node, message); | 5204 generateTypeError(node, message); |
| 5414 pop(); | 5205 pop(); |
| 5415 return; | 5206 return; |
| 5416 } | 5207 } |
| 5417 } else { | 5208 } else { |
| 5418 value = potentiallyCheckOrTrustType(value, returnType); | 5209 value = typeBuilder.potentiallyCheckOrTrustType(value, returnType); |
| 5419 } | 5210 } |
| 5420 } | 5211 } |
| 5421 | 5212 |
| 5422 handleInTryStatement(); | 5213 handleInTryStatement(); |
| 5423 emitReturn(value, node); | 5214 emitReturn(value, node); |
| 5424 } | 5215 } |
| 5425 | 5216 |
| 5426 visitThrow(ast.Throw node) { | 5217 visitThrow(ast.Throw node) { |
| 5427 visitThrowExpression(node.expression); | 5218 visitThrowExpression(node.expression); |
| 5428 if (isReachable) { | 5219 if (isReachable) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5470 } | 5261 } |
| 5471 } | 5262 } |
| 5472 | 5263 |
| 5473 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { | 5264 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { |
| 5474 InterfaceType type = localsHandler.substInContext(elements.getType(node)); | 5265 InterfaceType type = localsHandler.substInContext(elements.getType(node)); |
| 5475 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 5266 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
| 5476 return object; | 5267 return object; |
| 5477 } | 5268 } |
| 5478 List<HInstruction> arguments = <HInstruction>[]; | 5269 List<HInstruction> arguments = <HInstruction>[]; |
| 5479 for (DartType argument in type.typeArguments) { | 5270 for (DartType argument in type.typeArguments) { |
| 5480 arguments.add(analyzeTypeArgument(argument)); | 5271 arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 5481 } | 5272 } |
| 5482 // TODO(15489): Register at codegen. | 5273 // TODO(15489): Register at codegen. |
| 5483 registry?.registerInstantiation(type); | 5274 registry?.registerInstantiation(type); |
| 5484 return callSetRuntimeTypeInfoWithTypeArguments( | 5275 return callSetRuntimeTypeInfoWithTypeArguments( |
| 5485 type.element, arguments, object); | 5276 type.element, arguments, object); |
| 5486 } | 5277 } |
| 5487 | 5278 |
| 5488 visitLiteralList(ast.LiteralList node) { | 5279 visitLiteralList(ast.LiteralList node) { |
| 5489 HInstruction instruction; | 5280 HInstruction instruction; |
| 5490 | 5281 |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5918 InterfaceType type = elements.getType(node); | 5709 InterfaceType type = elements.getType(node); |
| 5919 InterfaceType expectedType = | 5710 InterfaceType expectedType = |
| 5920 functionElement.computeEffectiveTargetType(type); | 5711 functionElement.computeEffectiveTargetType(type); |
| 5921 expectedType = localsHandler.substInContext(expectedType); | 5712 expectedType = localsHandler.substInContext(expectedType); |
| 5922 | 5713 |
| 5923 ClassElement cls = constructor.enclosingClass; | 5714 ClassElement cls = constructor.enclosingClass; |
| 5924 | 5715 |
| 5925 if (backend.classNeedsRti(cls)) { | 5716 if (backend.classNeedsRti(cls)) { |
| 5926 List<HInstruction> typeInputs = <HInstruction>[]; | 5717 List<HInstruction> typeInputs = <HInstruction>[]; |
| 5927 expectedType.typeArguments.forEach((DartType argument) { | 5718 expectedType.typeArguments.forEach((DartType argument) { |
| 5928 typeInputs.add(analyzeTypeArgument(argument)); | 5719 typeInputs |
| 5720 .add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 5929 }); | 5721 }); |
| 5930 | 5722 |
| 5931 // We lift this common call pattern into a helper function to save space | 5723 // We lift this common call pattern into a helper function to save space |
| 5932 // in the output. | 5724 // in the output. |
| 5933 if (typeInputs.every((HInstruction input) => input.isNull())) { | 5725 if (typeInputs.every((HInstruction input) => input.isNull())) { |
| 5934 if (listInputs.isEmpty) { | 5726 if (listInputs.isEmpty) { |
| 5935 constructor = helpers.mapLiteralUntypedEmptyMaker; | 5727 constructor = helpers.mapLiteralUntypedEmptyMaker; |
| 5936 } else { | 5728 } else { |
| 5937 constructor = helpers.mapLiteralUntypedMaker; | 5729 constructor = helpers.mapLiteralUntypedMaker; |
| 5938 } | 5730 } |
| (...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6995 this.oldReturnLocal, | 6787 this.oldReturnLocal, |
| 6996 this.oldReturnType, | 6788 this.oldReturnType, |
| 6997 this.oldResolvedAst, | 6789 this.oldResolvedAst, |
| 6998 this.oldStack, | 6790 this.oldStack, |
| 6999 this.oldLocalsHandler, | 6791 this.oldLocalsHandler, |
| 7000 this.inTryStatement, | 6792 this.inTryStatement, |
| 7001 this.allFunctionsCalledOnce, | 6793 this.allFunctionsCalledOnce, |
| 7002 this.oldElementInferenceResults) | 6794 this.oldElementInferenceResults) |
| 7003 : super(function); | 6795 : super(function); |
| 7004 } | 6796 } |
| 7005 | |
| 7006 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { | |
| 7007 final ClosedWorld closedWorld; | |
| 7008 | |
| 7009 TypeBuilder(this.closedWorld); | |
| 7010 | |
| 7011 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder); | |
| 7012 | |
| 7013 void visitVoidType(VoidType type, SsaBuilder builder) { | |
| 7014 ClassElement cls = builder.backend.helpers.VoidRuntimeType; | |
| 7015 builder.push(new HVoidType(type, new TypeMask.exact(cls, closedWorld))); | |
| 7016 } | |
| 7017 | |
| 7018 void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) { | |
| 7019 ClassElement cls = builder.backend.helpers.RuntimeType; | |
| 7020 TypeMask instructionType = new TypeMask.subclass(cls, closedWorld); | |
| 7021 if (!builder.sourceElement.enclosingElement.isClosure && | |
| 7022 builder.sourceElement.isInstanceMember) { | |
| 7023 HInstruction receiver = builder.localsHandler.readThis(); | |
| 7024 builder.push(new HReadTypeVariable(type, receiver, instructionType)); | |
| 7025 } else { | |
| 7026 builder.push(new HReadTypeVariable.noReceiver( | |
| 7027 type, builder.addTypeVariableReference(type), instructionType)); | |
| 7028 } | |
| 7029 } | |
| 7030 | |
| 7031 void visitFunctionType(FunctionType type, SsaBuilder builder) { | |
| 7032 type.returnType.accept(this, builder); | |
| 7033 HInstruction returnType = builder.pop(); | |
| 7034 List<HInstruction> inputs = <HInstruction>[returnType]; | |
| 7035 | |
| 7036 for (DartType parameter in type.parameterTypes) { | |
| 7037 parameter.accept(this, builder); | |
| 7038 inputs.add(builder.pop()); | |
| 7039 } | |
| 7040 | |
| 7041 for (DartType parameter in type.optionalParameterTypes) { | |
| 7042 parameter.accept(this, builder); | |
| 7043 inputs.add(builder.pop()); | |
| 7044 } | |
| 7045 | |
| 7046 List<DartType> namedParameterTypes = type.namedParameterTypes; | |
| 7047 List<String> names = type.namedParameters; | |
| 7048 for (int index = 0; index < names.length; index++) { | |
| 7049 ast.DartString dartString = new ast.DartString.literal(names[index]); | |
| 7050 inputs.add(builder.graph.addConstantString(dartString, builder.compiler)); | |
| 7051 namedParameterTypes[index].accept(this, builder); | |
| 7052 inputs.add(builder.pop()); | |
| 7053 } | |
| 7054 | |
| 7055 ClassElement cls = builder.backend.helpers.RuntimeFunctionType; | |
| 7056 builder.push( | |
| 7057 new HFunctionType(inputs, type, new TypeMask.exact(cls, closedWorld))); | |
| 7058 } | |
| 7059 | |
| 7060 void visitMalformedType(MalformedType type, SsaBuilder builder) { | |
| 7061 visitDynamicType(const DynamicType(), builder); | |
| 7062 } | |
| 7063 | |
| 7064 void visitStatementType(StatementType type, SsaBuilder builder) { | |
| 7065 throw 'not implemented visitStatementType($type)'; | |
| 7066 } | |
| 7067 | |
| 7068 void visitInterfaceType(InterfaceType type, SsaBuilder builder) { | |
| 7069 List<HInstruction> inputs = <HInstruction>[]; | |
| 7070 for (DartType typeArgument in type.typeArguments) { | |
| 7071 typeArgument.accept(this, builder); | |
| 7072 inputs.add(builder.pop()); | |
| 7073 } | |
| 7074 ClassElement cls; | |
| 7075 if (type.typeArguments.isEmpty) { | |
| 7076 cls = builder.backend.helpers.RuntimeTypePlain; | |
| 7077 } else { | |
| 7078 cls = builder.backend.helpers.RuntimeTypeGeneric; | |
| 7079 } | |
| 7080 builder.push( | |
| 7081 new HInterfaceType(inputs, type, new TypeMask.exact(cls, closedWorld))); | |
| 7082 } | |
| 7083 | |
| 7084 void visitTypedefType(TypedefType type, SsaBuilder builder) { | |
| 7085 DartType unaliased = type.unaliased; | |
| 7086 if (unaliased is TypedefType) throw 'unable to unalias $type'; | |
| 7087 unaliased.accept(this, builder); | |
| 7088 } | |
| 7089 | |
| 7090 void visitDynamicType(DynamicType type, SsaBuilder builder) { | |
| 7091 JavaScriptBackend backend = builder.compiler.backend; | |
| 7092 ClassElement cls = backend.helpers.DynamicRuntimeType; | |
| 7093 builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld))); | |
| 7094 } | |
| 7095 } | |
| OLD | NEW |