| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
| 8 | 8 |
| 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 void markAsInlinable(FunctionElement element, {bool insideLoop}) { | 100 void markAsInlinable(FunctionElement element, {bool insideLoop}) { |
| 101 int oldDecision = _cachedDecisions[element]; | 101 int oldDecision = _cachedDecisions[element]; |
| 102 | 102 |
| 103 if (oldDecision == null) { | 103 if (oldDecision == null) { |
| 104 oldDecision = _unknown; | 104 oldDecision = _unknown; |
| 105 } | 105 } |
| 106 | 106 |
| 107 if (insideLoop) { | 107 if (insideLoop) { |
| 108 switch (oldDecision) { | 108 switch (oldDecision) { |
| 109 case _mustNotInline: | 109 case _mustNotInline: |
| 110 throw new SpannableAssertionFailure(element, | 110 throw new SpannableAssertionFailure( |
| 111 element, |
| 111 "Can't mark a function as non-inlinable and inlinable at the " | 112 "Can't mark a function as non-inlinable and inlinable at the " |
| 112 "same time."); | 113 "same time."); |
| 113 | 114 |
| 114 case _unknown: | 115 case _unknown: |
| 115 // We know that it can be inlined in a loop, but don't know about the | 116 // We know that it can be inlined in a loop, but don't know about the |
| 116 // non-loop case yet. | 117 // non-loop case yet. |
| 117 _cachedDecisions[element] = _canInlineInLoopMayInlineOutside; | 118 _cachedDecisions[element] = _canInlineInLoopMayInlineOutside; |
| 118 break; | 119 break; |
| 119 | 120 |
| 120 case _mayInlineInLoopMustNotOutside: | 121 case _mayInlineInLoopMustNotOutside: |
| 121 _cachedDecisions[element] = _canInlineInLoopMustNotOutside; | 122 _cachedDecisions[element] = _canInlineInLoopMustNotOutside; |
| 122 break; | 123 break; |
| 123 | 124 |
| 124 case _canInlineInLoopMustNotOutside: | 125 case _canInlineInLoopMustNotOutside: |
| 125 case _canInlineInLoopMayInlineOutside: | 126 case _canInlineInLoopMayInlineOutside: |
| 126 case _canInline: | 127 case _canInline: |
| 127 case _mustInline: | 128 case _mustInline: |
| 128 // Do nothing. | 129 // Do nothing. |
| 129 break; | 130 break; |
| 130 } | 131 } |
| 131 } else { | 132 } else { |
| 132 switch (oldDecision) { | 133 switch (oldDecision) { |
| 133 case _mustNotInline: | 134 case _mustNotInline: |
| 134 case _mayInlineInLoopMustNotOutside: | 135 case _mayInlineInLoopMustNotOutside: |
| 135 case _canInlineInLoopMustNotOutside: | 136 case _canInlineInLoopMustNotOutside: |
| 136 throw new SpannableAssertionFailure(element, | 137 throw new SpannableAssertionFailure( |
| 138 element, |
| 137 "Can't mark a function as non-inlinable and inlinable at the " | 139 "Can't mark a function as non-inlinable and inlinable at the " |
| 138 "same time."); | 140 "same time."); |
| 139 | 141 |
| 140 case _unknown: | 142 case _unknown: |
| 141 case _canInlineInLoopMayInlineOutside: | 143 case _canInlineInLoopMayInlineOutside: |
| 142 _cachedDecisions[element] = _canInline; | 144 _cachedDecisions[element] = _canInline; |
| 143 break; | 145 break; |
| 144 | 146 |
| 145 case _canInline: | 147 case _canInline: |
| 146 case _mustInline: | 148 case _mustInline: |
| 147 // Do nothing. | 149 // Do nothing. |
| 148 break; | 150 break; |
| 149 | |
| 150 } | 151 } |
| 151 } | 152 } |
| 152 } | 153 } |
| 153 | 154 |
| 154 void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) { | 155 void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) { |
| 155 int oldDecision = _cachedDecisions[element]; | 156 int oldDecision = _cachedDecisions[element]; |
| 156 | 157 |
| 157 if (oldDecision == null) { | 158 if (oldDecision == null) { |
| 158 oldDecision = _unknown; | 159 oldDecision = _unknown; |
| 159 } | 160 } |
| 160 | 161 |
| 161 if (insideLoop) { | 162 if (insideLoop) { |
| 162 switch (oldDecision) { | 163 switch (oldDecision) { |
| 163 case _canInlineInLoopMustNotOutside: | 164 case _canInlineInLoopMustNotOutside: |
| 164 case _canInlineInLoopMayInlineOutside: | 165 case _canInlineInLoopMayInlineOutside: |
| 165 case _canInline: | 166 case _canInline: |
| 166 case _mustInline: | 167 case _mustInline: |
| 167 throw new SpannableAssertionFailure(element, | 168 throw new SpannableAssertionFailure( |
| 169 element, |
| 168 "Can't mark a function as non-inlinable and inlinable at the " | 170 "Can't mark a function as non-inlinable and inlinable at the " |
| 169 "same time."); | 171 "same time."); |
| 170 | 172 |
| 171 case _mayInlineInLoopMustNotOutside: | 173 case _mayInlineInLoopMustNotOutside: |
| 172 case _unknown: | 174 case _unknown: |
| 173 _cachedDecisions[element] = _mustNotInline; | 175 _cachedDecisions[element] = _mustNotInline; |
| 174 break; | 176 break; |
| 175 | 177 |
| 176 case _mustNotInline: | 178 case _mustNotInline: |
| 177 // Do nothing. | 179 // Do nothing. |
| 178 break; | 180 break; |
| 179 } | 181 } |
| 180 } else { | 182 } else { |
| 181 switch (oldDecision) { | 183 switch (oldDecision) { |
| 182 case _canInline: | 184 case _canInline: |
| 183 case _mustInline: | 185 case _mustInline: |
| 184 throw new SpannableAssertionFailure(element, | 186 throw new SpannableAssertionFailure( |
| 187 element, |
| 185 "Can't mark a function as non-inlinable and inlinable at the " | 188 "Can't mark a function as non-inlinable and inlinable at the " |
| 186 "same time."); | 189 "same time."); |
| 187 | 190 |
| 188 case _unknown: | 191 case _unknown: |
| 189 // We can't inline outside a loop, but we might still be allowed to do | 192 // We can't inline outside a loop, but we might still be allowed to do |
| 190 // so outside. | 193 // so outside. |
| 191 _cachedDecisions[element] = _mayInlineInLoopMustNotOutside; | 194 _cachedDecisions[element] = _mayInlineInLoopMustNotOutside; |
| 192 break; | 195 break; |
| 193 | 196 |
| 194 case _canInlineInLoopMayInlineOutside: | 197 case _canInlineInLoopMayInlineOutside: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 208 } | 211 } |
| 209 | 212 |
| 210 void markAsMustInline(FunctionElement element) { | 213 void markAsMustInline(FunctionElement element) { |
| 211 _cachedDecisions[element] = _mustInline; | 214 _cachedDecisions[element] = _mustInline; |
| 212 } | 215 } |
| 213 } | 216 } |
| 214 | 217 |
| 215 enum SyntheticConstantKind { | 218 enum SyntheticConstantKind { |
| 216 DUMMY_INTERCEPTOR, | 219 DUMMY_INTERCEPTOR, |
| 217 EMPTY_VALUE, | 220 EMPTY_VALUE, |
| 218 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. | 221 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. |
| 219 NAME | 222 NAME |
| 220 } | 223 } |
| 221 | 224 |
| 222 class JavaScriptBackend extends Backend { | 225 class JavaScriptBackend extends Backend { |
| 223 String get patchVersion => emitter.patchVersion; | 226 String get patchVersion => emitter.patchVersion; |
| 224 | 227 |
| 225 bool get supportsReflection => emitter.emitter.supportsReflection; | 228 bool get supportsReflection => emitter.emitter.supportsReflection; |
| 226 | 229 |
| 227 final Annotations annotations; | 230 final Annotations annotations; |
| 228 | 231 |
| 229 | |
| 230 /// Set of classes that need to be considered for reflection although not | 232 /// Set of classes that need to be considered for reflection although not |
| 231 /// otherwise visible during resolution. | 233 /// otherwise visible during resolution. |
| 232 Iterable<ClassElement> get classesRequiredForReflection { | 234 Iterable<ClassElement> get classesRequiredForReflection { |
| 233 // TODO(herhut): Clean this up when classes needed for rti are tracked. | 235 // TODO(herhut): Clean this up when classes needed for rti are tracked. |
| 234 return [helpers.closureClass, helpers.jsIndexableClass]; | 236 return [helpers.closureClass, helpers.jsIndexableClass]; |
| 235 } | 237 } |
| 236 | 238 |
| 237 FunctionCompiler functionCompiler; | 239 FunctionCompiler functionCompiler; |
| 238 | 240 |
| 239 CodeEmitterTask emitter; | 241 CodeEmitterTask emitter; |
| 240 | 242 |
| 241 /** | 243 /** |
| 242 * The generated code as a js AST for compiled methods. | 244 * The generated code as a js AST for compiled methods. |
| 243 */ | 245 */ |
| 244 Map<Element, jsAst.Expression> get generatedCode { | 246 Map<Element, jsAst.Expression> get generatedCode { |
| 245 return compiler.enqueuer.codegen.generatedCode; | 247 return compiler.enqueuer.codegen.generatedCode; |
| 246 } | 248 } |
| 247 | 249 |
| 248 FunctionInlineCache inlineCache = new FunctionInlineCache(); | 250 FunctionInlineCache inlineCache = new FunctionInlineCache(); |
| 249 | 251 |
| 250 /// If [true], the compiler will emit code that logs whenever a method is | 252 /// If [true], the compiler will emit code that logs whenever a method is |
| 251 /// called. When TRACE_METHOD is 'console' this will be logged | 253 /// called. When TRACE_METHOD is 'console' this will be logged |
| 252 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the | 254 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the |
| 253 /// information will be sent to a server via a POST request. | 255 /// information will be sent to a server via a POST request. |
| 254 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); | 256 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); |
| 255 static const bool TRACE_CALLS = | 257 static const bool TRACE_CALLS = |
| 256 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; | 258 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; |
| 257 Element traceHelper; | 259 Element traceHelper; |
| 258 | 260 |
| 259 TypeMask get stringType => compiler.typesTask.stringType; | 261 TypeMask get stringType => compiler.typesTask.stringType; |
| 260 TypeMask get doubleType => compiler.typesTask.doubleType; | 262 TypeMask get doubleType => compiler.typesTask.doubleType; |
| 261 TypeMask get intType => compiler.typesTask.intType; | 263 TypeMask get intType => compiler.typesTask.intType; |
| 262 TypeMask get uint32Type => compiler.typesTask.uint32Type; | 264 TypeMask get uint32Type => compiler.typesTask.uint32Type; |
| 263 TypeMask get uint31Type => compiler.typesTask.uint31Type; | 265 TypeMask get uint31Type => compiler.typesTask.uint31Type; |
| 264 TypeMask get positiveIntType => compiler.typesTask.positiveIntType; | 266 TypeMask get positiveIntType => compiler.typesTask.positiveIntType; |
| 265 TypeMask get numType => compiler.typesTask.numType; | 267 TypeMask get numType => compiler.typesTask.numType; |
| 266 TypeMask get boolType => compiler.typesTask.boolType; | 268 TypeMask get boolType => compiler.typesTask.boolType; |
| 267 TypeMask get dynamicType => compiler.typesTask.dynamicType; | 269 TypeMask get dynamicType => compiler.typesTask.dynamicType; |
| 268 TypeMask get nullType => compiler.typesTask.nullType; | 270 TypeMask get nullType => compiler.typesTask.nullType; |
| 269 TypeMask get emptyType => const TypeMask.nonNullEmpty(); | 271 TypeMask get emptyType => const TypeMask.nonNullEmpty(); |
| 270 | 272 |
| 271 TypeMask _indexablePrimitiveTypeCache; | 273 TypeMask _indexablePrimitiveTypeCache; |
| 272 TypeMask get indexablePrimitiveType { | 274 TypeMask get indexablePrimitiveType { |
| 273 if (_indexablePrimitiveTypeCache == null) { | 275 if (_indexablePrimitiveTypeCache == null) { |
| 274 _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype( | 276 _indexablePrimitiveTypeCache = |
| 275 helpers.jsIndexableClass, compiler.world); | 277 new TypeMask.nonNullSubtype(helpers.jsIndexableClass, compiler.world); |
| 276 } | 278 } |
| 277 return _indexablePrimitiveTypeCache; | 279 return _indexablePrimitiveTypeCache; |
| 278 } | 280 } |
| 279 | 281 |
| 280 TypeMask _readableArrayTypeCache; | 282 TypeMask _readableArrayTypeCache; |
| 281 TypeMask get readableArrayType { | 283 TypeMask get readableArrayType { |
| 282 if (_readableArrayTypeCache == null) { | 284 if (_readableArrayTypeCache == null) { |
| 283 _readableArrayTypeCache = new TypeMask.nonNullSubclass( | 285 _readableArrayTypeCache = |
| 284 helpers.jsArrayClass, compiler.world); | 286 new TypeMask.nonNullSubclass(helpers.jsArrayClass, compiler.world); |
| 285 } | 287 } |
| 286 return _readableArrayTypeCache; | 288 return _readableArrayTypeCache; |
| 287 } | 289 } |
| 288 | 290 |
| 289 TypeMask _mutableArrayTypeCache; | 291 TypeMask _mutableArrayTypeCache; |
| 290 TypeMask get mutableArrayType { | 292 TypeMask get mutableArrayType { |
| 291 if (_mutableArrayTypeCache == null) { | 293 if (_mutableArrayTypeCache == null) { |
| 292 _mutableArrayTypeCache = new TypeMask.nonNullSubclass( | 294 _mutableArrayTypeCache = new TypeMask.nonNullSubclass( |
| 293 helpers.jsMutableArrayClass, compiler.world); | 295 helpers.jsMutableArrayClass, compiler.world); |
| 294 } | 296 } |
| 295 return _mutableArrayTypeCache; | 297 return _mutableArrayTypeCache; |
| 296 } | 298 } |
| 297 | 299 |
| 298 TypeMask _fixedArrayTypeCache; | 300 TypeMask _fixedArrayTypeCache; |
| 299 TypeMask get fixedArrayType { | 301 TypeMask get fixedArrayType { |
| 300 if (_fixedArrayTypeCache == null) { | 302 if (_fixedArrayTypeCache == null) { |
| 301 _fixedArrayTypeCache = new TypeMask.nonNullExact( | 303 _fixedArrayTypeCache = |
| 302 helpers.jsFixedArrayClass, compiler.world); | 304 new TypeMask.nonNullExact(helpers.jsFixedArrayClass, compiler.world); |
| 303 } | 305 } |
| 304 return _fixedArrayTypeCache; | 306 return _fixedArrayTypeCache; |
| 305 } | 307 } |
| 306 | 308 |
| 307 TypeMask _extendableArrayTypeCache; | 309 TypeMask _extendableArrayTypeCache; |
| 308 TypeMask get extendableArrayType { | 310 TypeMask get extendableArrayType { |
| 309 if (_extendableArrayTypeCache == null) { | 311 if (_extendableArrayTypeCache == null) { |
| 310 _extendableArrayTypeCache = new TypeMask.nonNullExact( | 312 _extendableArrayTypeCache = new TypeMask.nonNullExact( |
| 311 helpers.jsExtendableArrayClass, compiler.world); | 313 helpers.jsExtendableArrayClass, compiler.world); |
| 312 } | 314 } |
| 313 return _extendableArrayTypeCache; | 315 return _extendableArrayTypeCache; |
| 314 } | 316 } |
| 315 | 317 |
| 316 TypeMask _unmodifiableArrayTypeCache; | 318 TypeMask _unmodifiableArrayTypeCache; |
| 317 TypeMask get unmodifiableArrayType { | 319 TypeMask get unmodifiableArrayType { |
| 318 if (_unmodifiableArrayTypeCache == null) { | 320 if (_unmodifiableArrayTypeCache == null) { |
| 319 _unmodifiableArrayTypeCache = new TypeMask.nonNullExact( | 321 _unmodifiableArrayTypeCache = new TypeMask.nonNullExact( |
| 320 helpers.jsUnmodifiableArrayClass, compiler.world); | 322 helpers.jsUnmodifiableArrayClass, compiler.world); |
| 321 } | 323 } |
| 322 return _fixedArrayTypeCache; | 324 return _fixedArrayTypeCache; |
| 323 } | 325 } |
| 324 | 326 |
| 325 TypeMask _nonNullTypeCache; | 327 TypeMask _nonNullTypeCache; |
| 326 TypeMask get nonNullType { | 328 TypeMask get nonNullType { |
| 327 if (_nonNullTypeCache == null) { | 329 if (_nonNullTypeCache == null) { |
| 328 _nonNullTypeCache = | 330 _nonNullTypeCache = compiler.typesTask.dynamicType.nonNullable(); |
| 329 compiler.typesTask.dynamicType.nonNullable(); | |
| 330 } | 331 } |
| 331 return _nonNullTypeCache; | 332 return _nonNullTypeCache; |
| 332 } | 333 } |
| 333 | 334 |
| 334 /// Maps special classes to their implementation (JSXxx) class. | 335 /// Maps special classes to their implementation (JSXxx) class. |
| 335 Map<ClassElement, ClassElement> implementationClasses; | 336 Map<ClassElement, ClassElement> implementationClasses; |
| 336 | 337 |
| 337 bool needToInitializeIsolateAffinityTag = false; | 338 bool needToInitializeIsolateAffinityTag = false; |
| 338 bool needToInitializeDispatchProperty = false; | 339 bool needToInitializeDispatchProperty = false; |
| 339 | 340 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 final Set<String> symbolsUsed = new Set<String>(); | 466 final Set<String> symbolsUsed = new Set<String>(); |
| 466 | 467 |
| 467 /// List of elements that the backend may use. | 468 /// List of elements that the backend may use. |
| 468 final Set<Element> helpersUsed = new Set<Element>(); | 469 final Set<Element> helpersUsed = new Set<Element>(); |
| 469 | 470 |
| 470 /// All the checked mode helpers. | 471 /// All the checked mode helpers. |
| 471 static const checkedModeHelpers = CheckedModeHelper.helpers; | 472 static const checkedModeHelpers = CheckedModeHelper.helpers; |
| 472 | 473 |
| 473 // Checked mode helpers indexed by name. | 474 // Checked mode helpers indexed by name. |
| 474 Map<String, CheckedModeHelper> checkedModeHelperByName = | 475 Map<String, CheckedModeHelper> checkedModeHelperByName = |
| 475 new Map<String, CheckedModeHelper>.fromIterable( | 476 new Map<String, CheckedModeHelper>.fromIterable(checkedModeHelpers, |
| 476 checkedModeHelpers, | |
| 477 key: (helper) => helper.name); | 477 key: (helper) => helper.name); |
| 478 | 478 |
| 479 TypeVariableHandler typeVariableHandler; | 479 TypeVariableHandler typeVariableHandler; |
| 480 | 480 |
| 481 /// Number of methods compiled before considering reflection. | 481 /// Number of methods compiled before considering reflection. |
| 482 int preMirrorsMethodCount = 0; | 482 int preMirrorsMethodCount = 0; |
| 483 | 483 |
| 484 /// Resolution and codegen support for generating table of interceptors and | 484 /// Resolution and codegen support for generating table of interceptors and |
| 485 /// constructors for custom elements. | 485 /// constructors for custom elements. |
| 486 CustomElementsAnalysis customElementsAnalysis; | 486 CustomElementsAnalysis customElementsAnalysis; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 505 SourceInformationStrategy sourceInformationStrategy; | 505 SourceInformationStrategy sourceInformationStrategy; |
| 506 | 506 |
| 507 JavaScriptBackendSerialization serialization; | 507 JavaScriptBackendSerialization serialization; |
| 508 | 508 |
| 509 final NativeData nativeData = new NativeData(); | 509 final NativeData nativeData = new NativeData(); |
| 510 | 510 |
| 511 final BackendHelpers helpers; | 511 final BackendHelpers helpers; |
| 512 final BackendImpacts impacts; | 512 final BackendImpacts impacts; |
| 513 | 513 |
| 514 JavaScriptBackend(Compiler compiler, | 514 JavaScriptBackend(Compiler compiler, |
| 515 {bool generateSourceMap: true, | 515 {bool generateSourceMap: true, |
| 516 bool useStartupEmitter: false, | 516 bool useStartupEmitter: false, |
| 517 bool useNewSourceInfo: false}) | 517 bool useNewSourceInfo: false}) |
| 518 : namer = determineNamer(compiler), | 518 : namer = determineNamer(compiler), |
| 519 oneShotInterceptors = new Map<jsAst.Name, Selector>(), | 519 oneShotInterceptors = new Map<jsAst.Name, Selector>(), |
| 520 interceptedElements = new Map<String, Set<Element>>(), | 520 interceptedElements = new Map<String, Set<Element>>(), |
| 521 rti = new _RuntimeTypes(compiler), | 521 rti = new _RuntimeTypes(compiler), |
| 522 rtiEncoder = new _RuntimeTypesEncoder(compiler), | 522 rtiEncoder = new _RuntimeTypesEncoder(compiler), |
| 523 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), | 523 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), |
| 524 annotations = new Annotations(compiler), | 524 annotations = new Annotations(compiler), |
| 525 this.sourceInformationStrategy = | 525 this.sourceInformationStrategy = generateSourceMap |
| 526 generateSourceMap | 526 ? (useNewSourceInfo |
| 527 ? (useNewSourceInfo | 527 ? new PositionSourceInformationStrategy() |
| 528 ? new PositionSourceInformationStrategy() | 528 : const StartEndSourceInformationStrategy()) |
| 529 : const StartEndSourceInformationStrategy()) | 529 : const JavaScriptSourceInformationStrategy(), |
| 530 : const JavaScriptSourceInformationStrategy(), | |
| 531 helpers = new BackendHelpers(compiler), | 530 helpers = new BackendHelpers(compiler), |
| 532 impacts = new BackendImpacts(compiler), | 531 impacts = new BackendImpacts(compiler), |
| 533 super(compiler) { | 532 super(compiler) { |
| 534 emitter = new CodeEmitterTask( | 533 emitter = new CodeEmitterTask( |
| 535 compiler, namer, generateSourceMap, useStartupEmitter); | 534 compiler, namer, generateSourceMap, useStartupEmitter); |
| 536 typeVariableHandler = new TypeVariableHandler(compiler); | 535 typeVariableHandler = new TypeVariableHandler(compiler); |
| 537 customElementsAnalysis = new CustomElementsAnalysis(this); | 536 customElementsAnalysis = new CustomElementsAnalysis(this); |
| 538 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); | 537 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); |
| 539 jsInteropAnalysis = new JsInteropAnalysis(this); | 538 jsInteropAnalysis = new JsInteropAnalysis(this); |
| 540 | 539 |
| 541 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 540 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
| 542 constantCompilerTask = new JavaScriptConstantTask(compiler); | 541 constantCompilerTask = new JavaScriptConstantTask(compiler); |
| 543 impactTransformer = new JavaScriptImpactTransformer(this); | 542 impactTransformer = new JavaScriptImpactTransformer(this); |
| 544 patchResolverTask = new PatchResolverTask(compiler); | 543 patchResolverTask = new PatchResolverTask(compiler); |
| 545 functionCompiler = compiler.options.useCpsIr | 544 functionCompiler = compiler.options.useCpsIr |
| 546 ? new CpsFunctionCompiler( | 545 ? new CpsFunctionCompiler(compiler, this, sourceInformationStrategy) |
| 547 compiler, this, sourceInformationStrategy) | 546 : new SsaFunctionCompiler(this, sourceInformationStrategy); |
| 548 : new SsaFunctionCompiler(this, sourceInformationStrategy); | |
| 549 serialization = new JavaScriptBackendSerialization(this); | 547 serialization = new JavaScriptBackendSerialization(this); |
| 550 } | 548 } |
| 551 | 549 |
| 552 ConstantSystem get constantSystem => constants.constantSystem; | 550 ConstantSystem get constantSystem => constants.constantSystem; |
| 553 | 551 |
| 554 DiagnosticReporter get reporter => compiler.reporter; | 552 DiagnosticReporter get reporter => compiler.reporter; |
| 555 | 553 |
| 556 CoreClasses get coreClasses => compiler.coreClasses; | 554 CoreClasses get coreClasses => compiler.coreClasses; |
| 557 | 555 |
| 558 CoreTypes get coreTypes => compiler.coreTypes; | 556 CoreTypes get coreTypes => compiler.coreTypes; |
| 559 | 557 |
| 560 Resolution get resolution => compiler.resolution; | 558 Resolution get resolution => compiler.resolution; |
| 561 | 559 |
| 562 /// Returns constant environment for the JavaScript interpretation of the | 560 /// Returns constant environment for the JavaScript interpretation of the |
| 563 /// constants. | 561 /// constants. |
| 564 JavaScriptConstantCompiler get constants { | 562 JavaScriptConstantCompiler get constants { |
| 565 return constantCompilerTask.jsConstantCompiler; | 563 return constantCompilerTask.jsConstantCompiler; |
| 566 } | 564 } |
| 567 | 565 |
| 568 MethodElement resolveExternalFunction(MethodElement element) { | 566 MethodElement resolveExternalFunction(MethodElement element) { |
| 569 if (isForeign(element)) { | 567 if (isForeign(element)) { |
| 570 return element; | 568 return element; |
| 571 } | 569 } |
| 572 if (isJsInterop(element)) { | 570 if (isJsInterop(element)) { |
| 573 if (element.memberName == const PublicName('[]') || | 571 if (element.memberName == const PublicName('[]') || |
| 574 element.memberName == const PublicName('[]=')) { | 572 element.memberName == const PublicName('[]=')) { |
| 575 reporter.reportErrorMessage(element, | 573 reporter.reportErrorMessage( |
| 576 MessageKind.JS_INTEROP_INDEX_NOT_SUPPORTED); | 574 element, MessageKind.JS_INTEROP_INDEX_NOT_SUPPORTED); |
| 577 } | 575 } |
| 578 return element; | 576 return element; |
| 579 } | 577 } |
| 580 return patchResolverTask.measure(() { | 578 return patchResolverTask.measure(() { |
| 581 return patchResolverTask.resolveExternalFunction(element); | 579 return patchResolverTask.resolveExternalFunction(element); |
| 582 }); | 580 }); |
| 583 } | 581 } |
| 584 | 582 |
| 585 bool isForeign(Element element) => element.library == helpers.foreignLibrary; | 583 bool isForeign(Element element) => element.library == helpers.foreignLibrary; |
| 586 | 584 |
| 587 bool isBackendLibrary(LibraryElement library) { | 585 bool isBackendLibrary(LibraryElement library) { |
| 588 return library == helpers.interceptorsLibrary || | 586 return library == helpers.interceptorsLibrary || |
| 589 library == helpers.jsHelperLibrary; | 587 library == helpers.jsHelperLibrary; |
| 590 } | 588 } |
| 591 | 589 |
| 592 static Namer determineNamer(Compiler compiler) { | 590 static Namer determineNamer(Compiler compiler) { |
| 593 return compiler.options.enableMinification ? | 591 return compiler.options.enableMinification |
| 594 compiler.options.useFrequencyNamer ? | 592 ? compiler.options.useFrequencyNamer |
| 595 new FrequencyBasedNamer(compiler) : | 593 ? new FrequencyBasedNamer(compiler) |
| 596 new MinifyNamer(compiler) : | 594 : new MinifyNamer(compiler) |
| 597 new Namer(compiler); | 595 : new Namer(compiler); |
| 598 } | 596 } |
| 599 | 597 |
| 600 /// The backend must *always* call this method when enqueuing an | 598 /// The backend must *always* call this method when enqueuing an |
| 601 /// element. Calls done by the backend are not seen by global | 599 /// element. Calls done by the backend are not seen by global |
| 602 /// optimizations, so they would make these optimizations unsound. | 600 /// optimizations, so they would make these optimizations unsound. |
| 603 /// Therefore we need to collect the list of helpers the backend may | 601 /// Therefore we need to collect the list of helpers the backend may |
| 604 /// use. | 602 /// use. |
| 605 // TODO(johnniwinther): Replace this with a more precise modelling; type | 603 // TODO(johnniwinther): Replace this with a more precise modelling; type |
| 606 // inference of these elements is disabled. | 604 // inference of these elements is disabled. |
| 607 Element registerBackendUse(Element element) { | 605 Element registerBackendUse(Element element) { |
| 608 if (element == null) return null; | 606 if (element == null) return null; |
| 609 assert(invariant(element, _isValidBackendUse(element), | 607 assert(invariant(element, _isValidBackendUse(element), |
| 610 message: "Backend use of $element is not allowed.")); | 608 message: "Backend use of $element is not allowed.")); |
| 611 helpersUsed.add(element.declaration); | 609 helpersUsed.add(element.declaration); |
| 612 if (element.isClass && element.isPatched) { | 610 if (element.isClass && element.isPatched) { |
| 613 // Both declaration and implementation may declare fields, so we | 611 // Both declaration and implementation may declare fields, so we |
| 614 // add both to the list of helpers. | 612 // add both to the list of helpers. |
| 615 helpersUsed.add(element.implementation); | 613 helpersUsed.add(element.implementation); |
| 616 } | 614 } |
| 617 return element; | 615 return element; |
| 618 } | 616 } |
| 619 | 617 |
| 620 bool _isValidBackendUse(Element element) { | 618 bool _isValidBackendUse(Element element) { |
| 621 assert(invariant(element, element.isDeclaration, | 619 assert(invariant(element, element.isDeclaration, message: "")); |
| 622 message: "")); | |
| 623 if (element == helpers.streamIteratorConstructor || | 620 if (element == helpers.streamIteratorConstructor || |
| 624 element == helpers.compiler.symbolConstructor || | 621 element == helpers.compiler.symbolConstructor || |
| 625 element == helpers.compiler.symbolValidatedConstructor || | 622 element == helpers.compiler.symbolValidatedConstructor || |
| 626 element == helpers.syncCompleterConstructor || | 623 element == helpers.syncCompleterConstructor || |
| 627 element == coreClasses.symbolClass || | 624 element == coreClasses.symbolClass || |
| 628 element == helpers.objectNoSuchMethod) { | 625 element == helpers.objectNoSuchMethod) { |
| 629 // TODO(johnniwinther): These are valid but we could be more precise. | 626 // TODO(johnniwinther): These are valid but we could be more precise. |
| 630 return true; | 627 return true; |
| 631 } else if (element.implementationLibrary.isPatch || | 628 } else if (element.implementationLibrary.isPatch || |
| 632 // Needed to detect deserialized injected elements, that is | 629 // Needed to detect deserialized injected elements, that is |
| 633 // element declared in patch files. | 630 // element declared in patch files. |
| 634 (element.library.isPlatformLibrary && | 631 (element.library.isPlatformLibrary && |
| 635 element.sourcePosition.uri.path.contains( | 632 element.sourcePosition.uri.path |
| 636 '_internal/js_runtime/lib/')) || | 633 .contains('_internal/js_runtime/lib/')) || |
| 637 element.library == helpers.jsHelperLibrary || | 634 element.library == helpers.jsHelperLibrary || |
| 638 element.library == helpers.interceptorsLibrary || | 635 element.library == helpers.interceptorsLibrary || |
| 639 element.library == helpers.isolateHelperLibrary) { | 636 element.library == helpers.isolateHelperLibrary) { |
| 640 // TODO(johnniwinther): We should be more precise about these. | 637 // TODO(johnniwinther): We should be more precise about these. |
| 641 return true; | 638 return true; |
| 642 } else if (element == coreClasses.listClass || | 639 } else if (element == coreClasses.listClass || |
| 643 element == helpers.mapLiteralClass || | 640 element == helpers.mapLiteralClass || |
| 644 element == coreClasses.functionClass || | 641 element == coreClasses.functionClass || |
| 645 element == coreClasses.stringClass) { | 642 element == coreClasses.stringClass) { |
| 646 // TODO(johnniwinther): Avoid these. | 643 // TODO(johnniwinther): Avoid these. |
| 647 return true; | 644 return true; |
| 648 } | 645 } |
| 649 return false; | 646 return false; |
| 650 } | 647 } |
| 651 | 648 |
| 652 bool usedByBackend(Element element) { | 649 bool usedByBackend(Element element) { |
| 653 if (element.isParameter | 650 if (element.isParameter || |
| 654 || element.isInitializingFormal | 651 element.isInitializingFormal || |
| 655 || element.isField) { | 652 element.isField) { |
| 656 if (usedByBackend(element.enclosingElement)) return true; | 653 if (usedByBackend(element.enclosingElement)) return true; |
| 657 } | 654 } |
| 658 return helpersUsed.contains(element.declaration); | 655 return helpersUsed.contains(element.declaration); |
| 659 } | 656 } |
| 660 | 657 |
| 661 bool invokedReflectively(Element element) { | 658 bool invokedReflectively(Element element) { |
| 662 if (element.isParameter || element.isInitializingFormal) { | 659 if (element.isParameter || element.isInitializingFormal) { |
| 663 ParameterElement parameter = element; | 660 ParameterElement parameter = element; |
| 664 if (invokedReflectively(parameter.functionDeclaration)) return true; | 661 if (invokedReflectively(parameter.functionDeclaration)) return true; |
| 665 } | 662 } |
| 666 | 663 |
| 667 if (element.isField) { | 664 if (element.isField) { |
| 668 if (Elements.isStaticOrTopLevel(element) | 665 if (Elements.isStaticOrTopLevel(element) && |
| 669 && (element.isFinal || element.isConst)) { | 666 (element.isFinal || element.isConst)) { |
| 670 return false; | 667 return false; |
| 671 } | 668 } |
| 672 } | 669 } |
| 673 | 670 |
| 674 return isAccessibleByReflection(element.declaration); | 671 return isAccessibleByReflection(element.declaration); |
| 675 } | 672 } |
| 676 | 673 |
| 677 bool canBeUsedForGlobalOptimizations(Element element) { | 674 bool canBeUsedForGlobalOptimizations(Element element) { |
| 678 return !usedByBackend(element) && !invokedReflectively(element); | 675 return !usedByBackend(element) && !invokedReflectively(element); |
| 679 } | 676 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 bool isInterceptedSelector(Selector selector) { | 765 bool isInterceptedSelector(Selector selector) { |
| 769 return interceptedElements[selector.name] != null; | 766 return interceptedElements[selector.name] != null; |
| 770 } | 767 } |
| 771 | 768 |
| 772 /** | 769 /** |
| 773 * Returns `true` iff [selector] matches an element defined in a class mixed | 770 * Returns `true` iff [selector] matches an element defined in a class mixed |
| 774 * into an intercepted class. These selectors are not eligible for the 'dummy | 771 * into an intercepted class. These selectors are not eligible for the 'dummy |
| 775 * explicit receiver' optimization. | 772 * explicit receiver' optimization. |
| 776 */ | 773 */ |
| 777 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { | 774 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { |
| 778 Set<Element> elements = interceptedMixinElements.putIfAbsent( | 775 Set<Element> elements = |
| 779 selector.name, | 776 interceptedMixinElements.putIfAbsent(selector.name, () { |
| 780 () { | 777 Set<Element> elements = interceptedElements[selector.name]; |
| 781 Set<Element> elements = interceptedElements[selector.name]; | 778 if (elements == null) return null; |
| 782 if (elements == null) return null; | 779 return elements |
| 783 return elements | 780 .where((element) => classesMixedIntoInterceptedClasses |
| 784 .where((element) => | 781 .contains(element.enclosingClass)) |
| 785 classesMixedIntoInterceptedClasses.contains( | 782 .toSet(); |
| 786 element.enclosingClass)) | 783 }); |
| 787 .toSet(); | |
| 788 }); | |
| 789 | 784 |
| 790 if (elements == null) return false; | 785 if (elements == null) return false; |
| 791 if (elements.isEmpty) return false; | 786 if (elements.isEmpty) return false; |
| 792 return elements.any((element) { | 787 return elements.any((element) { |
| 793 return selector.applies(element, compiler.world) && | 788 return selector.applies(element, compiler.world) && |
| 794 (mask == null || mask.canHit(element, selector, compiler.world)); | 789 (mask == null || mask.canHit(element, selector, compiler.world)); |
| 795 }); | 790 }); |
| 796 } | 791 } |
| 797 | 792 |
| 798 /// True if the given class is an internal class used for type inference | 793 /// True if the given class is an internal class used for type inference |
| 799 /// and never exists at runtime. | 794 /// and never exists at runtime. |
| 800 bool isCompileTimeOnlyClass(ClassElement class_) { | 795 bool isCompileTimeOnlyClass(ClassElement class_) { |
| 801 return class_ == helpers.jsPositiveIntClass || | 796 return class_ == helpers.jsPositiveIntClass || |
| 802 class_ == helpers.jsUInt32Class || | 797 class_ == helpers.jsUInt32Class || |
| 803 class_ == helpers.jsUInt31Class || | 798 class_ == helpers.jsUInt31Class || |
| 804 class_ == helpers.jsFixedArrayClass || | 799 class_ == helpers.jsFixedArrayClass || |
| 805 class_ == helpers.jsUnmodifiableArrayClass || | 800 class_ == helpers.jsUnmodifiableArrayClass || |
| 806 class_ == helpers.jsMutableArrayClass || | 801 class_ == helpers.jsMutableArrayClass || |
| 807 class_ == helpers.jsExtendableArrayClass; | 802 class_ == helpers.jsExtendableArrayClass; |
| 808 } | 803 } |
| 809 | 804 |
| 810 /// Maps compile-time classes to their runtime class. The runtime class is | 805 /// Maps compile-time classes to their runtime class. The runtime class is |
| 811 /// always a superclass or the class itself. | 806 /// always a superclass or the class itself. |
| 812 ClassElement getRuntimeClass(ClassElement class_) { | 807 ClassElement getRuntimeClass(ClassElement class_) { |
| 813 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; | 808 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; |
| 814 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; | 809 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; |
| 815 return class_; | 810 return class_; |
| 816 } | 811 } |
| 817 | 812 |
| 818 final Map<String, Set<ClassElement>> interceptedClassesCache = | 813 final Map<String, Set<ClassElement>> interceptedClassesCache = |
| 819 new Map<String, Set<ClassElement>>(); | 814 new Map<String, Set<ClassElement>>(); |
| 820 final Set<ClassElement> _noClasses = new Set<ClassElement>(); | 815 final Set<ClassElement> _noClasses = new Set<ClassElement>(); |
| 821 | 816 |
| 822 /// Returns a set of interceptor classes that contain a member named [name] | 817 /// Returns a set of interceptor classes that contain a member named [name] |
| 823 /// | 818 /// |
| 824 /// Returns an empty set if there is no class. Do not modify the returned set. | 819 /// Returns an empty set if there is no class. Do not modify the returned set. |
| 825 Set<ClassElement> getInterceptedClassesOn(String name) { | 820 Set<ClassElement> getInterceptedClassesOn(String name) { |
| 826 Set<Element> intercepted = interceptedElements[name]; | 821 Set<Element> intercepted = interceptedElements[name]; |
| 827 if (intercepted == null) return _noClasses; | 822 if (intercepted == null) return _noClasses; |
| 828 return interceptedClassesCache.putIfAbsent(name, () { | 823 return interceptedClassesCache.putIfAbsent(name, () { |
| 829 // Populate the cache by running through all the elements and | 824 // Populate the cache by running through all the elements and |
| 830 // determine if the given selector applies to them. | 825 // determine if the given selector applies to them. |
| 831 Set<ClassElement> result = new Set<ClassElement>(); | 826 Set<ClassElement> result = new Set<ClassElement>(); |
| 832 for (Element element in intercepted) { | 827 for (Element element in intercepted) { |
| 833 ClassElement classElement = element.enclosingClass; | 828 ClassElement classElement = element.enclosingClass; |
| 834 if (isCompileTimeOnlyClass(classElement)) continue; | 829 if (isCompileTimeOnlyClass(classElement)) continue; |
| 835 if (isNativeOrExtendsNative(classElement) | 830 if (isNativeOrExtendsNative(classElement) || |
| 836 || interceptedClasses.contains(classElement)) { | 831 interceptedClasses.contains(classElement)) { |
| 837 result.add(classElement); | 832 result.add(classElement); |
| 838 } | 833 } |
| 839 if (classesMixedIntoInterceptedClasses.contains(classElement)) { | 834 if (classesMixedIntoInterceptedClasses.contains(classElement)) { |
| 840 Set<ClassElement> nativeSubclasses = | 835 Set<ClassElement> nativeSubclasses = |
| 841 nativeSubclassesOfMixin(classElement); | 836 nativeSubclassesOfMixin(classElement); |
| 842 if (nativeSubclasses != null) result.addAll(nativeSubclasses); | 837 if (nativeSubclasses != null) result.addAll(nativeSubclasses); |
| 843 } | 838 } |
| 844 } | 839 } |
| 845 return result; | 840 return result; |
| 846 }); | 841 }); |
| 847 } | 842 } |
| 848 | 843 |
| 849 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { | 844 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { |
| 850 ClassWorld classWorld = compiler.world; | 845 ClassWorld classWorld = compiler.world; |
| 851 Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin); | 846 Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin); |
| 852 Set<ClassElement> result = null; | 847 Set<ClassElement> result = null; |
| 853 for (MixinApplicationElement use in uses) { | 848 for (MixinApplicationElement use in uses) { |
| 854 classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { | 849 classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { |
| 855 if (isNativeOrExtendsNative(subclass)) { | 850 if (isNativeOrExtendsNative(subclass)) { |
| 856 if (result == null) result = new Set<ClassElement>(); | 851 if (result == null) result = new Set<ClassElement>(); |
| 857 result.add(subclass); | 852 result.add(subclass); |
| 858 } | 853 } |
| 859 }); | 854 }); |
| 860 } | 855 } |
| 861 return result; | 856 return result; |
| 862 } | 857 } |
| 863 | 858 |
| 864 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 859 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
| 865 return specialOperatorEqClasses.contains( | 860 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass); |
| 866 operatorEqfunction.enclosingClass); | |
| 867 } | 861 } |
| 868 | 862 |
| 869 void validateInterceptorImplementsAllObjectMethods( | 863 void validateInterceptorImplementsAllObjectMethods( |
| 870 ClassElement interceptorClass) { | 864 ClassElement interceptorClass) { |
| 871 if (interceptorClass == null) return; | 865 if (interceptorClass == null) return; |
| 872 interceptorClass.ensureResolved(resolution); | 866 interceptorClass.ensureResolved(resolution); |
| 873 coreClasses.objectClass.forEachMember((_, Element member) { | 867 coreClasses.objectClass.forEachMember((_, Element member) { |
| 874 if (member.isGenerativeConstructor) return; | 868 if (member.isGenerativeConstructor) return; |
| 875 Element interceptorMember = interceptorClass.lookupMember(member.name); | 869 Element interceptorMember = interceptorClass.lookupMember(member.name); |
| 876 // Interceptors must override all Object methods due to calling convention | 870 // Interceptors must override all Object methods due to calling convention |
| 877 // differences. | 871 // differences. |
| 878 assert(invariant( | 872 assert(invariant(interceptorMember, |
| 879 interceptorMember, | |
| 880 interceptorMember.enclosingClass == interceptorClass, | 873 interceptorMember.enclosingClass == interceptorClass, |
| 881 message: | 874 message: |
| 882 "Member ${member.name} not overridden in ${interceptorClass}. " | 875 "Member ${member.name} not overridden in ${interceptorClass}. " |
| 883 "Found $interceptorMember from " | 876 "Found $interceptorMember from " |
| 884 "${interceptorMember.enclosingClass}.")); | 877 "${interceptorMember.enclosingClass}.")); |
| 885 }); | 878 }); |
| 886 } | 879 } |
| 887 | 880 |
| 888 void addInterceptorsForNativeClassMembers( | 881 void addInterceptorsForNativeClassMembers( |
| 889 ClassElement cls, Enqueuer enqueuer) { | 882 ClassElement cls, Enqueuer enqueuer) { |
| 890 if (enqueuer.isResolutionQueue) { | 883 if (enqueuer.isResolutionQueue) { |
| 891 cls.ensureResolved(resolution); | 884 cls.ensureResolved(resolution); |
| 892 cls.forEachMember((ClassElement classElement, Element member) { | 885 cls.forEachMember((ClassElement classElement, Element member) { |
| 893 if (member.name == Identifiers.call) { | 886 if (member.name == Identifiers.call) { |
| 894 reporter.reportErrorMessage( | 887 reporter.reportErrorMessage( |
| 895 member, | 888 member, MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); |
| 896 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); | |
| 897 return; | 889 return; |
| 898 } | 890 } |
| 899 if (member.isSynthesized) return; | 891 if (member.isSynthesized) return; |
| 900 // All methods on [Object] are shadowed by [Interceptor]. | 892 // All methods on [Object] are shadowed by [Interceptor]. |
| 901 if (classElement == coreClasses.objectClass) return; | 893 if (classElement == coreClasses.objectClass) return; |
| 902 Set<Element> set = interceptedElements.putIfAbsent( | 894 Set<Element> set = interceptedElements.putIfAbsent( |
| 903 member.name, () => new Set<Element>()); | 895 member.name, () => new Set<Element>()); |
| 904 set.add(member); | 896 set.add(member); |
| 905 }, | 897 }, includeSuperAndInjectedMembers: true); |
| 906 includeSuperAndInjectedMembers: true); | |
| 907 | 898 |
| 908 // Walk superclass chain to find mixins. | 899 // Walk superclass chain to find mixins. |
| 909 for (; cls != null; cls = cls.superclass) { | 900 for (; cls != null; cls = cls.superclass) { |
| 910 if (cls.isMixinApplication) { | 901 if (cls.isMixinApplication) { |
| 911 MixinApplicationElement mixinApplication = cls; | 902 MixinApplicationElement mixinApplication = cls; |
| 912 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | 903 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); |
| 913 } | 904 } |
| 914 } | 905 } |
| 915 } | 906 } |
| 916 } | 907 } |
| 917 | 908 |
| 918 void addInterceptors(ClassElement cls, | 909 void addInterceptors(ClassElement cls, Enqueuer enqueuer, Registry registry) { |
| 919 Enqueuer enqueuer, | |
| 920 Registry registry) { | |
| 921 if (enqueuer.isResolutionQueue) { | 910 if (enqueuer.isResolutionQueue) { |
| 922 _interceptedClasses.add(helpers.jsInterceptorClass); | 911 _interceptedClasses.add(helpers.jsInterceptorClass); |
| 923 _interceptedClasses.add(cls); | 912 _interceptedClasses.add(cls); |
| 924 cls.ensureResolved(resolution); | 913 cls.ensureResolved(resolution); |
| 925 cls.forEachMember((ClassElement classElement, Element member) { | 914 cls.forEachMember((ClassElement classElement, Element member) { |
| 926 // All methods on [Object] are shadowed by [Interceptor]. | 915 // All methods on [Object] are shadowed by [Interceptor]. |
| 927 if (classElement == coreClasses.objectClass) return; | 916 if (classElement == coreClasses.objectClass) return; |
| 928 Set<Element> set = interceptedElements.putIfAbsent( | 917 Set<Element> set = interceptedElements.putIfAbsent( |
| 929 member.name, () => new Set<Element>()); | 918 member.name, () => new Set<Element>()); |
| 930 set.add(member); | 919 set.add(member); |
| 931 }, | 920 }, includeSuperAndInjectedMembers: true); |
| 932 includeSuperAndInjectedMembers: true); | |
| 933 } | 921 } |
| 934 enqueueClass(enqueuer, cls, registry); | 922 enqueueClass(enqueuer, cls, registry); |
| 935 } | 923 } |
| 936 | 924 |
| 937 Set<ClassElement> get interceptedClasses { | 925 Set<ClassElement> get interceptedClasses { |
| 938 assert(compiler.enqueuer.resolution.queueIsClosed); | 926 assert(compiler.enqueuer.resolution.queueIsClosed); |
| 939 return _interceptedClasses; | 927 return _interceptedClasses; |
| 940 } | 928 } |
| 941 | 929 |
| 942 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { | 930 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
| 943 jsAst.Name name = namer.nameForGetInterceptor(classes); | 931 jsAst.Name name = namer.nameForGetInterceptor(classes); |
| 944 if (classes.contains(helpers.jsInterceptorClass)) { | 932 if (classes.contains(helpers.jsInterceptorClass)) { |
| 945 // We can't use a specialized [getInterceptorMethod], so we make | 933 // We can't use a specialized [getInterceptorMethod], so we make |
| 946 // sure we emit the one with all checks. | 934 // sure we emit the one with all checks. |
| 947 specializedGetInterceptors[name] = interceptedClasses; | 935 specializedGetInterceptors[name] = interceptedClasses; |
| 948 } else { | 936 } else { |
| 949 specializedGetInterceptors[name] = classes; | 937 specializedGetInterceptors[name] = classes; |
| 950 } | 938 } |
| 951 } | 939 } |
| 952 | 940 |
| 953 void registerCompileTimeConstant(ConstantValue constant, Registry registry) { | 941 void registerCompileTimeConstant(ConstantValue constant, Registry registry) { |
| 954 registerCompileTimeConstantInternal(constant, registry); | 942 registerCompileTimeConstantInternal(constant, registry); |
| 955 | 943 |
| 956 if (!registry.isForResolution && | 944 if (!registry.isForResolution && lookupMapAnalysis.isLookupMap(constant)) { |
| 957 lookupMapAnalysis.isLookupMap(constant)) { | |
| 958 // Note: internally, this registration will temporarily remove the | 945 // Note: internally, this registration will temporarily remove the |
| 959 // constant dependencies and add them later on-demand. | 946 // constant dependencies and add them later on-demand. |
| 960 lookupMapAnalysis.registerLookupMapReference(constant); | 947 lookupMapAnalysis.registerLookupMapReference(constant); |
| 961 } | 948 } |
| 962 | 949 |
| 963 for (ConstantValue dependency in constant.getDependencies()) { | 950 for (ConstantValue dependency in constant.getDependencies()) { |
| 964 registerCompileTimeConstant(dependency, registry); | 951 registerCompileTimeConstant(dependency, registry); |
| 965 } | 952 } |
| 966 } | 953 } |
| 967 | 954 |
| 968 void addCompileTimeConstantForEmission(ConstantValue constant) { | 955 void addCompileTimeConstantForEmission(ConstantValue constant) { |
| 969 constants.addCompileTimeConstantForEmission(constant); | 956 constants.addCompileTimeConstantForEmission(constant); |
| 970 } | 957 } |
| 971 | 958 |
| 972 void registerCompileTimeConstantInternal(ConstantValue constant, | 959 void registerCompileTimeConstantInternal( |
| 973 Registry registry) { | 960 ConstantValue constant, Registry registry) { |
| 974 DartType type = constant.getType(compiler.coreTypes); | 961 DartType type = constant.getType(compiler.coreTypes); |
| 975 registerInstantiatedConstantType(type, registry); | 962 registerInstantiatedConstantType(type, registry); |
| 976 | 963 |
| 977 if (constant.isFunction) { | 964 if (constant.isFunction) { |
| 978 FunctionConstantValue function = constant; | 965 FunctionConstantValue function = constant; |
| 979 registry.registerStaticUse(new StaticUse.staticTearOff(function.element)); | 966 registry.registerStaticUse(new StaticUse.staticTearOff(function.element)); |
| 980 } else if (constant.isInterceptor) { | 967 } else if (constant.isInterceptor) { |
| 981 // An interceptor constant references the class's prototype chain. | 968 // An interceptor constant references the class's prototype chain. |
| 982 InterceptorConstantValue interceptor = constant; | 969 InterceptorConstantValue interceptor = constant; |
| 983 registerInstantiatedConstantType(interceptor.dispatchedType, registry); | 970 registerInstantiatedConstantType(interceptor.dispatchedType, registry); |
| 984 } else if (constant.isType) { | 971 } else if (constant.isType) { |
| 985 enqueueInResolution(helpers.createRuntimeType, registry); | 972 enqueueInResolution(helpers.createRuntimeType, registry); |
| 986 registry.registerInstantiation(typeImplementation.rawType); | 973 registry.registerInstantiation(typeImplementation.rawType); |
| 987 } | 974 } |
| 988 lookupMapAnalysis.registerConstantKey(constant); | 975 lookupMapAnalysis.registerConstantKey(constant); |
| 989 } | 976 } |
| 990 | 977 |
| 991 void registerInstantiatedConstantType(DartType type, Registry registry) { | 978 void registerInstantiatedConstantType(DartType type, Registry registry) { |
| 992 DartType instantiatedType = | 979 DartType instantiatedType = |
| 993 type.isFunctionType ? coreTypes.functionType : type; | 980 type.isFunctionType ? coreTypes.functionType : type; |
| 994 if (type is InterfaceType) { | 981 if (type is InterfaceType) { |
| 995 registry.registerInstantiation(instantiatedType); | 982 registry.registerInstantiation(instantiatedType); |
| 996 if (!type.treatAsRaw && classNeedsRti(type.element)) { | 983 if (!type.treatAsRaw && classNeedsRti(type.element)) { |
| 997 registry.registerStaticUse( | 984 registry.registerStaticUse(new StaticUse.staticInvoke( |
| 998 new StaticUse.staticInvoke( | 985 // TODO(johnniwinther): Find the right [CallStructure]. |
| 999 // TODO(johnniwinther): Find the right [CallStructure]. | 986 helpers.setRuntimeTypeInfo, |
| 1000 helpers.setRuntimeTypeInfo, null)); | 987 null)); |
| 1001 } | 988 } |
| 1002 if (type.element == typeImplementation) { | 989 if (type.element == typeImplementation) { |
| 1003 // If we use a type literal in a constant, the compile time | 990 // If we use a type literal in a constant, the compile time |
| 1004 // constant emitter will generate a call to the createRuntimeType | 991 // constant emitter will generate a call to the createRuntimeType |
| 1005 // helper so we register a use of that. | 992 // helper so we register a use of that. |
| 1006 registry.registerStaticUse( | 993 registry.registerStaticUse(new StaticUse.staticInvoke( |
| 1007 new StaticUse.staticInvoke( | 994 // TODO(johnniwinther): Find the right [CallStructure]. |
| 1008 // TODO(johnniwinther): Find the right [CallStructure]. | |
| 1009 | 995 |
| 1010 helpers.createRuntimeType, null)); | 996 helpers.createRuntimeType, |
| 997 null)); |
| 1011 } | 998 } |
| 1012 } | 999 } |
| 1013 } | 1000 } |
| 1014 | 1001 |
| 1015 void registerMetadataConstant(MetadataAnnotation metadata, | 1002 void registerMetadataConstant(MetadataAnnotation metadata, |
| 1016 Element annotatedElement, | 1003 Element annotatedElement, Registry registry) { |
| 1017 Registry registry) { | |
| 1018 assert(registry.isForResolution); | 1004 assert(registry.isForResolution); |
| 1019 ConstantValue constant = constants.getConstantValueForMetadata(metadata); | 1005 ConstantValue constant = constants.getConstantValueForMetadata(metadata); |
| 1020 registerCompileTimeConstant(constant, registry); | 1006 registerCompileTimeConstant(constant, registry); |
| 1021 metadataConstants.add(new Dependency(constant, annotatedElement)); | 1007 metadataConstants.add(new Dependency(constant, annotatedElement)); |
| 1022 } | 1008 } |
| 1023 | 1009 |
| 1024 void registerInstantiatedClass(ClassElement cls, | 1010 void registerInstantiatedClass( |
| 1025 Enqueuer enqueuer, | 1011 ClassElement cls, Enqueuer enqueuer, Registry registry) { |
| 1026 Registry registry) { | |
| 1027 _processClass(cls, enqueuer, registry); | 1012 _processClass(cls, enqueuer, registry); |
| 1028 } | 1013 } |
| 1029 | 1014 |
| 1030 void registerImplementedClass(ClassElement cls, | 1015 void registerImplementedClass( |
| 1031 Enqueuer enqueuer, | 1016 ClassElement cls, Enqueuer enqueuer, Registry registry) { |
| 1032 Registry registry) { | |
| 1033 _processClass(cls, enqueuer, registry); | 1017 _processClass(cls, enqueuer, registry); |
| 1034 } | 1018 } |
| 1035 | 1019 |
| 1036 void _processClass(ClassElement cls, | 1020 void _processClass(ClassElement cls, Enqueuer enqueuer, Registry registry) { |
| 1037 Enqueuer enqueuer, | |
| 1038 Registry registry) { | |
| 1039 if (!cls.typeVariables.isEmpty) { | 1021 if (!cls.typeVariables.isEmpty) { |
| 1040 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer, | 1022 typeVariableHandler.registerClassWithTypeVariables( |
| 1041 registry); | 1023 cls, enqueuer, registry); |
| 1042 } | 1024 } |
| 1043 | 1025 |
| 1044 // Register any helper that will be needed by the backend. | 1026 // Register any helper that will be needed by the backend. |
| 1045 if (enqueuer.isResolutionQueue) { | 1027 if (enqueuer.isResolutionQueue) { |
| 1046 if (cls == coreClasses.intClass || | 1028 if (cls == coreClasses.intClass || |
| 1047 cls == coreClasses.doubleClass || | 1029 cls == coreClasses.doubleClass || |
| 1048 cls == coreClasses.numClass) { | 1030 cls == coreClasses.numClass) { |
| 1049 // The backend will try to optimize number operations and use the | 1031 // The backend will try to optimize number operations and use the |
| 1050 // `iae` helper directly. | 1032 // `iae` helper directly. |
| 1051 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); | 1033 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); |
| 1052 } else if (cls == coreClasses.listClass || | 1034 } else if (cls == coreClasses.listClass || |
| 1053 cls == coreClasses.stringClass) { | 1035 cls == coreClasses.stringClass) { |
| 1054 // The backend will try to optimize array and string access and use the | 1036 // The backend will try to optimize array and string access and use the |
| 1055 // `ioore` and `iae` helpers directly. | 1037 // `ioore` and `iae` helpers directly. |
| 1056 enqueue(enqueuer, helpers.throwIndexOutOfRangeException, registry); | 1038 enqueue(enqueuer, helpers.throwIndexOutOfRangeException, registry); |
| 1057 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); | 1039 enqueue(enqueuer, helpers.throwIllegalArgumentException, registry); |
| 1058 } else if (cls == coreClasses.functionClass) { | 1040 } else if (cls == coreClasses.functionClass) { |
| 1059 enqueueClass(enqueuer, helpers.closureClass, registry); | 1041 enqueueClass(enqueuer, helpers.closureClass, registry); |
| 1060 } else if (cls == coreClasses.mapClass) { | 1042 } else if (cls == coreClasses.mapClass) { |
| 1061 // The backend will use a literal list to initialize the entries | 1043 // The backend will use a literal list to initialize the entries |
| 1062 // of the map. | 1044 // of the map. |
| 1063 enqueueClass(enqueuer, coreClasses.listClass, registry); | 1045 enqueueClass(enqueuer, coreClasses.listClass, registry); |
| 1064 enqueueClass(enqueuer, helpers.mapLiteralClass, registry); | 1046 enqueueClass(enqueuer, helpers.mapLiteralClass, registry); |
| 1065 // For map literals, the dependency between the implementation class | 1047 // For map literals, the dependency between the implementation class |
| 1066 // and [Map] is not visible, so we have to add it manually. | 1048 // and [Map] is not visible, so we have to add it manually. |
| 1067 rti.registerRtiDependency(helpers.mapLiteralClass, cls); | 1049 rti.registerRtiDependency(helpers.mapLiteralClass, cls); |
| 1068 } else if (cls == helpers.boundClosureClass) { | 1050 } else if (cls == helpers.boundClosureClass) { |
| 1069 // TODO(johnniwinther): Is this a noop? | 1051 // TODO(johnniwinther): Is this a noop? |
| 1070 enqueueClass(enqueuer, helpers.boundClosureClass, registry); | 1052 enqueueClass(enqueuer, helpers.boundClosureClass, registry); |
| 1071 } else if (isNativeOrExtendsNative(cls)) { | 1053 } else if (isNativeOrExtendsNative(cls)) { |
| 1072 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); | 1054 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
| 1073 enqueueClass(enqueuer, helpers.jsInterceptorClass, | 1055 enqueueClass( |
| 1074 compiler.globalDependencies); | 1056 enqueuer, helpers.jsInterceptorClass, compiler.globalDependencies); |
| 1075 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); | 1057 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
| 1076 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); | 1058 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
| 1077 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); | 1059 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
| 1078 } else if (cls == helpers.mapLiteralClass) { | 1060 } else if (cls == helpers.mapLiteralClass) { |
| 1079 // For map literals, the dependency between the implementation class | 1061 // For map literals, the dependency between the implementation class |
| 1080 // and [Map] is not visible, so we have to add it manually. | 1062 // and [Map] is not visible, so we have to add it manually. |
| 1081 Element getFactory(String name, int arity) { | 1063 Element getFactory(String name, int arity) { |
| 1082 // The constructor is on the patch class, but dart2js unit tests don't | 1064 // The constructor is on the patch class, but dart2js unit tests don't |
| 1083 // have a patch class. | 1065 // have a patch class. |
| 1084 ClassElement implementation = cls.implementation; | 1066 ClassElement implementation = cls.implementation; |
| 1085 ConstructorElement ctor = implementation.lookupConstructor(name); | 1067 ConstructorElement ctor = implementation.lookupConstructor(name); |
| 1086 if (ctor == null || | 1068 if (ctor == null || |
| 1087 (Name.isPrivateName(name) && | 1069 (Name.isPrivateName(name) && |
| 1088 ctor.library != helpers.mapLiteralClass.library)) { | 1070 ctor.library != helpers.mapLiteralClass.library)) { |
| 1089 reporter.internalError( | 1071 reporter.internalError( |
| 1090 helpers.mapLiteralClass, | 1072 helpers.mapLiteralClass, |
| 1091 "Map literal class ${helpers.mapLiteralClass} missing " | 1073 "Map literal class ${helpers.mapLiteralClass} missing " |
| 1092 "'$name' constructor" | 1074 "'$name' constructor" |
| 1093 " ${helpers.mapLiteralClass.constructors}"); | 1075 " ${helpers.mapLiteralClass.constructors}"); |
| 1094 } | 1076 } |
| 1095 return ctor; | 1077 return ctor; |
| 1096 } | 1078 } |
| 1097 Element getMember(String name) { | 1079 Element getMember(String name) { |
| 1098 // The constructor is on the patch class, but dart2js unit tests don't | 1080 // The constructor is on the patch class, but dart2js unit tests don't |
| 1099 // have a patch class. | 1081 // have a patch class. |
| 1100 ClassElement implementation = cls.implementation; | 1082 ClassElement implementation = cls.implementation; |
| 1101 Element element = implementation.lookupLocalMember(name); | 1083 Element element = implementation.lookupLocalMember(name); |
| 1102 if (element == null || !element.isFunction || !element.isStatic) { | 1084 if (element == null || !element.isFunction || !element.isStatic) { |
| 1103 reporter.internalError(helpers.mapLiteralClass, | 1085 reporter.internalError( |
| 1086 helpers.mapLiteralClass, |
| 1104 "Map literal class ${helpers.mapLiteralClass} missing " | 1087 "Map literal class ${helpers.mapLiteralClass} missing " |
| 1105 "'$name' static member function"); | 1088 "'$name' static member function"); |
| 1106 } | 1089 } |
| 1107 return element; | 1090 return element; |
| 1108 } | 1091 } |
| 1109 helpers.mapLiteralConstructor = getFactory('_literal', 1); | 1092 helpers.mapLiteralConstructor = getFactory('_literal', 1); |
| 1110 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); | 1093 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); |
| 1111 enqueueInResolution(helpers.mapLiteralConstructor, registry); | 1094 enqueueInResolution(helpers.mapLiteralConstructor, registry); |
| 1112 enqueueInResolution(helpers.mapLiteralConstructorEmpty, registry); | 1095 enqueueInResolution(helpers.mapLiteralConstructorEmpty, registry); |
| 1113 | 1096 |
| 1114 helpers.mapLiteralUntypedMaker = getMember('_makeLiteral'); | 1097 helpers.mapLiteralUntypedMaker = getMember('_makeLiteral'); |
| 1115 helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); | 1098 helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); |
| 1116 enqueueInResolution(helpers.mapLiteralUntypedMaker, registry); | 1099 enqueueInResolution(helpers.mapLiteralUntypedMaker, registry); |
| 1117 enqueueInResolution(helpers.mapLiteralUntypedEmptyMaker, registry); | 1100 enqueueInResolution(helpers.mapLiteralUntypedEmptyMaker, registry); |
| 1118 } | 1101 } |
| 1119 } | 1102 } |
| 1120 if (cls == helpers.closureClass) { | 1103 if (cls == helpers.closureClass) { |
| 1121 enqueue(enqueuer, helpers.closureFromTearOff, registry); | 1104 enqueue(enqueuer, helpers.closureFromTearOff, registry); |
| 1122 } | 1105 } |
| 1123 if (cls == coreClasses.stringClass || | 1106 if (cls == coreClasses.stringClass || cls == helpers.jsStringClass) { |
| 1124 cls == helpers.jsStringClass) { | |
| 1125 addInterceptors(helpers.jsStringClass, enqueuer, registry); | 1107 addInterceptors(helpers.jsStringClass, enqueuer, registry); |
| 1126 } else if (cls == coreClasses.listClass || | 1108 } else if (cls == coreClasses.listClass || |
| 1127 cls == helpers.jsArrayClass || | 1109 cls == helpers.jsArrayClass || |
| 1128 cls == helpers.jsFixedArrayClass || | 1110 cls == helpers.jsFixedArrayClass || |
| 1129 cls == helpers.jsExtendableArrayClass || | 1111 cls == helpers.jsExtendableArrayClass || |
| 1130 cls == helpers.jsUnmodifiableArrayClass) { | 1112 cls == helpers.jsUnmodifiableArrayClass) { |
| 1131 addInterceptors(helpers.jsArrayClass, enqueuer, registry); | 1113 addInterceptors(helpers.jsArrayClass, enqueuer, registry); |
| 1132 addInterceptors(helpers.jsMutableArrayClass, enqueuer, registry); | 1114 addInterceptors(helpers.jsMutableArrayClass, enqueuer, registry); |
| 1133 addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry); | 1115 addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry); |
| 1134 addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry); | 1116 addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry); |
| 1135 addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry); | 1117 addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry); |
| 1136 // Literal lists can be translated into calls to these functions: | 1118 // Literal lists can be translated into calls to these functions: |
| 1137 enqueueInResolution(helpers.jsArrayTypedConstructor, registry); | 1119 enqueueInResolution(helpers.jsArrayTypedConstructor, registry); |
| 1138 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); | 1120 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); |
| 1139 enqueueInResolution(helpers.getTypeArgumentByIndex, registry); | 1121 enqueueInResolution(helpers.getTypeArgumentByIndex, registry); |
| 1140 } else if (cls == coreClasses.intClass || | 1122 } else if (cls == coreClasses.intClass || cls == helpers.jsIntClass) { |
| 1141 cls == helpers.jsIntClass) { | |
| 1142 addInterceptors(helpers.jsIntClass, enqueuer, registry); | 1123 addInterceptors(helpers.jsIntClass, enqueuer, registry); |
| 1143 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); | 1124 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); |
| 1144 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); | 1125 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); |
| 1145 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); | 1126 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); |
| 1146 addInterceptors(helpers.jsNumberClass, enqueuer, registry); | 1127 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
| 1147 } else if (cls == coreClasses.doubleClass || | 1128 } else if (cls == coreClasses.doubleClass || cls == helpers.jsDoubleClass) { |
| 1148 cls == helpers.jsDoubleClass) { | |
| 1149 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); | 1129 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); |
| 1150 addInterceptors(helpers.jsNumberClass, enqueuer, registry); | 1130 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
| 1151 } else if (cls == coreClasses.boolClass || | 1131 } else if (cls == coreClasses.boolClass || cls == helpers.jsBoolClass) { |
| 1152 cls == helpers.jsBoolClass) { | |
| 1153 addInterceptors(helpers.jsBoolClass, enqueuer, registry); | 1132 addInterceptors(helpers.jsBoolClass, enqueuer, registry); |
| 1154 } else if (cls == coreClasses.nullClass || | 1133 } else if (cls == coreClasses.nullClass || cls == helpers.jsNullClass) { |
| 1155 cls == helpers.jsNullClass) { | |
| 1156 addInterceptors(helpers.jsNullClass, enqueuer, registry); | 1134 addInterceptors(helpers.jsNullClass, enqueuer, registry); |
| 1157 } else if (cls == coreClasses.numClass || | 1135 } else if (cls == coreClasses.numClass || cls == helpers.jsNumberClass) { |
| 1158 cls == helpers.jsNumberClass) { | |
| 1159 addInterceptors(helpers.jsIntClass, enqueuer, registry); | 1136 addInterceptors(helpers.jsIntClass, enqueuer, registry); |
| 1160 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); | 1137 addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry); |
| 1161 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); | 1138 addInterceptors(helpers.jsUInt32Class, enqueuer, registry); |
| 1162 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); | 1139 addInterceptors(helpers.jsUInt31Class, enqueuer, registry); |
| 1163 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); | 1140 addInterceptors(helpers.jsDoubleClass, enqueuer, registry); |
| 1164 addInterceptors(helpers.jsNumberClass, enqueuer, registry); | 1141 addInterceptors(helpers.jsNumberClass, enqueuer, registry); |
| 1165 } else if (cls == helpers.jsJavaScriptObjectClass) { | 1142 } else if (cls == helpers.jsJavaScriptObjectClass) { |
| 1166 addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer, registry); | 1143 addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer, registry); |
| 1167 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { | 1144 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { |
| 1168 addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer, registry); | 1145 addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer, registry); |
| 1169 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { | 1146 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { |
| 1170 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, enqueuer, registry
); | 1147 addInterceptors( |
| 1148 helpers.jsUnknownJavaScriptObjectClass, enqueuer, registry); |
| 1171 } else if (cls == helpers.jsJavaScriptFunctionClass) { | 1149 } else if (cls == helpers.jsJavaScriptFunctionClass) { |
| 1172 addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer, registry); | 1150 addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer, registry); |
| 1173 } else if (isNativeOrExtendsNative(cls)) { | 1151 } else if (isNativeOrExtendsNative(cls)) { |
| 1174 addInterceptorsForNativeClassMembers(cls, enqueuer); | 1152 addInterceptorsForNativeClassMembers(cls, enqueuer); |
| 1175 } else if (cls == helpers.jsIndexingBehaviorInterface) { | 1153 } else if (cls == helpers.jsIndexingBehaviorInterface) { |
| 1176 // These two helpers are used by the emitter and the codegen. | 1154 // These two helpers are used by the emitter and the codegen. |
| 1177 // Because we cannot enqueue elements at the time of emission, | 1155 // Because we cannot enqueue elements at the time of emission, |
| 1178 // we make sure they are always generated. | 1156 // we make sure they are always generated. |
| 1179 enqueue(enqueuer, helpers.isJsIndexable, registry); | 1157 enqueue(enqueuer, helpers.isJsIndexable, registry); |
| 1180 } | 1158 } |
| 1181 | 1159 |
| 1182 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); | 1160 customElementsAnalysis.registerInstantiatedClass(cls, enqueuer); |
| 1183 if (!enqueuer.isResolutionQueue) { | 1161 if (!enqueuer.isResolutionQueue) { |
| 1184 lookupMapAnalysis.registerInstantiatedClass(cls); | 1162 lookupMapAnalysis.registerInstantiatedClass(cls); |
| 1185 } | 1163 } |
| 1186 } | 1164 } |
| 1187 | 1165 |
| 1188 void registerInstantiatedType(InterfaceType type, | 1166 void registerInstantiatedType( |
| 1189 Enqueuer enqueuer, | 1167 InterfaceType type, Enqueuer enqueuer, Registry registry, |
| 1190 Registry registry, | 1168 {bool mirrorUsage: false}) { |
| 1191 {bool mirrorUsage: false}) { | |
| 1192 lookupMapAnalysis.registerInstantiatedType(type, registry); | 1169 lookupMapAnalysis.registerInstantiatedType(type, registry); |
| 1193 super.registerInstantiatedType( | 1170 super.registerInstantiatedType(type, enqueuer, registry, |
| 1194 type, enqueuer, registry, mirrorUsage: mirrorUsage); | 1171 mirrorUsage: mirrorUsage); |
| 1195 } | 1172 } |
| 1196 | 1173 |
| 1197 void registerUseInterceptor(Enqueuer enqueuer) { | 1174 void registerUseInterceptor(Enqueuer enqueuer) { |
| 1198 assert(!enqueuer.isResolutionQueue); | 1175 assert(!enqueuer.isResolutionQueue); |
| 1199 if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; | 1176 if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; |
| 1200 Registry registry = compiler.globalDependencies; | 1177 Registry registry = compiler.globalDependencies; |
| 1201 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); | 1178 enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
| 1202 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); | 1179 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
| 1203 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); | 1180 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
| 1204 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); | 1181 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1220 if (compiler.options.enableTypeAssertions) { | 1197 if (compiler.options.enableTypeAssertions) { |
| 1221 // Unconditionally register the helper that checks if the | 1198 // Unconditionally register the helper that checks if the |
| 1222 // expression in an if/while/for is a boolean. | 1199 // expression in an if/while/for is a boolean. |
| 1223 // TODO(ngeoffray): Should we have the resolver register those instead? | 1200 // TODO(ngeoffray): Should we have the resolver register those instead? |
| 1224 Element e = helpers.boolConversionCheck; | 1201 Element e = helpers.boolConversionCheck; |
| 1225 if (e != null) enqueue(world, e, registry); | 1202 if (e != null) enqueue(world, e, registry); |
| 1226 } | 1203 } |
| 1227 | 1204 |
| 1228 if (TRACE_CALLS) { | 1205 if (TRACE_CALLS) { |
| 1229 traceHelper = TRACE_METHOD == 'console' | 1206 traceHelper = TRACE_METHOD == 'console' |
| 1230 ? helpers.consoleTraceHelper : helpers.postTraceHelper; | 1207 ? helpers.consoleTraceHelper |
| 1208 : helpers.postTraceHelper; |
| 1231 assert(traceHelper != null); | 1209 assert(traceHelper != null); |
| 1232 enqueueInResolution(traceHelper, registry); | 1210 enqueueInResolution(traceHelper, registry); |
| 1233 } | 1211 } |
| 1234 enqueueInResolution(helpers.assertUnreachableMethod, registry); | 1212 enqueueInResolution(helpers.assertUnreachableMethod, registry); |
| 1235 registerCheckedModeHelpers(registry); | 1213 registerCheckedModeHelpers(registry); |
| 1236 } | 1214 } |
| 1237 | 1215 |
| 1238 onResolutionComplete() { | 1216 onResolutionComplete() { |
| 1239 super.onResolutionComplete(); | 1217 super.onResolutionComplete(); |
| 1240 computeMembersNeededForReflection(); | 1218 computeMembersNeededForReflection(); |
| 1241 rti.computeClassesNeedingRti(); | 1219 rti.computeClassesNeedingRti(); |
| 1242 } | 1220 } |
| 1243 | 1221 |
| 1244 onTypeInferenceComplete() { | 1222 onTypeInferenceComplete() { |
| 1245 super.onTypeInferenceComplete(); | 1223 super.onTypeInferenceComplete(); |
| 1246 noSuchMethodRegistry.onTypeInferenceComplete(); | 1224 noSuchMethodRegistry.onTypeInferenceComplete(); |
| 1247 } | 1225 } |
| 1248 | 1226 |
| 1249 void registerGetRuntimeTypeArgument(Registry registry) { | 1227 void registerGetRuntimeTypeArgument(Registry registry) { |
| 1250 enqueueImpact( | 1228 enqueueImpact( |
| 1251 compiler.enqueuer.resolution, | 1229 compiler.enqueuer.resolution, impacts.getRuntimeTypeArgument, registry); |
| 1252 impacts.getRuntimeTypeArgument, | |
| 1253 registry); | |
| 1254 } | 1230 } |
| 1255 | 1231 |
| 1256 void registerCallMethodWithFreeTypeVariables( | 1232 void registerCallMethodWithFreeTypeVariables( |
| 1257 Element callMethod, | 1233 Element callMethod, Enqueuer enqueuer, Registry registry) { |
| 1258 Enqueuer enqueuer, | |
| 1259 Registry registry) { | |
| 1260 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { | 1234 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { |
| 1261 registerComputeSignature(enqueuer, registry); | 1235 registerComputeSignature(enqueuer, registry); |
| 1262 } | 1236 } |
| 1263 } | 1237 } |
| 1264 | 1238 |
| 1265 void registerClosureWithFreeTypeVariables( | 1239 void registerClosureWithFreeTypeVariables( |
| 1266 Element closure, | 1240 Element closure, Enqueuer enqueuer, Registry registry) { |
| 1267 Enqueuer enqueuer, | |
| 1268 Registry registry) { | |
| 1269 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { | 1241 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { |
| 1270 registerComputeSignature(enqueuer, registry); | 1242 registerComputeSignature(enqueuer, registry); |
| 1271 } | 1243 } |
| 1272 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); | 1244 super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry); |
| 1273 } | 1245 } |
| 1274 | 1246 |
| 1275 void registerBoundClosure(Enqueuer enqueuer) { | 1247 void registerBoundClosure(Enqueuer enqueuer) { |
| 1276 helpers.boundClosureClass.ensureResolved(resolution); | 1248 helpers.boundClosureClass.ensureResolved(resolution); |
| 1277 registerInstantiatedType( | 1249 registerInstantiatedType( |
| 1278 helpers.boundClosureClass.rawType, | 1250 helpers.boundClosureClass.rawType, |
| 1279 enqueuer, | 1251 enqueuer, |
| 1280 // Precise dependency is not important here. | 1252 // Precise dependency is not important here. |
| 1281 compiler.globalDependencies); | 1253 compiler.globalDependencies); |
| 1282 } | 1254 } |
| 1283 | 1255 |
| 1284 void registerGetOfStaticFunction(Enqueuer enqueuer) { | 1256 void registerGetOfStaticFunction(Enqueuer enqueuer) { |
| 1285 helpers.closureClass.ensureResolved(resolution); | 1257 helpers.closureClass.ensureResolved(resolution); |
| 1286 registerInstantiatedType( | 1258 registerInstantiatedType( |
| 1287 helpers.closureClass.rawType, | 1259 helpers.closureClass.rawType, enqueuer, compiler.globalDependencies); |
| 1288 enqueuer, | |
| 1289 compiler.globalDependencies); | |
| 1290 } | 1260 } |
| 1291 | 1261 |
| 1292 void registerComputeSignature(Enqueuer enqueuer, Registry registry) { | 1262 void registerComputeSignature(Enqueuer enqueuer, Registry registry) { |
| 1293 // Calls to [:computeSignature:] are generated by the emitter and we | 1263 // Calls to [:computeSignature:] are generated by the emitter and we |
| 1294 // therefore need to enqueue the used elements in the codegen enqueuer as | 1264 // therefore need to enqueue the used elements in the codegen enqueuer as |
| 1295 // well as in the resolution enqueuer. | 1265 // well as in the resolution enqueuer. |
| 1296 enqueueImpact(enqueuer, impacts.computeSignature, registry); | 1266 enqueueImpact(enqueuer, impacts.computeSignature, registry); |
| 1297 } | 1267 } |
| 1298 | 1268 |
| 1299 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { | 1269 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { |
| 1300 registerComputeSignature(enqueuer, registry); | 1270 registerComputeSignature(enqueuer, registry); |
| 1301 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); | 1271 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); |
| 1302 registerGetRuntimeTypeArgument(registry); | 1272 registerGetRuntimeTypeArgument(registry); |
| 1303 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); | 1273 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); |
| 1304 enqueueClass(enqueuer, coreClasses.listClass, registry); | 1274 enqueueClass(enqueuer, coreClasses.listClass, registry); |
| 1305 } | 1275 } |
| 1306 | 1276 |
| 1307 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 1277 void registerTypeVariableBoundsSubtypeCheck( |
| 1308 DartType bound) { | 1278 DartType typeArgument, DartType bound) { |
| 1309 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); | 1279 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); |
| 1310 } | 1280 } |
| 1311 | 1281 |
| 1312 void registerCheckDeferredIsLoaded(Registry registry) { | 1282 void registerCheckDeferredIsLoaded(Registry registry) { |
| 1313 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); | 1283 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); |
| 1314 // Also register the types of the arguments passed to this method. | 1284 // Also register the types of the arguments passed to this method. |
| 1315 enqueueClass( | 1285 enqueueClass( |
| 1316 compiler.enqueuer.resolution, coreClasses.stringClass, registry); | 1286 compiler.enqueuer.resolution, coreClasses.stringClass, registry); |
| 1317 } | 1287 } |
| 1318 | 1288 |
| 1319 void registerNoSuchMethod(FunctionElement noSuchMethod) { | 1289 void registerNoSuchMethod(FunctionElement noSuchMethod) { |
| 1320 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); | 1290 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); |
| 1321 } | 1291 } |
| 1322 | 1292 |
| 1323 /// Called when resolving a call to a foreign function. | 1293 /// Called when resolving a call to a foreign function. |
| 1324 void registerForeignCall(Send node, | 1294 void registerForeignCall(Send node, Element element, |
| 1325 Element element, | 1295 CallStructure callStructure, ForeignResolver resolver) { |
| 1326 CallStructure callStructure, | |
| 1327 ForeignResolver resolver) { | |
| 1328 native.NativeResolutionEnqueuer nativeEnqueuer = | 1296 native.NativeResolutionEnqueuer nativeEnqueuer = |
| 1329 compiler.enqueuer.resolution.nativeEnqueuer; | 1297 compiler.enqueuer.resolution.nativeEnqueuer; |
| 1330 if (element.name == 'JS') { | 1298 if (element.name == 'JS') { |
| 1331 nativeEnqueuer.registerJsCall(node, resolver); | 1299 nativeEnqueuer.registerJsCall(node, resolver); |
| 1332 } else if (element.name == 'JS_EMBEDDED_GLOBAL') { | 1300 } else if (element.name == 'JS_EMBEDDED_GLOBAL') { |
| 1333 nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver); | 1301 nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver); |
| 1334 } else if (element.name == 'JS_BUILTIN') { | 1302 } else if (element.name == 'JS_BUILTIN') { |
| 1335 nativeEnqueuer.registerJsBuiltinCall(node, resolver); | 1303 nativeEnqueuer.registerJsBuiltinCall(node, resolver); |
| 1336 } else if (element.name == 'JS_INTERCEPTOR_CONSTANT') { | 1304 } else if (element.name == 'JS_INTERCEPTOR_CONSTANT') { |
| 1337 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names | 1305 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names |
| 1338 // a class that will be instantiated outside the program by attaching a | 1306 // a class that will be instantiated outside the program by attaching a |
| 1339 // native class dispatch record referencing the interceptor. | 1307 // native class dispatch record referencing the interceptor. |
| 1340 if (!node.argumentsNode.isEmpty) { | 1308 if (!node.argumentsNode.isEmpty) { |
| 1341 Node argument = node.argumentsNode.nodes.head; | 1309 Node argument = node.argumentsNode.nodes.head; |
| 1342 ConstantExpression constant = resolver.getConstant(argument); | 1310 ConstantExpression constant = resolver.getConstant(argument); |
| 1343 if (constant != null && constant.kind == ConstantExpressionKind.TYPE) { | 1311 if (constant != null && constant.kind == ConstantExpressionKind.TYPE) { |
| 1344 TypeConstantExpression typeConstant = constant; | 1312 TypeConstantExpression typeConstant = constant; |
| 1345 if (typeConstant.type is InterfaceType) { | 1313 if (typeConstant.type is InterfaceType) { |
| 1346 resolver.registerInstantiatedType(typeConstant.type); | 1314 resolver.registerInstantiatedType(typeConstant.type); |
| 1347 return; | 1315 return; |
| 1348 } | 1316 } |
| 1349 } | 1317 } |
| 1350 } | 1318 } |
| 1351 reporter.reportErrorMessage( | 1319 reporter.reportErrorMessage( |
| 1352 node, | 1320 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
| 1353 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
| 1354 } | 1321 } |
| 1355 } | 1322 } |
| 1356 | 1323 |
| 1357 void enableNoSuchMethod(Enqueuer world) { | 1324 void enableNoSuchMethod(Enqueuer world) { |
| 1358 enqueue(world, helpers.createInvocationMirror, compiler.globalDependencies); | 1325 enqueue(world, helpers.createInvocationMirror, compiler.globalDependencies); |
| 1359 world.registerDynamicUse( | 1326 world.registerDynamicUse(new DynamicUse(Selectors.noSuchMethod_, null)); |
| 1360 new DynamicUse(Selectors.noSuchMethod_, null)); | |
| 1361 } | 1327 } |
| 1362 | 1328 |
| 1363 void enableIsolateSupport(Enqueuer enqueuer) { | 1329 void enableIsolateSupport(Enqueuer enqueuer) { |
| 1364 // TODO(floitsch): We should also ensure that the class IsolateMessage is | 1330 // TODO(floitsch): We should also ensure that the class IsolateMessage is |
| 1365 // instantiated. Currently, just enabling isolate support works. | 1331 // instantiated. Currently, just enabling isolate support works. |
| 1366 if (compiler.mainFunction != null) { | 1332 if (compiler.mainFunction != null) { |
| 1367 // The JavaScript backend implements [Isolate.spawn] by looking up | 1333 // The JavaScript backend implements [Isolate.spawn] by looking up |
| 1368 // top-level functions by name. So all top-level function tear-off | 1334 // top-level functions by name. So all top-level function tear-off |
| 1369 // closures have a private name field. | 1335 // closures have a private name field. |
| 1370 // | 1336 // |
| 1371 // The JavaScript backend of [Isolate.spawnUri] uses the same internal | 1337 // The JavaScript backend of [Isolate.spawnUri] uses the same internal |
| 1372 // implementation as [Isolate.spawn], and fails if it cannot look main up | 1338 // implementation as [Isolate.spawn], and fails if it cannot look main up |
| 1373 // by name. | 1339 // by name. |
| 1374 enqueuer.registerStaticUse( | 1340 enqueuer.registerStaticUse( |
| 1375 new StaticUse.staticTearOff(compiler.mainFunction)); | 1341 new StaticUse.staticTearOff(compiler.mainFunction)); |
| 1376 } | 1342 } |
| 1377 if (enqueuer.isResolutionQueue) { | 1343 if (enqueuer.isResolutionQueue) { |
| 1378 | |
| 1379 void enqueue(Element element) { | 1344 void enqueue(Element element) { |
| 1380 enqueuer.addToWorkList(element); | 1345 enqueuer.addToWorkList(element); |
| 1381 compiler.globalDependencies.registerDependency(element); | 1346 compiler.globalDependencies.registerDependency(element); |
| 1382 helpersUsed.add(element.declaration); | 1347 helpersUsed.add(element.declaration); |
| 1383 } | 1348 } |
| 1384 | 1349 |
| 1385 enqueue(helpers.startRootIsolate); | 1350 enqueue(helpers.startRootIsolate); |
| 1386 enqueue(helpers.currentIsolate); | 1351 enqueue(helpers.currentIsolate); |
| 1387 enqueue(helpers.callInIsolate); | 1352 enqueue(helpers.callInIsolate); |
| 1388 } else { | 1353 } else { |
| 1389 enqueuer.addToWorkList(helpers.startRootIsolate); | 1354 enqueuer.addToWorkList(helpers.startRootIsolate); |
| 1390 } | 1355 } |
| 1391 } | 1356 } |
| 1392 | 1357 |
| 1393 bool classNeedsRti(ClassElement cls) { | 1358 bool classNeedsRti(ClassElement cls) { |
| 1394 return rti.classesNeedingRti.contains(cls.declaration) || | 1359 return rti.classesNeedingRti.contains(cls.declaration) || |
| 1395 compiler.enabledRuntimeType; | 1360 compiler.enabledRuntimeType; |
| 1396 } | 1361 } |
| 1397 | 1362 |
| 1398 bool isComplexNoSuchMethod(FunctionElement element) => | 1363 bool isComplexNoSuchMethod(FunctionElement element) => |
| 1399 noSuchMethodRegistry.isComplex(element); | 1364 noSuchMethodRegistry.isComplex(element); |
| 1400 | 1365 |
| 1401 bool isDefaultEqualityImplementation(Element element) { | 1366 bool isDefaultEqualityImplementation(Element element) { |
| 1402 assert(element.name == '=='); | 1367 assert(element.name == '=='); |
| 1403 ClassElement classElement = element.enclosingClass; | 1368 ClassElement classElement = element.enclosingClass; |
| 1404 return classElement == coreClasses.objectClass | 1369 return classElement == coreClasses.objectClass || |
| 1405 || classElement == helpers.jsInterceptorClass | 1370 classElement == helpers.jsInterceptorClass || |
| 1406 || classElement == helpers.jsNullClass; | 1371 classElement == helpers.jsNullClass; |
| 1407 } | 1372 } |
| 1408 | 1373 |
| 1409 bool methodNeedsRti(FunctionElement function) { | 1374 bool methodNeedsRti(FunctionElement function) { |
| 1410 return rti.methodsNeedingRti.contains(function) || | 1375 return rti.methodsNeedingRti.contains(function) || |
| 1411 compiler.enabledRuntimeType; | 1376 compiler.enabledRuntimeType; |
| 1412 } | 1377 } |
| 1413 | 1378 |
| 1414 /// Enqueue [e] in [enqueuer]. | 1379 /// Enqueue [e] in [enqueuer]. |
| 1415 /// | 1380 /// |
| 1416 /// This method calls [registerBackendUse]. | 1381 /// This method calls [registerBackendUse]. |
| 1417 void enqueue(Enqueuer enqueuer, Element e, Registry registry) { | 1382 void enqueue(Enqueuer enqueuer, Element e, Registry registry) { |
| 1418 if (e == null) return; | 1383 if (e == null) return; |
| 1419 registerBackendUse(e); | 1384 registerBackendUse(e); |
| 1420 enqueuer.addToWorkList(e); | 1385 enqueuer.addToWorkList(e); |
| 1421 registry.registerDependency(e); | 1386 registry.registerDependency(e); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1452 ClassElement cls = type.element; | 1417 ClassElement cls = type.element; |
| 1453 registerBackendUse(cls); | 1418 registerBackendUse(cls); |
| 1454 helpersUsed.add(cls.declaration); | 1419 helpersUsed.add(cls.declaration); |
| 1455 if (cls.declaration != cls.implementation) { | 1420 if (cls.declaration != cls.implementation) { |
| 1456 helpersUsed.add(cls.implementation); | 1421 helpersUsed.add(cls.implementation); |
| 1457 } | 1422 } |
| 1458 cls.ensureResolved(resolution); | 1423 cls.ensureResolved(resolution); |
| 1459 registerInstantiatedType(type, enqueuer, registry); | 1424 registerInstantiatedType(type, enqueuer, registry); |
| 1460 } | 1425 } |
| 1461 | 1426 |
| 1462 void enqueueImpact(Enqueuer enqueuer, | 1427 void enqueueImpact( |
| 1463 BackendImpact impact, | 1428 Enqueuer enqueuer, BackendImpact impact, Registry registry) { |
| 1464 Registry registry) { | |
| 1465 for (Element staticUse in impact.staticUses) { | 1429 for (Element staticUse in impact.staticUses) { |
| 1466 enqueue(enqueuer, staticUse, registry); | 1430 enqueue(enqueuer, staticUse, registry); |
| 1467 } | 1431 } |
| 1468 for (InterfaceType type in impact.instantiatedTypes) { | 1432 for (InterfaceType type in impact.instantiatedTypes) { |
| 1469 enqueueType(enqueuer, type, registry); | 1433 enqueueType(enqueuer, type, registry); |
| 1470 } | 1434 } |
| 1471 for (ClassElement cls in impact.instantiatedClasses) { | 1435 for (ClassElement cls in impact.instantiatedClasses) { |
| 1472 enqueueClass(enqueuer, cls, registry); | 1436 enqueueClass(enqueuer, cls, registry); |
| 1473 } | 1437 } |
| 1474 for (BackendImpact otherImpact in impact.otherImpacts) { | 1438 for (BackendImpact otherImpact in impact.otherImpacts) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1495 if (kind.category == ElementCategory.VARIABLE) { | 1459 if (kind.category == ElementCategory.VARIABLE) { |
| 1496 ConstantValue initialValue = | 1460 ConstantValue initialValue = |
| 1497 constants.getConstantValueForVariable(element); | 1461 constants.getConstantValueForVariable(element); |
| 1498 if (initialValue != null) { | 1462 if (initialValue != null) { |
| 1499 registerCompileTimeConstant(initialValue, work.registry); | 1463 registerCompileTimeConstant(initialValue, work.registry); |
| 1500 addCompileTimeConstantForEmission(initialValue); | 1464 addCompileTimeConstantForEmission(initialValue); |
| 1501 // We don't need to generate code for static or top-level | 1465 // We don't need to generate code for static or top-level |
| 1502 // variables. For instance variables, we may need to generate | 1466 // variables. For instance variables, we may need to generate |
| 1503 // the checked setter. | 1467 // the checked setter. |
| 1504 if (Elements.isStaticOrTopLevel(element)) { | 1468 if (Elements.isStaticOrTopLevel(element)) { |
| 1505 return impactTransformer.transformCodegenImpact( | 1469 return impactTransformer |
| 1506 work.registry.worldImpact); | 1470 .transformCodegenImpact(work.registry.worldImpact); |
| 1507 } | 1471 } |
| 1508 } else { | 1472 } else { |
| 1509 // If the constant-handler was not able to produce a result we have to | 1473 // If the constant-handler was not able to produce a result we have to |
| 1510 // go through the builder (below) to generate the lazy initializer for | 1474 // go through the builder (below) to generate the lazy initializer for |
| 1511 // the static variable. | 1475 // the static variable. |
| 1512 // We also need to register the use of the cyclic-error helper. | 1476 // We also need to register the use of the cyclic-error helper. |
| 1513 compiler.enqueuer.codegen.registerStaticUse( | 1477 compiler.enqueuer.codegen.registerStaticUse(new StaticUse.staticInvoke( |
| 1514 new StaticUse.staticInvoke( | 1478 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); |
| 1515 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); | |
| 1516 } | 1479 } |
| 1517 } | 1480 } |
| 1518 | 1481 |
| 1519 jsAst.Fun function = functionCompiler.compile(work); | 1482 jsAst.Fun function = functionCompiler.compile(work); |
| 1520 if (function.sourceInformation == null) { | 1483 if (function.sourceInformation == null) { |
| 1521 function = function.withSourceInformation( | 1484 function = function.withSourceInformation( |
| 1522 sourceInformationStrategy.buildSourceMappedMarker()); | 1485 sourceInformationStrategy.buildSourceMappedMarker()); |
| 1523 } | 1486 } |
| 1524 generatedCode[element] = function; | 1487 generatedCode[element] = function; |
| 1525 WorldImpact worldImpact = | 1488 WorldImpact worldImpact = |
| 1526 impactTransformer.transformCodegenImpact(work.registry.worldImpact); | 1489 impactTransformer.transformCodegenImpact(work.registry.worldImpact); |
| 1527 compiler.dumpInfoTask.registerImpact(element, worldImpact); | 1490 compiler.dumpInfoTask.registerImpact(element, worldImpact); |
| 1528 return worldImpact; | 1491 return worldImpact; |
| 1529 } | 1492 } |
| 1530 | 1493 |
| 1531 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { | 1494 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { |
| 1532 return new native.NativeResolutionEnqueuer(world, compiler); | 1495 return new native.NativeResolutionEnqueuer(world, compiler); |
| 1533 } | 1496 } |
| 1534 | 1497 |
| 1535 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1498 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { |
| 1536 return new native.NativeCodegenEnqueuer(world, compiler, emitter); | 1499 return new native.NativeCodegenEnqueuer(world, compiler, emitter); |
| 1537 } | 1500 } |
| 1538 | 1501 |
| 1539 ClassElement defaultSuperclass(ClassElement element) { | 1502 ClassElement defaultSuperclass(ClassElement element) { |
| 1540 if (isJsInterop(element)) { | 1503 if (isJsInterop(element)) { |
| 1541 return helpers.jsJavaScriptObjectClass; | 1504 return helpers.jsJavaScriptObjectClass; |
| 1542 } | 1505 } |
| 1543 // Native classes inherit from Interceptor. | 1506 // Native classes inherit from Interceptor. |
| 1544 return isNative(element) | 1507 return isNative(element) |
| 1545 ? helpers.jsInterceptorClass : coreClasses.objectClass; | 1508 ? helpers.jsInterceptorClass |
| 1509 : coreClasses.objectClass; |
| 1546 } | 1510 } |
| 1547 | 1511 |
| 1548 /** | 1512 /** |
| 1549 * Unit test hook that returns code of an element as a String. | 1513 * Unit test hook that returns code of an element as a String. |
| 1550 * | 1514 * |
| 1551 * Invariant: [element] must be a declaration element. | 1515 * Invariant: [element] must be a declaration element. |
| 1552 */ | 1516 */ |
| 1553 String getGeneratedCode(Element element) { | 1517 String getGeneratedCode(Element element) { |
| 1554 assert(invariant(element, element.isDeclaration)); | 1518 assert(invariant(element, element.isDeclaration)); |
| 1555 return jsAst.prettyPrint(generatedCode[element], compiler); | 1519 return jsAst.prettyPrint(generatedCode[element], compiler); |
| 1556 } | 1520 } |
| 1557 | 1521 |
| 1558 int assembleProgram() { | 1522 int assembleProgram() { |
| 1559 int programSize = emitter.assembleProgram(); | 1523 int programSize = emitter.assembleProgram(); |
| 1560 noSuchMethodRegistry.emitDiagnostic(); | 1524 noSuchMethodRegistry.emitDiagnostic(); |
| 1561 int totalMethodCount = generatedCode.length; | 1525 int totalMethodCount = generatedCode.length; |
| 1562 if (totalMethodCount != preMirrorsMethodCount) { | 1526 if (totalMethodCount != preMirrorsMethodCount) { |
| 1563 int mirrorCount = totalMethodCount - preMirrorsMethodCount; | 1527 int mirrorCount = totalMethodCount - preMirrorsMethodCount; |
| 1564 double percentage = (mirrorCount / totalMethodCount) * 100; | 1528 double percentage = (mirrorCount / totalMethodCount) * 100; |
| 1565 DiagnosticMessage hint = reporter.createMessage( | 1529 DiagnosticMessage hint = |
| 1566 compiler.mainApp, MessageKind.MIRROR_BLOAT, | 1530 reporter.createMessage(compiler.mainApp, MessageKind.MIRROR_BLOAT, { |
| 1567 {'count': mirrorCount, | 1531 'count': mirrorCount, |
| 1568 'total': totalMethodCount, | 1532 'total': totalMethodCount, |
| 1569 'percentage': percentage.round()}); | 1533 'percentage': percentage.round() |
| 1534 }); |
| 1570 | 1535 |
| 1571 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 1536 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 1572 for (LibraryElement library in compiler.libraryLoader.libraries) { | 1537 for (LibraryElement library in compiler.libraryLoader.libraries) { |
| 1573 if (library.isInternalLibrary) continue; | 1538 if (library.isInternalLibrary) continue; |
| 1574 for (ImportElement import in library.imports) { | 1539 for (ImportElement import in library.imports) { |
| 1575 LibraryElement importedLibrary = import.importedLibrary; | 1540 LibraryElement importedLibrary = import.importedLibrary; |
| 1576 if (importedLibrary != compiler.mirrorsLibrary) continue; | 1541 if (importedLibrary != compiler.mirrorsLibrary) continue; |
| 1577 MessageKind kind = | 1542 MessageKind kind = |
| 1578 compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library) | 1543 compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library) |
| 1579 ? MessageKind.MIRROR_IMPORT | 1544 ? MessageKind.MIRROR_IMPORT |
| 1580 : MessageKind.MIRROR_IMPORT_NO_USAGE; | 1545 : MessageKind.MIRROR_IMPORT_NO_USAGE; |
| 1581 reporter.withCurrentElement(library, () { | 1546 reporter.withCurrentElement(library, () { |
| 1582 infos.add(reporter.createMessage(import, kind)); | 1547 infos.add(reporter.createMessage(import, kind)); |
| 1583 }); | 1548 }); |
| 1584 } | 1549 } |
| 1585 } | 1550 } |
| 1586 reporter.reportHint(hint, infos); | 1551 reporter.reportHint(hint, infos); |
| 1587 } | 1552 } |
| 1588 return programSize; | 1553 return programSize; |
| 1589 } | 1554 } |
| 1590 | 1555 |
| 1591 Element getDartClass(Element element) { | 1556 Element getDartClass(Element element) { |
| 1592 for (ClassElement dartClass in implementationClasses.keys) { | 1557 for (ClassElement dartClass in implementationClasses.keys) { |
| 1593 if (element == implementationClasses[dartClass]) { | 1558 if (element == implementationClasses[dartClass]) { |
| 1594 return dartClass; | 1559 return dartClass; |
| 1595 } | 1560 } |
| 1596 } | 1561 } |
| 1597 return element; | 1562 return element; |
| 1598 } | 1563 } |
| 1599 | 1564 |
| 1600 /** | 1565 /** |
| 1601 * Returns the checked mode helper that will be needed to do a type check/type | 1566 * Returns the checked mode helper that will be needed to do a type check/type |
| 1602 * cast on [type] at runtime. Note that this method is being called both by | 1567 * cast on [type] at runtime. Note that this method is being called both by |
| 1603 * the resolver with interface types (int, String, ...), and by the SSA | 1568 * the resolver with interface types (int, String, ...), and by the SSA |
| 1604 * backend with implementation types (JSInt, JSString, ...). | 1569 * backend with implementation types (JSInt, JSString, ...). |
| 1605 */ | 1570 */ |
| 1606 CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) { | 1571 CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) { |
| 1607 return getCheckedModeHelperInternal( | 1572 return getCheckedModeHelperInternal(type, |
| 1608 type, typeCast: typeCast, nativeCheckOnly: false); | 1573 typeCast: typeCast, nativeCheckOnly: false); |
| 1609 } | 1574 } |
| 1610 | 1575 |
| 1611 /** | 1576 /** |
| 1612 * Returns the native checked mode helper that will be needed to do a type | 1577 * Returns the native checked mode helper that will be needed to do a type |
| 1613 * check/type cast on [type] at runtime. If no native helper exists for | 1578 * check/type cast on [type] at runtime. If no native helper exists for |
| 1614 * [type], [:null:] is returned. | 1579 * [type], [:null:] is returned. |
| 1615 */ | 1580 */ |
| 1616 CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) { | 1581 CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) { |
| 1617 return getCheckedModeHelperInternal( | 1582 return getCheckedModeHelperInternal(type, |
| 1618 type, typeCast: typeCast, nativeCheckOnly: true); | 1583 typeCast: typeCast, nativeCheckOnly: true); |
| 1619 } | 1584 } |
| 1620 | 1585 |
| 1621 /** | 1586 /** |
| 1622 * Returns the checked mode helper for the type check/type cast for [type]. If | 1587 * Returns the checked mode helper for the type check/type cast for [type]. If |
| 1623 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. | 1588 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. |
| 1624 */ | 1589 */ |
| 1625 CheckedModeHelper getCheckedModeHelperInternal(DartType type, | 1590 CheckedModeHelper getCheckedModeHelperInternal(DartType type, |
| 1626 {bool typeCast, | 1591 {bool typeCast, bool nativeCheckOnly}) { |
| 1627 bool nativeCheckOnly}) { | |
| 1628 String name = getCheckedModeHelperNameInternal(type, | 1592 String name = getCheckedModeHelperNameInternal(type, |
| 1629 typeCast: typeCast, nativeCheckOnly: nativeCheckOnly); | 1593 typeCast: typeCast, nativeCheckOnly: nativeCheckOnly); |
| 1630 if (name == null) return null; | 1594 if (name == null) return null; |
| 1631 CheckedModeHelper helper = checkedModeHelperByName[name]; | 1595 CheckedModeHelper helper = checkedModeHelperByName[name]; |
| 1632 assert(helper != null); | 1596 assert(helper != null); |
| 1633 return helper; | 1597 return helper; |
| 1634 } | 1598 } |
| 1635 | 1599 |
| 1636 String getCheckedModeHelperNameInternal(DartType type, | 1600 String getCheckedModeHelperNameInternal(DartType type, |
| 1637 {bool typeCast, | 1601 {bool typeCast, bool nativeCheckOnly}) { |
| 1638 bool nativeCheckOnly}) { | |
| 1639 assert(type.kind != TypeKind.TYPEDEF); | 1602 assert(type.kind != TypeKind.TYPEDEF); |
| 1640 if (type.isMalformed) { | 1603 if (type.isMalformed) { |
| 1641 // The same error is thrown for type test and type cast of a malformed | 1604 // The same error is thrown for type test and type cast of a malformed |
| 1642 // type so we only need one check method. | 1605 // type so we only need one check method. |
| 1643 return 'checkMalformedType'; | 1606 return 'checkMalformedType'; |
| 1644 } | 1607 } |
| 1645 Element element = type.element; | 1608 Element element = type.element; |
| 1646 bool nativeCheck = nativeCheckOnly || | 1609 bool nativeCheck = |
| 1647 emitter.nativeEmitter.requiresNativeIsCheck(element); | 1610 nativeCheckOnly || emitter.nativeEmitter.requiresNativeIsCheck(element); |
| 1648 | 1611 |
| 1649 // TODO(13955), TODO(9731). The test for non-primitive types should use an | 1612 // TODO(13955), TODO(9731). The test for non-primitive types should use an |
| 1650 // interceptor. The interceptor should be an argument to HTypeConversion so | 1613 // interceptor. The interceptor should be an argument to HTypeConversion so |
| 1651 // that it can be optimized by standard interceptor optimizations. | 1614 // that it can be optimized by standard interceptor optimizations. |
| 1652 nativeCheck = true; | 1615 nativeCheck = true; |
| 1653 | 1616 |
| 1654 if (type.isVoid) { | 1617 if (type.isVoid) { |
| 1655 assert(!typeCast); // Cannot cast to void. | 1618 assert(!typeCast); // Cannot cast to void. |
| 1656 if (nativeCheckOnly) return null; | 1619 if (nativeCheckOnly) return null; |
| 1657 return 'voidTypeCheck'; | 1620 return 'voidTypeCheck'; |
| 1658 } else if (element == helpers.jsStringClass || | 1621 } else if (element == helpers.jsStringClass || |
| 1659 element == coreClasses.stringClass) { | 1622 element == coreClasses.stringClass) { |
| 1660 if (nativeCheckOnly) return null; | 1623 if (nativeCheckOnly) return null; |
| 1661 return typeCast | 1624 return typeCast ? 'stringTypeCast' : 'stringTypeCheck'; |
| 1662 ? 'stringTypeCast' | |
| 1663 : 'stringTypeCheck'; | |
| 1664 } else if (element == helpers.jsDoubleClass || | 1625 } else if (element == helpers.jsDoubleClass || |
| 1665 element == coreClasses.doubleClass) { | 1626 element == coreClasses.doubleClass) { |
| 1666 if (nativeCheckOnly) return null; | 1627 if (nativeCheckOnly) return null; |
| 1667 return typeCast | 1628 return typeCast ? 'doubleTypeCast' : 'doubleTypeCheck'; |
| 1668 ? 'doubleTypeCast' | |
| 1669 : 'doubleTypeCheck'; | |
| 1670 } else if (element == helpers.jsNumberClass || | 1629 } else if (element == helpers.jsNumberClass || |
| 1671 element == coreClasses.numClass) { | 1630 element == coreClasses.numClass) { |
| 1672 if (nativeCheckOnly) return null; | 1631 if (nativeCheckOnly) return null; |
| 1673 return typeCast | 1632 return typeCast ? 'numTypeCast' : 'numTypeCheck'; |
| 1674 ? 'numTypeCast' | |
| 1675 : 'numTypeCheck'; | |
| 1676 } else if (element == helpers.jsBoolClass || | 1633 } else if (element == helpers.jsBoolClass || |
| 1677 element == coreClasses.boolClass) { | 1634 element == coreClasses.boolClass) { |
| 1678 if (nativeCheckOnly) return null; | 1635 if (nativeCheckOnly) return null; |
| 1679 return typeCast | 1636 return typeCast ? 'boolTypeCast' : 'boolTypeCheck'; |
| 1680 ? 'boolTypeCast' | |
| 1681 : 'boolTypeCheck'; | |
| 1682 } else if (element == helpers.jsIntClass || | 1637 } else if (element == helpers.jsIntClass || |
| 1683 element == coreClasses.intClass || | 1638 element == coreClasses.intClass || |
| 1684 element == helpers.jsUInt32Class || | 1639 element == helpers.jsUInt32Class || |
| 1685 element == helpers.jsUInt31Class || | 1640 element == helpers.jsUInt31Class || |
| 1686 element == helpers.jsPositiveIntClass) { | 1641 element == helpers.jsPositiveIntClass) { |
| 1687 if (nativeCheckOnly) return null; | 1642 if (nativeCheckOnly) return null; |
| 1688 return typeCast | 1643 return typeCast ? 'intTypeCast' : 'intTypeCheck'; |
| 1689 ? 'intTypeCast' | |
| 1690 : 'intTypeCheck'; | |
| 1691 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { | 1644 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { |
| 1692 if (nativeCheck) { | 1645 if (nativeCheck) { |
| 1693 return typeCast | 1646 return typeCast |
| 1694 ? 'numberOrStringSuperNativeTypeCast' | 1647 ? 'numberOrStringSuperNativeTypeCast' |
| 1695 : 'numberOrStringSuperNativeTypeCheck'; | 1648 : 'numberOrStringSuperNativeTypeCheck'; |
| 1696 } else { | 1649 } else { |
| 1697 return typeCast | 1650 return typeCast |
| 1698 ? 'numberOrStringSuperTypeCast' | 1651 ? 'numberOrStringSuperTypeCast' |
| 1699 : 'numberOrStringSuperTypeCheck'; | 1652 : 'numberOrStringSuperTypeCheck'; |
| 1700 } | 1653 } |
| 1701 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 1654 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
| 1702 if (nativeCheck) { | 1655 if (nativeCheck) { |
| 1703 return typeCast | 1656 return typeCast |
| 1704 ? 'stringSuperNativeTypeCast' | 1657 ? 'stringSuperNativeTypeCast' |
| 1705 : 'stringSuperNativeTypeCheck'; | 1658 : 'stringSuperNativeTypeCheck'; |
| 1706 } else { | 1659 } else { |
| 1707 return typeCast | 1660 return typeCast ? 'stringSuperTypeCast' : 'stringSuperTypeCheck'; |
| 1708 ? 'stringSuperTypeCast' | |
| 1709 : 'stringSuperTypeCheck'; | |
| 1710 } | 1661 } |
| 1711 } else if ((element == coreClasses.listClass || | 1662 } else if ((element == coreClasses.listClass || |
| 1712 element == helpers.jsArrayClass) && | 1663 element == helpers.jsArrayClass) && |
| 1713 type.treatAsRaw) { | 1664 type.treatAsRaw) { |
| 1714 if (nativeCheckOnly) return null; | 1665 if (nativeCheckOnly) return null; |
| 1715 return typeCast | 1666 return typeCast ? 'listTypeCast' : 'listTypeCheck'; |
| 1716 ? 'listTypeCast' | |
| 1717 : 'listTypeCheck'; | |
| 1718 } else { | 1667 } else { |
| 1719 if (Elements.isListSupertype(element, compiler)) { | 1668 if (Elements.isListSupertype(element, compiler)) { |
| 1720 if (nativeCheck) { | 1669 if (nativeCheck) { |
| 1721 return typeCast | 1670 return typeCast |
| 1722 ? 'listSuperNativeTypeCast' | 1671 ? 'listSuperNativeTypeCast' |
| 1723 : 'listSuperNativeTypeCheck'; | 1672 : 'listSuperNativeTypeCheck'; |
| 1724 } else { | 1673 } else { |
| 1725 return typeCast | 1674 return typeCast ? 'listSuperTypeCast' : 'listSuperTypeCheck'; |
| 1726 ? 'listSuperTypeCast' | |
| 1727 : 'listSuperTypeCheck'; | |
| 1728 } | 1675 } |
| 1729 } else { | 1676 } else { |
| 1730 if (type.isInterfaceType && !type.treatAsRaw) { | 1677 if (type.isInterfaceType && !type.treatAsRaw) { |
| 1731 return typeCast | 1678 return typeCast ? 'subtypeCast' : 'assertSubtype'; |
| 1732 ? 'subtypeCast' | |
| 1733 : 'assertSubtype'; | |
| 1734 } else if (type.isTypeVariable) { | 1679 } else if (type.isTypeVariable) { |
| 1735 return typeCast | 1680 return typeCast |
| 1736 ? 'subtypeOfRuntimeTypeCast' | 1681 ? 'subtypeOfRuntimeTypeCast' |
| 1737 : 'assertSubtypeOfRuntimeType'; | 1682 : 'assertSubtypeOfRuntimeType'; |
| 1738 } else if (type.isFunctionType) { | 1683 } else if (type.isFunctionType) { |
| 1739 return null; | 1684 return null; |
| 1740 } else { | 1685 } else { |
| 1741 if (nativeCheck) { | 1686 if (nativeCheck) { |
| 1742 // TODO(karlklose): can we get rid of this branch when we use | 1687 // TODO(karlklose): can we get rid of this branch when we use |
| 1743 // interceptors? | 1688 // interceptors? |
| 1744 return typeCast | 1689 return typeCast ? 'interceptedTypeCast' : 'interceptedTypeCheck'; |
| 1745 ? 'interceptedTypeCast' | |
| 1746 : 'interceptedTypeCheck'; | |
| 1747 } else { | 1690 } else { |
| 1748 return typeCast | 1691 return typeCast ? 'propertyTypeCast' : 'propertyTypeCheck'; |
| 1749 ? 'propertyTypeCast' | |
| 1750 : 'propertyTypeCheck'; | |
| 1751 } | 1692 } |
| 1752 } | 1693 } |
| 1753 } | 1694 } |
| 1754 } | 1695 } |
| 1755 } | 1696 } |
| 1756 | 1697 |
| 1757 void registerCheckedModeHelpers(Registry registry) { | 1698 void registerCheckedModeHelpers(Registry registry) { |
| 1758 // We register all the helpers in the resolution queue. | 1699 // We register all the helpers in the resolution queue. |
| 1759 // TODO(13155): Find a way to register fewer helpers. | 1700 // TODO(13155): Find a way to register fewer helpers. |
| 1760 for (CheckedModeHelper helper in checkedModeHelpers) { | 1701 for (CheckedModeHelper helper in checkedModeHelpers) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 } else if (element == helpers.preserveUrisMarker) { | 1765 } else if (element == helpers.preserveUrisMarker) { |
| 1825 if (compiler.options.preserveUris) mustPreserveUris = true; | 1766 if (compiler.options.preserveUris) mustPreserveUris = true; |
| 1826 } else if (element == helpers.preserveLibraryNamesMarker) { | 1767 } else if (element == helpers.preserveLibraryNamesMarker) { |
| 1827 mustRetainLibraryNames = true; | 1768 mustRetainLibraryNames = true; |
| 1828 } else if (element == helpers.getIsolateAffinityTagMarker) { | 1769 } else if (element == helpers.getIsolateAffinityTagMarker) { |
| 1829 needToInitializeIsolateAffinityTag = true; | 1770 needToInitializeIsolateAffinityTag = true; |
| 1830 } else if (element.isDeferredLoaderGetter) { | 1771 } else if (element.isDeferredLoaderGetter) { |
| 1831 // TODO(sigurdm): Create a function registerLoadLibraryAccess. | 1772 // TODO(sigurdm): Create a function registerLoadLibraryAccess. |
| 1832 if (compiler.loadLibraryFunction == null) { | 1773 if (compiler.loadLibraryFunction == null) { |
| 1833 compiler.loadLibraryFunction = helpers.loadLibraryWrapper; | 1774 compiler.loadLibraryFunction = helpers.loadLibraryWrapper; |
| 1834 enqueueInResolution(compiler.loadLibraryFunction, | 1775 enqueueInResolution( |
| 1835 compiler.globalDependencies); | 1776 compiler.loadLibraryFunction, compiler.globalDependencies); |
| 1836 } | 1777 } |
| 1837 } else if (element == helpers.requiresPreambleMarker) { | 1778 } else if (element == helpers.requiresPreambleMarker) { |
| 1838 requiresPreamble = true; | 1779 requiresPreamble = true; |
| 1839 } | 1780 } |
| 1840 customElementsAnalysis.registerStaticUse(element, enqueuer); | 1781 customElementsAnalysis.registerStaticUse(element, enqueuer); |
| 1841 } | 1782 } |
| 1842 | 1783 |
| 1843 /// Called when [:const Symbol(name):] is seen. | 1784 /// Called when [:const Symbol(name):] is seen. |
| 1844 void registerConstSymbol(String name) { | 1785 void registerConstSymbol(String name) { |
| 1845 symbolsUsed.add(name); | 1786 symbolsUsed.add(name); |
| 1846 if (name.endsWith('=')) { | 1787 if (name.endsWith('=')) { |
| 1847 symbolsUsed.add(name.substring(0, name.length - 1)); | 1788 symbolsUsed.add(name.substring(0, name.length - 1)); |
| 1848 } | 1789 } |
| 1849 } | 1790 } |
| 1850 | 1791 |
| 1851 /// Called when [:new Symbol(...):] is seen. | 1792 /// Called when [:new Symbol(...):] is seen. |
| 1852 void registerNewSymbol(Registry registry) { | 1793 void registerNewSymbol(Registry registry) {} |
| 1853 } | |
| 1854 | 1794 |
| 1855 /// Should [element] (a getter) that would normally not be generated due to | 1795 /// Should [element] (a getter) that would normally not be generated due to |
| 1856 /// treeshaking be retained for reflection? | 1796 /// treeshaking be retained for reflection? |
| 1857 bool shouldRetainGetter(Element element) { | 1797 bool shouldRetainGetter(Element element) { |
| 1858 return isTreeShakingDisabled && isAccessibleByReflection(element); | 1798 return isTreeShakingDisabled && isAccessibleByReflection(element); |
| 1859 } | 1799 } |
| 1860 | 1800 |
| 1861 /// Should [element] (a setter) hat would normally not be generated due to | 1801 /// Should [element] (a setter) hat would normally not be generated due to |
| 1862 /// treeshaking be retained for reflection? | 1802 /// treeshaking be retained for reflection? |
| 1863 bool shouldRetainSetter(Element element) { | 1803 bool shouldRetainSetter(Element element) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1923 implementationClasses = <ClassElement, ClassElement>{}; | 1863 implementationClasses = <ClassElement, ClassElement>{}; |
| 1924 implementationClasses[coreClasses.intClass] = helpers.jsIntClass; | 1864 implementationClasses[coreClasses.intClass] = helpers.jsIntClass; |
| 1925 implementationClasses[coreClasses.boolClass] = helpers.jsBoolClass; | 1865 implementationClasses[coreClasses.boolClass] = helpers.jsBoolClass; |
| 1926 implementationClasses[coreClasses.numClass] = helpers.jsNumberClass; | 1866 implementationClasses[coreClasses.numClass] = helpers.jsNumberClass; |
| 1927 implementationClasses[coreClasses.doubleClass] = helpers.jsDoubleClass; | 1867 implementationClasses[coreClasses.doubleClass] = helpers.jsDoubleClass; |
| 1928 implementationClasses[coreClasses.stringClass] = helpers.jsStringClass; | 1868 implementationClasses[coreClasses.stringClass] = helpers.jsStringClass; |
| 1929 implementationClasses[coreClasses.listClass] = helpers.jsArrayClass; | 1869 implementationClasses[coreClasses.listClass] = helpers.jsArrayClass; |
| 1930 implementationClasses[coreClasses.nullClass] = helpers.jsNullClass; | 1870 implementationClasses[coreClasses.nullClass] = helpers.jsNullClass; |
| 1931 | 1871 |
| 1932 // These methods are overwritten with generated versions. | 1872 // These methods are overwritten with generated versions. |
| 1933 inlineCache.markAsNonInlinable( | 1873 inlineCache.markAsNonInlinable(helpers.getInterceptorMethod, |
| 1934 helpers.getInterceptorMethod, insideLoop: true); | 1874 insideLoop: true); |
| 1935 | 1875 |
| 1936 specialOperatorEqClasses | 1876 specialOperatorEqClasses |
| 1937 ..add(coreClasses.objectClass) | 1877 ..add(coreClasses.objectClass) |
| 1938 ..add(helpers.jsInterceptorClass) | 1878 ..add(helpers.jsInterceptorClass) |
| 1939 ..add(helpers.jsNullClass); | 1879 ..add(helpers.jsNullClass); |
| 1940 | 1880 |
| 1941 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); | 1881 validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass); |
| 1942 // The null-interceptor must also implement *all* methods. | 1882 // The null-interceptor must also implement *all* methods. |
| 1943 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); | 1883 validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass); |
| 1944 | 1884 |
| 1945 return new Future.value(); | 1885 return new Future.value(); |
| 1946 } | 1886 } |
| 1947 | 1887 |
| 1948 void registerMirrorUsage(Set<String> symbols, | 1888 void registerMirrorUsage( |
| 1949 Set<Element> targets, | 1889 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { |
| 1950 Set<Element> metaTargets) { | |
| 1951 if (symbols == null && targets == null && metaTargets == null) { | 1890 if (symbols == null && targets == null && metaTargets == null) { |
| 1952 // The user didn't specify anything, or there are imports of | 1891 // The user didn't specify anything, or there are imports of |
| 1953 // 'dart:mirrors' without @MirrorsUsed. | 1892 // 'dart:mirrors' without @MirrorsUsed. |
| 1954 hasInsufficientMirrorsUsed = true; | 1893 hasInsufficientMirrorsUsed = true; |
| 1955 return; | 1894 return; |
| 1956 } | 1895 } |
| 1957 if (symbols != null) symbolsUsed.addAll(symbols); | 1896 if (symbols != null) symbolsUsed.addAll(symbols); |
| 1958 if (targets != null) { | 1897 if (targets != null) { |
| 1959 for (Element target in targets) { | 1898 for (Element target in targets) { |
| 1960 if (target.isAbstractField) { | 1899 if (target.isAbstractField) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1985 return membersNeededForReflection.contains(element); | 1924 return membersNeededForReflection.contains(element); |
| 1986 } | 1925 } |
| 1987 | 1926 |
| 1988 /** | 1927 /** |
| 1989 * Returns true if the element has to be resolved due to a mirrorsUsed | 1928 * Returns true if the element has to be resolved due to a mirrorsUsed |
| 1990 * annotation. If we have insufficient mirrors used annotations, we only | 1929 * annotation. If we have insufficient mirrors used annotations, we only |
| 1991 * keep additonal elements if treeshaking has been disabled. | 1930 * keep additonal elements if treeshaking has been disabled. |
| 1992 */ | 1931 */ |
| 1993 bool requiredByMirrorSystem(Element element) { | 1932 bool requiredByMirrorSystem(Element element) { |
| 1994 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || | 1933 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
| 1995 matchesMirrorsMetaTarget(element) || | 1934 matchesMirrorsMetaTarget(element) || |
| 1996 targetsUsed.contains(element); | 1935 targetsUsed.contains(element); |
| 1997 } | 1936 } |
| 1998 | 1937 |
| 1999 /** | 1938 /** |
| 2000 * Returns true if the element matches a mirrorsUsed annotation. If | 1939 * Returns true if the element matches a mirrorsUsed annotation. If |
| 2001 * we have insufficient mirrorsUsed information, this returns true for | 1940 * we have insufficient mirrorsUsed information, this returns true for |
| 2002 * all elements, as they might all be potentially referenced. | 1941 * all elements, as they might all be potentially referenced. |
| 2003 */ | 1942 */ |
| 2004 bool referencedFromMirrorSystem(Element element, [recursive = true]) { | 1943 bool referencedFromMirrorSystem(Element element, [recursive = true]) { |
| 2005 Element enclosing = recursive ? element.enclosingElement : null; | 1944 Element enclosing = recursive ? element.enclosingElement : null; |
| 2006 | 1945 |
| 2007 return hasInsufficientMirrorsUsed || | 1946 return hasInsufficientMirrorsUsed || |
| 2008 matchesMirrorsMetaTarget(element) || | 1947 matchesMirrorsMetaTarget(element) || |
| 2009 targetsUsed.contains(element) || | 1948 targetsUsed.contains(element) || |
| 2010 (enclosing != null && referencedFromMirrorSystem(enclosing)); | 1949 (enclosing != null && referencedFromMirrorSystem(enclosing)); |
| 2011 } | 1950 } |
| 2012 | 1951 |
| 2013 /** | 1952 /** |
| 2014 * Returns `true` if the element is needed because it has an annotation | 1953 * Returns `true` if the element is needed because it has an annotation |
| 2015 * of a type that is used as a meta target for reflection. | 1954 * of a type that is used as a meta target for reflection. |
| 2016 */ | 1955 */ |
| 2017 bool matchesMirrorsMetaTarget(Element element) { | 1956 bool matchesMirrorsMetaTarget(Element element) { |
| 2018 if (metaTargetsUsed.isEmpty) return false; | 1957 if (metaTargetsUsed.isEmpty) return false; |
| 2019 for (MetadataAnnotation metadata in element.metadata) { | 1958 for (MetadataAnnotation metadata in element.metadata) { |
| 2020 // TODO(kasperl): It would be nice if we didn't have to resolve | 1959 // TODO(kasperl): It would be nice if we didn't have to resolve |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2173 // [computeMembersNeededForReflection]. | 2112 // [computeMembersNeededForReflection]. |
| 2174 void maybeMarkClosureAsNeededForReflection( | 2113 void maybeMarkClosureAsNeededForReflection( |
| 2175 ClosureClassElement globalizedElement, | 2114 ClosureClassElement globalizedElement, |
| 2176 FunctionElement callFunction, | 2115 FunctionElement callFunction, |
| 2177 FunctionElement function) { | 2116 FunctionElement function) { |
| 2178 if (!_membersNeededForReflection.contains(function)) return; | 2117 if (!_membersNeededForReflection.contains(function)) return; |
| 2179 _membersNeededForReflection.add(callFunction); | 2118 _membersNeededForReflection.add(callFunction); |
| 2180 _membersNeededForReflection.add(globalizedElement); | 2119 _membersNeededForReflection.add(globalizedElement); |
| 2181 } | 2120 } |
| 2182 | 2121 |
| 2183 jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1, | 2122 jsAst.Call generateIsJsIndexableCall( |
| 2184 jsAst.Expression use2) { | 2123 jsAst.Expression use1, jsAst.Expression use2) { |
| 2185 String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME; | 2124 String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME; |
| 2186 jsAst.Expression dispatchProperty = | 2125 jsAst.Expression dispatchProperty = |
| 2187 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); | 2126 emitter.generateEmbeddedGlobalAccess(dispatchPropertyName); |
| 2188 | 2127 |
| 2189 // We pass the dispatch property record to the isJsIndexable | 2128 // We pass the dispatch property record to the isJsIndexable |
| 2190 // helper rather than reading it inside the helper to increase the | 2129 // helper rather than reading it inside the helper to increase the |
| 2191 // chance of making the dispatch record access monomorphic. | 2130 // chance of making the dispatch record access monomorphic. |
| 2192 jsAst.PropertyAccess record = | 2131 jsAst.PropertyAccess record = |
| 2193 new jsAst.PropertyAccess(use2, dispatchProperty); | 2132 new jsAst.PropertyAccess(use2, dispatchProperty); |
| 2194 | 2133 |
| 2195 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; | 2134 List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record]; |
| 2196 FunctionElement helper = helpers.isJsIndexable; | 2135 FunctionElement helper = helpers.isJsIndexable; |
| 2197 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); | 2136 jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper); |
| 2198 return new jsAst.Call(helperExpression, arguments); | 2137 return new jsAst.Call(helperExpression, arguments); |
| 2199 } | 2138 } |
| 2200 | 2139 |
| 2201 bool isTypedArray(TypeMask mask) { | 2140 bool isTypedArray(TypeMask mask) { |
| 2202 // Just checking for [:TypedData:] is not sufficient, as it is an | 2141 // Just checking for [:TypedData:] is not sufficient, as it is an |
| 2203 // abstract class any user-defined class can implement. So we also | 2142 // abstract class any user-defined class can implement. So we also |
| 2204 // check for the interface [JavaScriptIndexingBehavior]. | 2143 // check for the interface [JavaScriptIndexingBehavior]. |
| 2205 return | 2144 return compiler.typedDataClass != null && |
| 2206 compiler.typedDataClass != null && | |
| 2207 compiler.world.isInstantiated(compiler.typedDataClass) && | 2145 compiler.world.isInstantiated(compiler.typedDataClass) && |
| 2208 mask.satisfies(compiler.typedDataClass, compiler.world) && | 2146 mask.satisfies(compiler.typedDataClass, compiler.world) && |
| 2209 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); | 2147 mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world); |
| 2210 } | 2148 } |
| 2211 | 2149 |
| 2212 bool couldBeTypedArray(TypeMask mask) { | 2150 bool couldBeTypedArray(TypeMask mask) { |
| 2213 bool intersects(TypeMask type1, TypeMask type2) => | 2151 bool intersects(TypeMask type1, TypeMask type2) => |
| 2214 !type1.intersection(type2, compiler.world).isEmpty; | 2152 !type1.intersection(type2, compiler.world).isEmpty; |
| 2215 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and | 2153 // TODO(herhut): Maybe cache the TypeMask for typedDataClass and |
| 2216 // jsIndexingBehaviourInterface. | 2154 // jsIndexingBehaviourInterface. |
| 2217 return | 2155 return compiler.typedDataClass != null && |
| 2218 compiler.typedDataClass != null && | |
| 2219 compiler.world.isInstantiated(compiler.typedDataClass) && | 2156 compiler.world.isInstantiated(compiler.typedDataClass) && |
| 2220 intersects(mask, | 2157 intersects(mask, |
| 2221 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && | 2158 new TypeMask.subtype(compiler.typedDataClass, compiler.world)) && |
| 2222 intersects(mask, | 2159 intersects( |
| 2223 new TypeMask.subtype(helpers.jsIndexingBehaviorInterface, compiler.w
orld)); | 2160 mask, |
| 2161 new TypeMask.subtype( |
| 2162 helpers.jsIndexingBehaviorInterface, compiler.world)); |
| 2224 } | 2163 } |
| 2225 | 2164 |
| 2226 /// Returns all static fields that are referenced through [targetsUsed]. | 2165 /// Returns all static fields that are referenced through [targetsUsed]. |
| 2227 /// If the target is a library or class all nested static fields are | 2166 /// If the target is a library or class all nested static fields are |
| 2228 /// included too. | 2167 /// included too. |
| 2229 Iterable<Element> _findStaticFieldTargets() { | 2168 Iterable<Element> _findStaticFieldTargets() { |
| 2230 List staticFields = []; | 2169 List staticFields = []; |
| 2231 | 2170 |
| 2232 void addFieldsInContainer(ScopeContainerElement container) { | 2171 void addFieldsInContainer(ScopeContainerElement container) { |
| 2233 container.forEachLocalMember((Element member) { | 2172 container.forEachLocalMember((Element member) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2253 /// Called when [enqueuer] is empty, but before it is closed. | 2192 /// Called when [enqueuer] is empty, but before it is closed. |
| 2254 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { | 2193 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { |
| 2255 // Add elements referenced only via custom elements. Return early if any | 2194 // Add elements referenced only via custom elements. Return early if any |
| 2256 // elements are added to avoid counting the elements as due to mirrors. | 2195 // elements are added to avoid counting the elements as due to mirrors. |
| 2257 customElementsAnalysis.onQueueEmpty(enqueuer); | 2196 customElementsAnalysis.onQueueEmpty(enqueuer); |
| 2258 if (!enqueuer.queueIsEmpty) return false; | 2197 if (!enqueuer.queueIsEmpty) return false; |
| 2259 | 2198 |
| 2260 noSuchMethodRegistry.onQueueEmpty(); | 2199 noSuchMethodRegistry.onQueueEmpty(); |
| 2261 if (!enabledNoSuchMethod && | 2200 if (!enabledNoSuchMethod && |
| 2262 (noSuchMethodRegistry.hasThrowingNoSuchMethod || | 2201 (noSuchMethodRegistry.hasThrowingNoSuchMethod || |
| 2263 noSuchMethodRegistry.hasComplexNoSuchMethod)) { | 2202 noSuchMethodRegistry.hasComplexNoSuchMethod)) { |
| 2264 enableNoSuchMethod(enqueuer); | 2203 enableNoSuchMethod(enqueuer); |
| 2265 enabledNoSuchMethod = true; | 2204 enabledNoSuchMethod = true; |
| 2266 } | 2205 } |
| 2267 | 2206 |
| 2268 if (compiler.options.hasIncrementalSupport) { | 2207 if (compiler.options.hasIncrementalSupport) { |
| 2269 // Always enable tear-off closures during incremental compilation. | 2208 // Always enable tear-off closures during incremental compilation. |
| 2270 Element e = helpers.closureFromTearOff; | 2209 Element e = helpers.closureFromTearOff; |
| 2271 if (e != null && !enqueuer.isProcessed(e)) { | 2210 if (e != null && !enqueuer.isProcessed(e)) { |
| 2272 registerBackendUse(e); | 2211 registerBackendUse(e); |
| 2273 enqueuer.addToWorkList(e); | 2212 enqueuer.addToWorkList(e); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2287 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); | 2226 enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets()); |
| 2288 } | 2227 } |
| 2289 | 2228 |
| 2290 if (mustPreserveNames) reporter.log('Preserving names.'); | 2229 if (mustPreserveNames) reporter.log('Preserving names.'); |
| 2291 | 2230 |
| 2292 if (mustRetainMetadata) { | 2231 if (mustRetainMetadata) { |
| 2293 reporter.log('Retaining metadata.'); | 2232 reporter.log('Retaining metadata.'); |
| 2294 | 2233 |
| 2295 compiler.libraryLoader.libraries.forEach(retainMetadataOf); | 2234 compiler.libraryLoader.libraries.forEach(retainMetadataOf); |
| 2296 for (Dependency dependency in metadataConstants) { | 2235 for (Dependency dependency in metadataConstants) { |
| 2297 registerCompileTimeConstant( | 2236 registerCompileTimeConstant(dependency.constant, |
| 2298 dependency.constant, | |
| 2299 new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); | 2237 new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
| 2300 } | 2238 } |
| 2301 if (!enqueuer.isResolutionQueue) { | 2239 if (!enqueuer.isResolutionQueue) { |
| 2302 metadataConstants.clear(); | 2240 metadataConstants.clear(); |
| 2303 } | 2241 } |
| 2304 } | 2242 } |
| 2305 return true; | 2243 return true; |
| 2306 } | 2244 } |
| 2307 | 2245 |
| 2308 void onQueueClosed() { | 2246 void onQueueClosed() { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2336 metadata.ensureResolved(resolution); | 2274 metadata.ensureResolved(resolution); |
| 2337 ConstantValue constantValue = | 2275 ConstantValue constantValue = |
| 2338 compiler.constants.getConstantValue(metadata.constant); | 2276 compiler.constants.getConstantValue(metadata.constant); |
| 2339 if (!constantValue.isConstructedObject) continue; | 2277 if (!constantValue.isConstructedObject) continue; |
| 2340 ObjectConstantValue value = constantValue; | 2278 ObjectConstantValue value = constantValue; |
| 2341 ClassElement cls = value.type.element; | 2279 ClassElement cls = value.type.element; |
| 2342 if (cls == helpers.forceInlineClass) { | 2280 if (cls == helpers.forceInlineClass) { |
| 2343 hasForceInline = true; | 2281 hasForceInline = true; |
| 2344 if (VERBOSE_OPTIMIZER_HINTS) { | 2282 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2345 reporter.reportHintMessage( | 2283 reporter.reportHintMessage( |
| 2346 element, | 2284 element, MessageKind.GENERIC, {'text': "Must inline"}); |
| 2347 MessageKind.GENERIC, | |
| 2348 {'text': "Must inline"}); | |
| 2349 } | 2285 } |
| 2350 inlineCache.markAsMustInline(element); | 2286 inlineCache.markAsMustInline(element); |
| 2351 } else if (cls == helpers.noInlineClass) { | 2287 } else if (cls == helpers.noInlineClass) { |
| 2352 hasNoInline = true; | 2288 hasNoInline = true; |
| 2353 if (VERBOSE_OPTIMIZER_HINTS) { | 2289 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2354 reporter.reportHintMessage( | 2290 reporter.reportHintMessage( |
| 2355 element, | 2291 element, MessageKind.GENERIC, {'text': "Cannot inline"}); |
| 2356 MessageKind.GENERIC, | |
| 2357 {'text': "Cannot inline"}); | |
| 2358 } | 2292 } |
| 2359 inlineCache.markAsNonInlinable(element); | 2293 inlineCache.markAsNonInlinable(element); |
| 2360 } else if (cls == helpers.noThrowsClass) { | 2294 } else if (cls == helpers.noThrowsClass) { |
| 2361 hasNoThrows = true; | 2295 hasNoThrows = true; |
| 2362 if (!Elements.isStaticOrTopLevelFunction(element) && | 2296 if (!Elements.isStaticOrTopLevelFunction(element) && |
| 2363 !element.isFactoryConstructor) { | 2297 !element.isFactoryConstructor) { |
| 2364 reporter.internalError(element, | 2298 reporter.internalError( |
| 2299 element, |
| 2365 "@NoThrows() is currently limited to top-level" | 2300 "@NoThrows() is currently limited to top-level" |
| 2366 " or static functions and factory constructors."); | 2301 " or static functions and factory constructors."); |
| 2367 } | 2302 } |
| 2368 if (VERBOSE_OPTIMIZER_HINTS) { | 2303 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2369 reporter.reportHintMessage( | 2304 reporter.reportHintMessage( |
| 2370 element, | 2305 element, MessageKind.GENERIC, {'text': "Cannot throw"}); |
| 2371 MessageKind.GENERIC, | |
| 2372 {'text': "Cannot throw"}); | |
| 2373 } | 2306 } |
| 2374 compiler.world.registerCannotThrow(element); | 2307 compiler.world.registerCannotThrow(element); |
| 2375 } else if (cls == helpers.noSideEffectsClass) { | 2308 } else if (cls == helpers.noSideEffectsClass) { |
| 2376 hasNoSideEffects = true; | 2309 hasNoSideEffects = true; |
| 2377 if (VERBOSE_OPTIMIZER_HINTS) { | 2310 if (VERBOSE_OPTIMIZER_HINTS) { |
| 2378 reporter.reportHintMessage( | 2311 reporter.reportHintMessage( |
| 2379 element, | 2312 element, MessageKind.GENERIC, {'text': "Has no side effects"}); |
| 2380 MessageKind.GENERIC, | |
| 2381 {'text': "Has no side effects"}); | |
| 2382 } | 2313 } |
| 2383 compiler.world.registerSideEffectsFree(element); | 2314 compiler.world.registerSideEffectsFree(element); |
| 2384 } | 2315 } |
| 2385 } | 2316 } |
| 2386 if (hasForceInline && hasNoInline) { | 2317 if (hasForceInline && hasNoInline) { |
| 2387 reporter.internalError(element, | 2318 reporter.internalError( |
| 2388 "@ForceInline() must not be used with @NoInline."); | 2319 element, "@ForceInline() must not be used with @NoInline."); |
| 2389 } | 2320 } |
| 2390 if (hasNoThrows && !hasNoInline) { | 2321 if (hasNoThrows && !hasNoInline) { |
| 2391 reporter.internalError(element, | 2322 reporter.internalError( |
| 2392 "@NoThrows() should always be combined with @NoInline."); | 2323 element, "@NoThrows() should always be combined with @NoInline."); |
| 2393 } | 2324 } |
| 2394 if (hasNoSideEffects && !hasNoInline) { | 2325 if (hasNoSideEffects && !hasNoInline) { |
| 2395 reporter.internalError(element, | 2326 reporter.internalError(element, |
| 2396 "@NoSideEffects() should always be combined with @NoInline."); | 2327 "@NoSideEffects() should always be combined with @NoInline."); |
| 2397 } | 2328 } |
| 2398 if (element == helpers.invokeOnMethod) { | 2329 if (element == helpers.invokeOnMethod) { |
| 2399 compiler.enabledInvokeOn = true; | 2330 compiler.enabledInvokeOn = true; |
| 2400 } | 2331 } |
| 2401 } | 2332 } |
| 2333 |
| 2402 /* | 2334 /* |
| 2403 CodeBuffer codeOf(Element element) { | 2335 CodeBuffer codeOf(Element element) { |
| 2404 return generatedCode.containsKey(element) | 2336 return generatedCode.containsKey(element) |
| 2405 ? jsAst.prettyPrint(generatedCode[element], compiler) | 2337 ? jsAst.prettyPrint(generatedCode[element], compiler) |
| 2406 : null; | 2338 : null; |
| 2407 } | 2339 } |
| 2408 */ | 2340 */ |
| 2409 FunctionElement helperForBadMain() => helpers.badMain; | 2341 FunctionElement helperForBadMain() => helpers.badMain; |
| 2410 | 2342 |
| 2411 FunctionElement helperForMissingMain() => helpers.missingMain; | 2343 FunctionElement helperForMissingMain() => helpers.missingMain; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2443 @override | 2375 @override |
| 2444 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) { | 2376 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) { |
| 2445 registerCheckDeferredIsLoaded(registry); | 2377 registerCheckDeferredIsLoaded(registry); |
| 2446 return true; | 2378 return true; |
| 2447 } | 2379 } |
| 2448 | 2380 |
| 2449 @override | 2381 @override |
| 2450 bool enableCodegenWithErrorsIfSupported(Spannable node) { | 2382 bool enableCodegenWithErrorsIfSupported(Spannable node) { |
| 2451 if (compiler.options.useCpsIr) { | 2383 if (compiler.options.useCpsIr) { |
| 2452 // TODO(25747): Support code generation with compile-time errors. | 2384 // TODO(25747): Support code generation with compile-time errors. |
| 2453 reporter.reportHintMessage( | 2385 reporter.reportHintMessage(node, MessageKind.GENERIC, { |
| 2454 node, | 2386 'text': "Generation of code with compile time errors is currently " |
| 2455 MessageKind.GENERIC, | 2387 "not supported with the CPS IR." |
| 2456 {'text': "Generation of code with compile time errors is currently " | 2388 }); |
| 2457 "not supported with the CPS IR."}); | |
| 2458 return false; | 2389 return false; |
| 2459 } | 2390 } |
| 2460 return true; | 2391 return true; |
| 2461 } | 2392 } |
| 2462 | 2393 |
| 2463 jsAst.Expression rewriteAsync(FunctionElement element, | 2394 jsAst.Expression rewriteAsync( |
| 2464 jsAst.Expression code) { | 2395 FunctionElement element, jsAst.Expression code) { |
| 2465 AsyncRewriterBase rewriter = null; | 2396 AsyncRewriterBase rewriter = null; |
| 2466 jsAst.Name name = namer.methodPropertyName(element); | 2397 jsAst.Name name = namer.methodPropertyName(element); |
| 2467 switch (element.asyncMarker) { | 2398 switch (element.asyncMarker) { |
| 2468 case AsyncMarker.ASYNC: | 2399 case AsyncMarker.ASYNC: |
| 2469 rewriter = new AsyncRewriter( | 2400 rewriter = new AsyncRewriter(reporter, element, |
| 2470 reporter, | 2401 asyncHelper: emitter.staticFunctionAccess(helpers.asyncHelper), |
| 2471 element, | 2402 wrapBody: emitter.staticFunctionAccess(helpers.wrapBody), |
| 2472 asyncHelper: | 2403 newCompleter: |
| 2473 emitter.staticFunctionAccess(helpers.asyncHelper), | 2404 emitter.staticFunctionAccess(helpers.syncCompleterConstructor), |
| 2474 wrapBody: | |
| 2475 emitter.staticFunctionAccess(helpers.wrapBody), | |
| 2476 newCompleter: emitter.staticFunctionAccess( | |
| 2477 helpers.syncCompleterConstructor), | |
| 2478 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, | 2405 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, |
| 2479 bodyName: namer.deriveAsyncBodyName(name)); | 2406 bodyName: namer.deriveAsyncBodyName(name)); |
| 2480 break; | 2407 break; |
| 2481 case AsyncMarker.SYNC_STAR: | 2408 case AsyncMarker.SYNC_STAR: |
| 2482 rewriter = new SyncStarRewriter( | 2409 rewriter = new SyncStarRewriter(reporter, element, |
| 2483 reporter, | 2410 endOfIteration: |
| 2484 element, | 2411 emitter.staticFunctionAccess(helpers.endOfIteration), |
| 2485 endOfIteration: emitter.staticFunctionAccess( | 2412 newIterable: emitter |
| 2486 helpers.endOfIteration), | 2413 .staticFunctionAccess(helpers.syncStarIterableConstructor), |
| 2487 newIterable: emitter.staticFunctionAccess( | 2414 yieldStarExpression: |
| 2488 helpers.syncStarIterableConstructor), | 2415 emitter.staticFunctionAccess(helpers.yieldStar), |
| 2489 yieldStarExpression: emitter.staticFunctionAccess( | 2416 uncaughtErrorExpression: |
| 2490 helpers.yieldStar), | 2417 emitter.staticFunctionAccess(helpers.syncStarUncaughtError), |
| 2491 uncaughtErrorExpression: emitter.staticFunctionAccess( | |
| 2492 helpers.syncStarUncaughtError), | |
| 2493 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, | 2418 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, |
| 2494 bodyName: namer.deriveAsyncBodyName(name)); | 2419 bodyName: namer.deriveAsyncBodyName(name)); |
| 2495 break; | 2420 break; |
| 2496 case AsyncMarker.ASYNC_STAR: | 2421 case AsyncMarker.ASYNC_STAR: |
| 2497 rewriter = new AsyncStarRewriter( | 2422 rewriter = new AsyncStarRewriter(reporter, element, |
| 2498 reporter, | 2423 asyncStarHelper: |
| 2499 element, | 2424 emitter.staticFunctionAccess(helpers.asyncStarHelper), |
| 2500 asyncStarHelper: emitter.staticFunctionAccess( | 2425 streamOfController: |
| 2501 helpers.asyncStarHelper), | 2426 emitter.staticFunctionAccess(helpers.streamOfController), |
| 2502 streamOfController: emitter.staticFunctionAccess( | 2427 wrapBody: emitter.staticFunctionAccess(helpers.wrapBody), |
| 2503 helpers.streamOfController), | 2428 newController: emitter |
| 2504 wrapBody: | 2429 .staticFunctionAccess(helpers.asyncStarControllerConstructor), |
| 2505 emitter.staticFunctionAccess(helpers.wrapBody), | |
| 2506 newController: emitter.staticFunctionAccess( | |
| 2507 helpers.asyncStarControllerConstructor), | |
| 2508 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, | 2430 safeVariableName: namer.safeVariablePrefixForAsyncRewrite, |
| 2509 yieldExpression: emitter.staticFunctionAccess( | 2431 yieldExpression: emitter.staticFunctionAccess(helpers.yieldSingle), |
| 2510 helpers.yieldSingle), | 2432 yieldStarExpression: |
| 2511 yieldStarExpression: emitter.staticFunctionAccess( | 2433 emitter.staticFunctionAccess(helpers.yieldStar), |
| 2512 helpers.yieldStar), | |
| 2513 bodyName: namer.deriveAsyncBodyName(name)); | 2434 bodyName: namer.deriveAsyncBodyName(name)); |
| 2514 break; | 2435 break; |
| 2515 default: | 2436 default: |
| 2516 assert(element.asyncMarker == AsyncMarker.SYNC); | 2437 assert(element.asyncMarker == AsyncMarker.SYNC); |
| 2517 return code; | 2438 return code; |
| 2518 } | 2439 } |
| 2519 return rewriter.rewrite(code); | 2440 return rewriter.rewrite(code); |
| 2520 } | 2441 } |
| 2521 | 2442 |
| 2522 /// The locations of js patch-files relative to the sdk-descriptors. | 2443 /// The locations of js patch-files relative to the sdk-descriptors. |
| 2523 static const _patchLocations = const <String, String>{ | 2444 static const _patchLocations = const <String, String>{ |
| 2524 "async": "_internal/js_runtime/lib/async_patch.dart", | 2445 "async": "_internal/js_runtime/lib/async_patch.dart", |
| 2525 "collection": "_internal/js_runtime/lib/collection_patch.dart", | 2446 "collection": "_internal/js_runtime/lib/collection_patch.dart", |
| 2526 "convert": "_internal/js_runtime/lib/convert_patch.dart", | 2447 "convert": "_internal/js_runtime/lib/convert_patch.dart", |
| 2527 "core": "_internal/js_runtime/lib/core_patch.dart", | 2448 "core": "_internal/js_runtime/lib/core_patch.dart", |
| 2528 "developer": "_internal/js_runtime/lib/developer_patch.dart", | 2449 "developer": "_internal/js_runtime/lib/developer_patch.dart", |
| 2529 "io": "_internal/js_runtime/lib/io_patch.dart", | 2450 "io": "_internal/js_runtime/lib/io_patch.dart", |
| 2530 "isolate": "_internal/js_runtime/lib/isolate_patch.dart", | 2451 "isolate": "_internal/js_runtime/lib/isolate_patch.dart", |
| 2531 "math": "_internal/js_runtime/lib/math_patch.dart", | 2452 "math": "_internal/js_runtime/lib/math_patch.dart", |
| 2532 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart", | 2453 "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart", |
| 2533 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart", | 2454 "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart", |
| 2534 "_internal": "_internal/js_runtime/lib/internal_patch.dart" | 2455 "_internal": "_internal/js_runtime/lib/internal_patch.dart" |
| 2535 }; | 2456 }; |
| 2536 | 2457 |
| 2537 @override | 2458 @override |
| 2538 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { | 2459 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { |
| 2539 String patchLocation = _patchLocations[libraryName]; | 2460 String patchLocation = _patchLocations[libraryName]; |
| 2540 if (patchLocation == null) return null; | 2461 if (patchLocation == null) return null; |
| 2541 return platformConfigUri.resolve(patchLocation); | 2462 return platformConfigUri.resolve(patchLocation); |
| 2542 } | 2463 } |
| 2543 | 2464 |
| 2544 @override | 2465 @override |
| 2545 ImpactStrategy createImpactStrategy( | 2466 ImpactStrategy createImpactStrategy( |
| 2546 {bool supportDeferredLoad: true, | 2467 {bool supportDeferredLoad: true, |
| 2547 bool supportDumpInfo: true, | 2468 bool supportDumpInfo: true, |
| 2548 bool supportSerialization: true}) { | 2469 bool supportSerialization: true}) { |
| 2549 return new JavaScriptImpactStrategy( | 2470 return new JavaScriptImpactStrategy(resolution, compiler.dumpInfoTask, |
| 2550 resolution, | |
| 2551 compiler.dumpInfoTask, | |
| 2552 supportDeferredLoad: supportDeferredLoad, | 2471 supportDeferredLoad: supportDeferredLoad, |
| 2553 supportDumpInfo: supportDumpInfo, | 2472 supportDumpInfo: supportDumpInfo, |
| 2554 supportSerialization: supportSerialization); | 2473 supportSerialization: supportSerialization); |
| 2555 } | 2474 } |
| 2556 } | 2475 } |
| 2557 | 2476 |
| 2558 /// Handling of special annotations for tests. | 2477 /// Handling of special annotations for tests. |
| 2559 class Annotations { | 2478 class Annotations { |
| 2560 static final Uri PACKAGE_EXPECT = | 2479 static final Uri PACKAGE_EXPECT = |
| 2561 new Uri(scheme: 'package', path: 'expect/expect.dart'); | 2480 new Uri(scheme: 'package', path: 'expect/expect.dart'); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 hasTypeLiteral = true; | 2670 hasTypeLiteral = true; |
| 2752 break; | 2671 break; |
| 2753 } | 2672 } |
| 2754 } | 2673 } |
| 2755 | 2674 |
| 2756 if (hasAsCast) { | 2675 if (hasAsCast) { |
| 2757 registerBackendImpact(transformed, impacts.asCheck); | 2676 registerBackendImpact(transformed, impacts.asCheck); |
| 2758 } | 2677 } |
| 2759 | 2678 |
| 2760 if (hasTypeLiteral) { | 2679 if (hasTypeLiteral) { |
| 2761 transformed.registerTypeUse(new TypeUse.instantiation( | 2680 transformed.registerTypeUse( |
| 2762 backend.compiler.coreTypes.typeType)); | 2681 new TypeUse.instantiation(backend.compiler.coreTypes.typeType)); |
| 2763 registerBackendImpact(transformed, impacts.typeLiteral); | 2682 registerBackendImpact(transformed, impacts.typeLiteral); |
| 2764 } | 2683 } |
| 2765 | 2684 |
| 2766 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { | 2685 for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { |
| 2767 // TODO(johnniwinther): Use the [isEmpty] property when factory | 2686 // TODO(johnniwinther): Use the [isEmpty] property when factory |
| 2768 // constructors are registered directly. | 2687 // constructors are registered directly. |
| 2769 if (mapLiteralUse.isConstant) { | 2688 if (mapLiteralUse.isConstant) { |
| 2770 registerBackendImpact(transformed, impacts.constantMapLiteral); | 2689 registerBackendImpact(transformed, impacts.constantMapLiteral); |
| 2771 } else { | 2690 } else { |
| 2772 transformed.registerTypeUse( | 2691 transformed |
| 2773 new TypeUse.instantiation(mapLiteralUse.type)); | 2692 .registerTypeUse(new TypeUse.instantiation(mapLiteralUse.type)); |
| 2774 } | 2693 } |
| 2775 registerRequiredType(mapLiteralUse.type); | 2694 registerRequiredType(mapLiteralUse.type); |
| 2776 } | 2695 } |
| 2777 | 2696 |
| 2778 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { | 2697 for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) { |
| 2779 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when | 2698 // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when |
| 2780 // factory constructors are registered directly. | 2699 // factory constructors are registered directly. |
| 2781 transformed.registerTypeUse( | 2700 transformed |
| 2782 new TypeUse.instantiation(listLiteralUse.type)); | 2701 .registerTypeUse(new TypeUse.instantiation(listLiteralUse.type)); |
| 2783 registerRequiredType(listLiteralUse.type); | 2702 registerRequiredType(listLiteralUse.type); |
| 2784 } | 2703 } |
| 2785 | 2704 |
| 2786 if (worldImpact.constSymbolNames.isNotEmpty) { | 2705 if (worldImpact.constSymbolNames.isNotEmpty) { |
| 2787 registerBackendImpact(transformed, impacts.constSymbol); | 2706 registerBackendImpact(transformed, impacts.constSymbol); |
| 2788 for (String constSymbolName in worldImpact.constSymbolNames) { | 2707 for (String constSymbolName in worldImpact.constSymbolNames) { |
| 2789 backend.registerConstSymbol(constSymbolName); | 2708 backend.registerConstSymbol(constSymbolName); |
| 2790 } | 2709 } |
| 2791 } | 2710 } |
| 2792 | 2711 |
| 2793 for (StaticUse staticUse in worldImpact.staticUses) { | 2712 for (StaticUse staticUse in worldImpact.staticUses) { |
| 2794 if (staticUse.kind == StaticUseKind.CLOSURE) { | 2713 if (staticUse.kind == StaticUseKind.CLOSURE) { |
| 2795 registerBackendImpact(transformed, impacts.closure); | 2714 registerBackendImpact(transformed, impacts.closure); |
| 2796 LocalFunctionElement closure = staticUse.element; | 2715 LocalFunctionElement closure = staticUse.element; |
| 2797 if (closure.type.containsTypeVariables) { | 2716 if (closure.type.containsTypeVariables) { |
| 2798 backend.compiler.enqueuer.resolution.universe | 2717 backend.compiler.enqueuer.resolution.universe |
| 2799 .closuresWithFreeTypeVariables.add(closure); | 2718 .closuresWithFreeTypeVariables |
| 2719 .add(closure); |
| 2800 registerBackendImpact(transformed, impacts.computeSignature); | 2720 registerBackendImpact(transformed, impacts.computeSignature); |
| 2801 } | 2721 } |
| 2802 } | 2722 } |
| 2803 } | 2723 } |
| 2804 | 2724 |
| 2805 for (ConstantExpression constant in worldImpact.constantLiterals) { | 2725 for (ConstantExpression constant in worldImpact.constantLiterals) { |
| 2806 switch (constant.kind) { | 2726 switch (constant.kind) { |
| 2807 case ConstantExpressionKind.NULL: | 2727 case ConstantExpressionKind.NULL: |
| 2808 registerBackendImpact(transformed, impacts.nullLiteral); | 2728 registerBackendImpact(transformed, impacts.nullLiteral); |
| 2809 break; | 2729 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2821 break; | 2741 break; |
| 2822 default: | 2742 default: |
| 2823 assert(invariant(NO_LOCATION_SPANNABLE, false, | 2743 assert(invariant(NO_LOCATION_SPANNABLE, false, |
| 2824 message: "Unexpected constant literal: ${constant.kind}.")); | 2744 message: "Unexpected constant literal: ${constant.kind}.")); |
| 2825 } | 2745 } |
| 2826 } | 2746 } |
| 2827 | 2747 |
| 2828 return transformed; | 2748 return transformed; |
| 2829 } | 2749 } |
| 2830 | 2750 |
| 2831 void registerBackendImpact(TransformedWorldImpact worldImpact, | 2751 void registerBackendImpact( |
| 2832 BackendImpact backendImpact) { | 2752 TransformedWorldImpact worldImpact, BackendImpact backendImpact) { |
| 2833 for (Element staticUse in backendImpact.staticUses) { | 2753 for (Element staticUse in backendImpact.staticUses) { |
| 2834 assert(staticUse != null); | 2754 assert(staticUse != null); |
| 2835 backend.registerBackendUse(staticUse); | 2755 backend.registerBackendUse(staticUse); |
| 2836 worldImpact.registerStaticUse( | 2756 worldImpact.registerStaticUse( |
| 2837 // TODO(johnniwinther): Store the correct use in impacts. | 2757 // TODO(johnniwinther): Store the correct use in impacts. |
| 2838 new StaticUse.foreignUse(staticUse)); | 2758 new StaticUse.foreignUse(staticUse)); |
| 2839 } | 2759 } |
| 2840 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { | 2760 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { |
| 2841 backend.registerBackendUse(instantiatedType.element); | 2761 backend.registerBackendUse(instantiatedType.element); |
| 2842 worldImpact.registerTypeUse( | 2762 worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType)); |
| 2843 new TypeUse.instantiation(instantiatedType)); | |
| 2844 } | 2763 } |
| 2845 for (ClassElement cls in backendImpact.instantiatedClasses) { | 2764 for (ClassElement cls in backendImpact.instantiatedClasses) { |
| 2846 cls.ensureResolved(backend.resolution); | 2765 cls.ensureResolved(backend.resolution); |
| 2847 backend.registerBackendUse(cls); | 2766 backend.registerBackendUse(cls); |
| 2848 worldImpact.registerTypeUse( | 2767 worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType)); |
| 2849 new TypeUse.instantiation(cls.rawType)); | |
| 2850 } | 2768 } |
| 2851 for (BackendImpact otherImpact in backendImpact.otherImpacts) { | 2769 for (BackendImpact otherImpact in backendImpact.otherImpacts) { |
| 2852 registerBackendImpact(worldImpact, otherImpact); | 2770 registerBackendImpact(worldImpact, otherImpact); |
| 2853 } | 2771 } |
| 2854 } | 2772 } |
| 2855 | 2773 |
| 2856 /// Register [type] as required for the runtime type information system. | 2774 /// Register [type] as required for the runtime type information system. |
| 2857 void registerRequiredType(DartType type) { | 2775 void registerRequiredType(DartType type) { |
| 2858 // If [argument] has type variables or is a type variable, this method | 2776 // If [argument] has type variables or is a type variable, this method |
| 2859 // registers a RTI dependency between the class where the type variable is | 2777 // registers a RTI dependency between the class where the type variable is |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2881 registerBackendImpact(transformed, impacts.malformedTypeCheck); | 2799 registerBackendImpact(transformed, impacts.malformedTypeCheck); |
| 2882 } | 2800 } |
| 2883 if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { | 2801 if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { |
| 2884 registerBackendImpact(transformed, impacts.genericTypeCheck); | 2802 registerBackendImpact(transformed, impacts.genericTypeCheck); |
| 2885 if (inCheckedMode) { | 2803 if (inCheckedMode) { |
| 2886 registerBackendImpact(transformed, impacts.genericCheckedModeTypeCheck); | 2804 registerBackendImpact(transformed, impacts.genericCheckedModeTypeCheck); |
| 2887 } | 2805 } |
| 2888 if (type.isTypeVariable) { | 2806 if (type.isTypeVariable) { |
| 2889 registerBackendImpact(transformed, impacts.typeVariableTypeCheck); | 2807 registerBackendImpact(transformed, impacts.typeVariableTypeCheck); |
| 2890 if (inCheckedMode) { | 2808 if (inCheckedMode) { |
| 2891 registerBackendImpact(transformed, | 2809 registerBackendImpact( |
| 2892 impacts.typeVariableCheckedModeTypeCheck); | 2810 transformed, impacts.typeVariableCheckedModeTypeCheck); |
| 2893 } | 2811 } |
| 2894 } | 2812 } |
| 2895 } | 2813 } |
| 2896 if (type is FunctionType) { | 2814 if (type is FunctionType) { |
| 2897 registerBackendImpact(transformed, impacts.functionTypeCheck); | 2815 registerBackendImpact(transformed, impacts.functionTypeCheck); |
| 2898 } | 2816 } |
| 2899 if (type.element != null && backend.isNative(type.element)) { | 2817 if (type.element != null && backend.isNative(type.element)) { |
| 2900 registerBackendImpact(transformed, impacts.nativeTypeCheck); | 2818 registerBackendImpact(transformed, impacts.nativeTypeCheck); |
| 2901 } | 2819 } |
| 2902 } | 2820 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2956 break; | 2874 break; |
| 2957 default: | 2875 default: |
| 2958 } | 2876 } |
| 2959 } | 2877 } |
| 2960 | 2878 |
| 2961 for (ConstantValue constant in impact.compileTimeConstants) { | 2879 for (ConstantValue constant in impact.compileTimeConstants) { |
| 2962 backend.registerCompileTimeConstant(constant, registry); | 2880 backend.registerCompileTimeConstant(constant, registry); |
| 2963 backend.addCompileTimeConstantForEmission(constant); | 2881 backend.addCompileTimeConstantForEmission(constant); |
| 2964 } | 2882 } |
| 2965 | 2883 |
| 2966 for (Pair<DartType, DartType> check in | 2884 for (Pair<DartType, DartType> check |
| 2967 impact.typeVariableBoundsSubtypeChecks) { | 2885 in impact.typeVariableBoundsSubtypeChecks) { |
| 2968 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); | 2886 backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
| 2969 } | 2887 } |
| 2970 | 2888 |
| 2971 | |
| 2972 for (StaticUse staticUse in impact.staticUses) { | 2889 for (StaticUse staticUse in impact.staticUses) { |
| 2973 if (staticUse.kind == StaticUseKind.CLOSURE) { | 2890 if (staticUse.kind == StaticUseKind.CLOSURE) { |
| 2974 LocalFunctionElement closure = staticUse.element; | 2891 LocalFunctionElement closure = staticUse.element; |
| 2975 if (backend.methodNeedsRti(closure)) { | 2892 if (backend.methodNeedsRti(closure)) { |
| 2976 registerBackendImpact(transformed, impacts.computeSignature); | 2893 registerBackendImpact(transformed, impacts.computeSignature); |
| 2977 } | 2894 } |
| 2978 } | 2895 } |
| 2979 } | 2896 } |
| 2980 | 2897 |
| 2981 for (String name in impact.constSymbols) { | 2898 for (String name in impact.constSymbols) { |
| 2982 backend.registerConstSymbol(name); | 2899 backend.registerConstSymbol(name); |
| 2983 } | 2900 } |
| 2984 | 2901 |
| 2985 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { | 2902 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
| 2986 backend.registerSpecializedGetInterceptor(classes); | 2903 backend.registerSpecializedGetInterceptor(classes); |
| 2987 } | 2904 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3022 const Dependency(this.constant, this.annotatedElement); | 2939 const Dependency(this.constant, this.annotatedElement); |
| 3023 } | 2940 } |
| 3024 | 2941 |
| 3025 class JavaScriptImpactStrategy extends ImpactStrategy { | 2942 class JavaScriptImpactStrategy extends ImpactStrategy { |
| 3026 final Resolution resolution; | 2943 final Resolution resolution; |
| 3027 final DumpInfoTask dumpInfoTask; | 2944 final DumpInfoTask dumpInfoTask; |
| 3028 final bool supportDeferredLoad; | 2945 final bool supportDeferredLoad; |
| 3029 final bool supportDumpInfo; | 2946 final bool supportDumpInfo; |
| 3030 final bool supportSerialization; | 2947 final bool supportSerialization; |
| 3031 | 2948 |
| 3032 JavaScriptImpactStrategy(this.resolution, | 2949 JavaScriptImpactStrategy(this.resolution, this.dumpInfoTask, |
| 3033 this.dumpInfoTask, | 2950 {this.supportDeferredLoad, |
| 3034 {this.supportDeferredLoad, | 2951 this.supportDumpInfo, |
| 3035 this.supportDumpInfo, | 2952 this.supportSerialization}); |
| 3036 this.supportSerialization}); | |
| 3037 | 2953 |
| 3038 @override | 2954 @override |
| 3039 void visitImpact(Element element, | 2955 void visitImpact(Element element, WorldImpact impact, |
| 3040 WorldImpact impact, | 2956 WorldImpactVisitor visitor, ImpactUseCase impactUse) { |
| 3041 WorldImpactVisitor visitor, | |
| 3042 ImpactUseCase impactUse) { | |
| 3043 // TODO(johnniwinther): Compute the application strategy once for each use. | 2957 // TODO(johnniwinther): Compute the application strategy once for each use. |
| 3044 if (impactUse == ResolutionEnqueuer.IMPACT_USE) { | 2958 if (impactUse == ResolutionEnqueuer.IMPACT_USE) { |
| 3045 if (supportDeferredLoad || supportSerialization) { | 2959 if (supportDeferredLoad || supportSerialization) { |
| 3046 impact.apply(visitor); | 2960 impact.apply(visitor); |
| 3047 } else { | 2961 } else { |
| 3048 impact.apply(visitor); | 2962 impact.apply(visitor); |
| 3049 resolution.uncacheWorldImpact(element); | 2963 resolution.uncacheWorldImpact(element); |
| 3050 } | 2964 } |
| 3051 } else if (impactUse == DeferredLoadTask.IMPACT_USE) { | 2965 } else if (impactUse == DeferredLoadTask.IMPACT_USE) { |
| 3052 impact.apply(visitor); | 2966 impact.apply(visitor); |
| 3053 // Impacts are uncached globally in [onImpactUsed]. | 2967 // Impacts are uncached globally in [onImpactUsed]. |
| 3054 } else if (impactUse == DumpInfoTask.IMPACT_USE) { | 2968 } else if (impactUse == DumpInfoTask.IMPACT_USE) { |
| 3055 impact.apply(visitor); | 2969 impact.apply(visitor); |
| 3056 dumpInfoTask.unregisterImpact(element); | 2970 dumpInfoTask.unregisterImpact(element); |
| 3057 } else { | 2971 } else { |
| 3058 impact.apply(visitor); | 2972 impact.apply(visitor); |
| 3059 } | 2973 } |
| 3060 } | 2974 } |
| 3061 | 2975 |
| 3062 @override | 2976 @override |
| 3063 void onImpactUsed(ImpactUseCase impactUse) { | 2977 void onImpactUsed(ImpactUseCase impactUse) { |
| 3064 if (impactUse == DeferredLoadTask.IMPACT_USE && | 2978 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { |
| 3065 !supportSerialization) { | |
| 3066 // TODO(johnniwinther): Allow emptying when serialization has been | 2979 // TODO(johnniwinther): Allow emptying when serialization has been |
| 3067 // performed. | 2980 // performed. |
| 3068 resolution.emptyCache(); | 2981 resolution.emptyCache(); |
| 3069 } | 2982 } |
| 3070 } | 2983 } |
| 3071 } | 2984 } |
| OLD | NEW |