| // Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | // @dart = 2.10 | 
 |  | 
 | library dart2js.js_model.strategy; | 
 |  | 
 | import 'package:kernel/ast.dart' as ir; | 
 |  | 
 | import '../common.dart'; | 
 | import '../common/codegen.dart'; | 
 | import '../common/elements.dart' show CommonElements, ElementEnvironment; | 
 | import '../common/tasks.dart'; | 
 | import '../common/work.dart'; | 
 | import '../compiler.dart'; | 
 | import '../deferred_load/output_unit.dart' | 
 |     show LateOutputUnitDataBuilder, OutputUnitData; | 
 | import '../dump_info.dart'; | 
 | import '../elements/entities.dart'; | 
 | import '../enqueue.dart'; | 
 | import '../io/kernel_source_information.dart' | 
 |     show KernelSourceInformationStrategy; | 
 | import '../io/source_information.dart'; | 
 | import '../inferrer/abstract_value_domain.dart'; | 
 | import '../inferrer/type_graph_inferrer.dart'; | 
 | import '../inferrer/types.dart'; | 
 | import '../js/js_source_mapping.dart'; | 
 | import '../js_backend/backend.dart'; | 
 | import '../js_backend/backend_impact.dart'; | 
 | import '../js_backend/codegen_listener.dart'; | 
 | import '../js_backend/custom_elements_analysis.dart'; | 
 | import '../js_backend/enqueuer.dart'; | 
 | import '../js_backend/impact_transformer.dart'; | 
 | import '../js_backend/inferred_data.dart'; | 
 | import '../js_backend/interceptor_data.dart'; | 
 | import '../js_backend/namer.dart'; | 
 | import '../js_backend/runtime_types.dart'; | 
 | import '../js_backend/runtime_types_codegen.dart'; | 
 | import '../js_backend/runtime_types_new.dart' | 
 |     show RecipeEncoder, RecipeEncoderImpl; | 
 | import '../js_emitter/code_emitter_task.dart' show ModularEmitter; | 
 | import '../js_emitter/js_emitter.dart' show CodeEmitterTask; | 
 | import '../js/js.dart' as js; | 
 | import '../kernel/kernel_strategy.dart'; | 
 | import '../kernel/kernel_world.dart'; | 
 | import '../native/behavior.dart'; | 
 | import '../native/enqueue.dart'; | 
 | import '../options.dart'; | 
 | import '../serialization/serialization.dart'; | 
 | import '../ssa/builder.dart'; | 
 | import '../ssa/nodes.dart'; | 
 | import '../ssa/ssa.dart'; | 
 | import '../ssa/types.dart'; | 
 | import '../tracer.dart'; | 
 | import '../universe/codegen_world_builder.dart'; | 
 | import '../universe/selector.dart'; | 
 | import '../universe/world_impact.dart'; | 
 | import '../world.dart'; | 
 | import 'closure.dart'; | 
 | import 'element_map.dart'; | 
 | import 'element_map_impl.dart'; | 
 | import 'js_world.dart'; | 
 | import 'js_world_builder.dart' show JsClosedWorldBuilder; | 
 | import 'locals.dart'; | 
 |  | 
 | /// JS Strategy pattern that defines the element model used in type inference | 
 | /// and code generation. | 
 | class JsBackendStrategy { | 
 |   final Compiler _compiler; | 
 |   JsKernelToElementMap _elementMap; | 
 |  | 
 |   /// Codegen support for generating table of interceptors and | 
 |   /// constructors for custom elements. | 
 |   CustomElementsCodegenAnalysis _customElementsCodegenAnalysis; | 
 |  | 
 |   NativeCodegenEnqueuer _nativeCodegenEnqueuer; | 
 |  | 
 |   Namer _namer; | 
 |  | 
 |   CodegenImpactTransformer _codegenImpactTransformer; | 
 |  | 
 |   CodeEmitterTask _emitterTask; | 
 |  | 
 |   RuntimeTypesChecksBuilder _rtiChecksBuilder; | 
 |  | 
 |   FunctionCompiler _functionCompiler; | 
 |  | 
 |   SourceInformationStrategy sourceInformationStrategy; | 
 |  | 
 |   /// The generated code as a js AST for compiled methods. | 
 |   final Map<MemberEntity, js.Expression> generatedCode = {}; | 
 |  | 
 |   JsBackendStrategy(this._compiler) { | 
 |     bool generateSourceMap = _compiler.options.generateSourceMap; | 
 |     if (!generateSourceMap) { | 
 |       sourceInformationStrategy = const JavaScriptSourceInformationStrategy(); | 
 |     } else { | 
 |       sourceInformationStrategy = KernelSourceInformationStrategy(this); | 
 |     } | 
 |     _emitterTask = CodeEmitterTask(_compiler, generateSourceMap); | 
 |     _functionCompiler = SsaFunctionCompiler( | 
 |         _compiler.options, | 
 |         _compiler.reporter, | 
 |         this, | 
 |         _compiler.measurer, | 
 |         sourceInformationStrategy); | 
 |   } | 
 |  | 
 |   List<CompilerTask> get tasks { | 
 |     List<CompilerTask> result = functionCompiler.tasks; | 
 |     result.add(emitterTask); | 
 |     return result; | 
 |   } | 
 |  | 
 |   FunctionCompiler get functionCompiler => _functionCompiler; | 
 |  | 
 |   CodeEmitterTask get emitterTask => _emitterTask; | 
 |  | 
 |   Namer get namerForTesting => _namer; | 
 |  | 
 |   NativeEnqueuer get nativeCodegenEnqueuer => _nativeCodegenEnqueuer; | 
 |  | 
 |   RuntimeTypesChecksBuilder get rtiChecksBuilderForTesting => _rtiChecksBuilder; | 
 |  | 
 |   Map<MemberEntity, WorldImpact> codegenImpactsForTesting; | 
 |  | 
 |   String getGeneratedCodeForTesting(MemberEntity element) { | 
 |     if (generatedCode[element] == null) return null; | 
 |     return js.prettyPrint(generatedCode[element], | 
 |         enableMinification: _compiler.options.enableMinification); | 
 |   } | 
 |  | 
 |   @deprecated | 
 |   JsToElementMap get elementMap { | 
 |     assert(_elementMap != null, | 
 |         "JsBackendStrategy.elementMap has not been created yet."); | 
 |     return _elementMap; | 
 |   } | 
 |  | 
 |   /// Codegen support for generating table of interceptors and | 
 |   /// constructors for custom elements. | 
 |   CustomElementsCodegenAnalysis get customElementsCodegenAnalysis { | 
 |     assert( | 
 |         _customElementsCodegenAnalysis != null, | 
 |         failedAt(NO_LOCATION_SPANNABLE, | 
 |             "CustomElementsCodegenAnalysis has not been created yet.")); | 
 |     return _customElementsCodegenAnalysis; | 
 |   } | 
 |  | 
 |   RuntimeTypesChecksBuilder get rtiChecksBuilder { | 
 |     assert( | 
 |         _rtiChecksBuilder != null, | 
 |         failedAt(NO_LOCATION_SPANNABLE, | 
 |             "RuntimeTypesChecksBuilder has not been created yet.")); | 
 |     assert( | 
 |         !_rtiChecksBuilder.rtiChecksBuilderClosed, | 
 |         failedAt(NO_LOCATION_SPANNABLE, | 
 |             "RuntimeTypesChecks has already been computed.")); | 
 |     return _rtiChecksBuilder; | 
 |   } | 
 |  | 
 |   /// Create the [JClosedWorld] from [closedWorld]. | 
 |   JClosedWorld createJClosedWorld( | 
 |       KClosedWorld closedWorld, OutputUnitData outputUnitData) { | 
 |     KernelFrontendStrategy strategy = _compiler.frontendStrategy; | 
 |     _elementMap = JsKernelToElementMap( | 
 |         _compiler.reporter, | 
 |         _compiler.environment, | 
 |         strategy.elementMap, | 
 |         closedWorld.liveMemberUsage, | 
 |         closedWorld.annotationsData); | 
 |     ClosureDataBuilder closureDataBuilder = ClosureDataBuilder( | 
 |         _compiler.reporter, _elementMap, closedWorld.annotationsData); | 
 |     JsClosedWorldBuilder closedWorldBuilder = JsClosedWorldBuilder(_elementMap, | 
 |         closureDataBuilder, _compiler.options, _compiler.abstractValueStrategy); | 
 |     JClosedWorld jClosedWorld = closedWorldBuilder.convertClosedWorld( | 
 |         closedWorld, strategy.closureModels, outputUnitData); | 
 |     _elementMap.lateOutputUnitDataBuilder = | 
 |         LateOutputUnitDataBuilder(jClosedWorld.outputUnitData); | 
 |     return jClosedWorld; | 
 |   } | 
 |  | 
 |   /// Registers [closedWorld] as the current closed world used by this backend | 
 |   /// strategy. | 
 |   /// | 
 |   /// This is used to support serialization after type inference. | 
 |   void registerJClosedWorld(covariant JsClosedWorld closedWorld) { | 
 |     _elementMap = closedWorld.elementMap; | 
 |   } | 
 |  | 
 |   /// Called when the compiler starts running the codegen. | 
 |   /// | 
 |   /// Returns the [CodegenInputs] objects with the needed data. | 
 |   CodegenInputs onCodegenStart( | 
 |       GlobalTypeInferenceResults globalTypeInferenceResults) { | 
 |     JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld; | 
 |     FixedNames fixedNames = _compiler.options.enableMinification | 
 |         ? const MinifiedFixedNames() | 
 |         : const FixedNames(); | 
 |  | 
 |     Tracer tracer = | 
 |         Tracer(closedWorld, _compiler.options, _compiler.outputProvider); | 
 |  | 
 |     RuntimeTypesSubstitutions rtiSubstitutions; | 
 |     if (_compiler.options.disableRtiOptimization) { | 
 |       rtiSubstitutions = TrivialRuntimeTypesSubstitutions(closedWorld); | 
 |       _rtiChecksBuilder = | 
 |           TrivialRuntimeTypesChecksBuilder(closedWorld, rtiSubstitutions); | 
 |     } else { | 
 |       RuntimeTypesImpl runtimeTypesImpl = RuntimeTypesImpl(closedWorld); | 
 |       _rtiChecksBuilder = runtimeTypesImpl; | 
 |       rtiSubstitutions = runtimeTypesImpl; | 
 |     } | 
 |  | 
 |     RecipeEncoder rtiRecipeEncoder = RecipeEncoderImpl(closedWorld, | 
 |         rtiSubstitutions, closedWorld.nativeData, closedWorld.commonElements); | 
 |  | 
 |     CodegenInputs codegen = | 
 |         CodegenInputs(rtiSubstitutions, rtiRecipeEncoder, tracer, fixedNames); | 
 |  | 
 |     functionCompiler.initialize(globalTypeInferenceResults, codegen); | 
 |     return codegen; | 
 |   } | 
 |  | 
 |   /// Creates an [Enqueuer] for code generation specific to this backend. | 
 |   CodegenEnqueuer createCodegenEnqueuer( | 
 |       CompilerTask task, | 
 |       JClosedWorld closedWorld, | 
 |       GlobalTypeInferenceResults globalInferenceResults, | 
 |       CodegenInputs codegen, | 
 |       CodegenResults codegenResults) { | 
 |     assert(_elementMap != null, | 
 |         "JsBackendStrategy.elementMap has not been created yet."); | 
 |     OneShotInterceptorData oneShotInterceptorData = OneShotInterceptorData( | 
 |         closedWorld.interceptorData, | 
 |         closedWorld.commonElements, | 
 |         closedWorld.nativeData); | 
 |     _onCodegenEnqueuerStart( | 
 |         globalInferenceResults, codegen, oneShotInterceptorData); | 
 |     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment; | 
 |     CommonElements commonElements = closedWorld.commonElements; | 
 |     BackendImpacts impacts = BackendImpacts(commonElements, _compiler.options); | 
 |     _customElementsCodegenAnalysis = CustomElementsCodegenAnalysis( | 
 |         commonElements, elementEnvironment, closedWorld.nativeData); | 
 |     return CodegenEnqueuer( | 
 |         task, | 
 |         CodegenWorldBuilderImpl( | 
 |             closedWorld, | 
 |             _compiler.abstractValueStrategy.createSelectorStrategy(), | 
 |             oneShotInterceptorData), | 
 |         KernelCodegenWorkItemBuilder( | 
 |             this, | 
 |             closedWorld, | 
 |             codegenResults, | 
 |             ClosedEntityLookup(_elementMap), | 
 |             // TODO(johnniwinther): Avoid the need for a [ComponentLookup]. This | 
 |             // is caused by some type masks holding a kernel node for using in | 
 |             // tracing. | 
 |             ComponentLookup(_elementMap.programEnv.mainComponent)), | 
 |         CodegenEnqueuerListener( | 
 |             _compiler.options, | 
 |             elementEnvironment, | 
 |             commonElements, | 
 |             impacts, | 
 |             closedWorld.backendUsage, | 
 |             closedWorld.rtiNeed, | 
 |             customElementsCodegenAnalysis, | 
 |             nativeCodegenEnqueuer), | 
 |         closedWorld.annotationsData); | 
 |   } | 
 |  | 
 |   /// Called before the compiler starts running the codegen enqueuer. | 
 |   void _onCodegenEnqueuerStart( | 
 |       GlobalTypeInferenceResults globalTypeInferenceResults, | 
 |       CodegenInputs codegen, | 
 |       OneShotInterceptorData oneShotInterceptorData) { | 
 |     JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld; | 
 |     FixedNames fixedNames = codegen.fixedNames; | 
 |     _namer = _compiler.options.enableMinification | 
 |         ? _compiler.options.useFrequencyNamer | 
 |             ? FrequencyBasedNamer(closedWorld, fixedNames) | 
 |             : MinifyNamer(closedWorld, fixedNames) | 
 |         : Namer(closedWorld, fixedNames); | 
 |     _nativeCodegenEnqueuer = NativeCodegenEnqueuer( | 
 |         _compiler.options, | 
 |         closedWorld.elementEnvironment, | 
 |         closedWorld.commonElements, | 
 |         closedWorld.dartTypes, | 
 |         emitterTask, | 
 |         closedWorld.liveNativeClasses, | 
 |         closedWorld.nativeData); | 
 |     emitterTask.createEmitter(_namer, codegen, closedWorld); | 
 |     // TODO(johnniwinther): Share the impact object created in | 
 |     // createCodegenEnqueuer. | 
 |     BackendImpacts impacts = | 
 |         BackendImpacts(closedWorld.commonElements, _compiler.options); | 
 |  | 
 |     _codegenImpactTransformer = CodegenImpactTransformer( | 
 |         closedWorld, | 
 |         closedWorld.elementEnvironment, | 
 |         impacts, | 
 |         closedWorld.nativeData, | 
 |         closedWorld.backendUsage, | 
 |         closedWorld.rtiNeed, | 
 |         nativeCodegenEnqueuer, | 
 |         _namer, | 
 |         oneShotInterceptorData, | 
 |         rtiChecksBuilder, | 
 |         emitterTask.nativeEmitter); | 
 |   } | 
 |  | 
 |   WorldImpact generateCode( | 
 |       WorkItem work, | 
 |       JClosedWorld closedWorld, | 
 |       CodegenResults codegenResults, | 
 |       EntityLookup entityLookup, | 
 |       ComponentLookup componentLookup) { | 
 |     MemberEntity member = work.element; | 
 |     CodegenResult result = codegenResults.getCodegenResults(member); | 
 |     if (_compiler.options.testMode) { | 
 |       bool useDataKinds = true; | 
 |       List<Object> data = []; | 
 |       DataSinkWriter sink = DataSinkWriter( | 
 |           ObjectDataSink(data), _compiler.options, | 
 |           useDataKinds: useDataKinds); | 
 |       sink.registerCodegenWriter(CodegenWriterImpl(closedWorld)); | 
 |       result.writeToDataSink(sink); | 
 |       sink.close(); | 
 |       DataSourceReader source = DataSourceReader( | 
 |           ObjectDataSource(data), _compiler.options, | 
 |           useDataKinds: useDataKinds); | 
 |       List<ModularName> modularNames = []; | 
 |       List<ModularExpression> modularExpression = []; | 
 |       source.registerCodegenReader( | 
 |           CodegenReaderImpl(closedWorld, modularNames, modularExpression)); | 
 |       source.registerEntityLookup(entityLookup); | 
 |       source.registerComponentLookup(componentLookup); | 
 |       result = CodegenResult.readFromDataSource( | 
 |           source, modularNames, modularExpression); | 
 |     } | 
 |     if (result.code != null) { | 
 |       generatedCode[member] = result.code; | 
 |     } | 
 |     if (retainDataForTesting) { | 
 |       codegenImpactsForTesting ??= {}; | 
 |       codegenImpactsForTesting[member] = result.impact; | 
 |     } | 
 |     WorldImpact worldImpact = | 
 |         _codegenImpactTransformer.transformCodegenImpact(result.impact); | 
 |     _compiler.dumpInfoTask.registerImpact(member, worldImpact); | 
 |     result.applyModularState(_namer, emitterTask.emitter); | 
 |     return worldImpact; | 
 |   } | 
 |  | 
 |   /// Called when code generation has been completed. | 
 |   void onCodegenEnd(CodegenInputs codegen) { | 
 |     sourceInformationStrategy.onComplete(); | 
 |     codegen.tracer.close(); | 
 |   } | 
 |  | 
 |   /// Generates the output and returns the total size of the generated code. | 
 |   int assembleProgram(JClosedWorld closedWorld, InferredData inferredData, | 
 |       CodegenInputs codegenInputs, CodegenWorld codegenWorld) { | 
 |     int programSize = emitterTask.assembleProgram( | 
 |         _namer, closedWorld, inferredData, codegenInputs, codegenWorld); | 
 |     closedWorld.noSuchMethodData.emitDiagnostic(_compiler.reporter); | 
 |     return programSize; | 
 |   } | 
 |  | 
 |   /// Creates the [SsaBuilder] used for the element model. | 
 |   SsaBuilder createSsaBuilder( | 
 |       CompilerTask task, SourceInformationStrategy sourceInformationStrategy) { | 
 |     return KernelSsaBuilder( | 
 |         task, | 
 |         _compiler.options, | 
 |         _compiler.reporter, | 
 |         _compiler.dumpInfoTask, | 
 |         // ignore:deprecated_member_use_from_same_package | 
 |         elementMap, | 
 |         sourceInformationStrategy); | 
 |   } | 
 |  | 
 |   /// Creates a [SourceSpan] from [spannable] in context of [currentElement]. | 
 |   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement) { | 
 |     return _elementMap.getSourceSpan(spannable, currentElement); | 
 |   } | 
 |  | 
 |   /// Creates the [TypesInferrer] used by this strategy. | 
 |   TypesInferrer createTypesInferrer( | 
 |       JClosedWorld closedWorld, | 
 |       GlobalLocalsMap globalLocalsMap, | 
 |       InferredDataBuilder inferredDataBuilder) { | 
 |     return TypeGraphInferrer( | 
 |         _compiler, closedWorld, globalLocalsMap, inferredDataBuilder); | 
 |   } | 
 |  | 
 |   /// Prepare [source] to deserialize modular code generation data. | 
 |   void prepareCodegenReader(DataSourceReader source) { | 
 |     source.registerEntityReader(ClosedEntityReader(_elementMap)); | 
 |     source.registerEntityLookup(ClosedEntityLookup(_elementMap)); | 
 |     source.registerComponentLookup( | 
 |         ComponentLookup(_elementMap.programEnv.mainComponent)); | 
 |   } | 
 |  | 
 |   /// Calls [f] for every member that needs to be serialized for modular code | 
 |   /// generation and returns an [EntityWriter] for encoding these members in | 
 |   /// the serialized data. | 
 |   /// | 
 |   /// The needed members include members computed on demand during non-modular | 
 |   /// code generation, such as constructor bodies and and generator bodies. | 
 |   EntityWriter forEachCodegenMember(void Function(MemberEntity member) f) { | 
 |     int earlyMemberIndexLimit = _elementMap.prepareForCodegenSerialization(); | 
 |     ClosedEntityWriter entityWriter = ClosedEntityWriter(earlyMemberIndexLimit); | 
 |     for (int memberIndex = 0; | 
 |         memberIndex < _elementMap.members.length; | 
 |         memberIndex++) { | 
 |       MemberEntity member = _elementMap.members.getEntity(memberIndex); | 
 |       if (member == null || member.isAbstract) continue; | 
 |       f(member); | 
 |     } | 
 |     return entityWriter; | 
 |   } | 
 | } | 
 |  | 
 | class KernelCodegenWorkItemBuilder implements WorkItemBuilder { | 
 |   final JsBackendStrategy _backendStrategy; | 
 |   final JClosedWorld _closedWorld; | 
 |   final CodegenResults _codegenResults; | 
 |   final EntityLookup _entityLookup; | 
 |   final ComponentLookup _componentLookup; | 
 |  | 
 |   KernelCodegenWorkItemBuilder(this._backendStrategy, this._closedWorld, | 
 |       this._codegenResults, this._entityLookup, this._componentLookup); | 
 |  | 
 |   @override | 
 |   WorkItem createWorkItem(MemberEntity entity) { | 
 |     if (entity.isAbstract) return null; | 
 |     return KernelCodegenWorkItem(_backendStrategy, _closedWorld, | 
 |         _codegenResults, _entityLookup, _componentLookup, entity); | 
 |   } | 
 | } | 
 |  | 
 | class KernelCodegenWorkItem extends WorkItem { | 
 |   final JsBackendStrategy _backendStrategy; | 
 |   final JClosedWorld _closedWorld; | 
 |   final CodegenResults _codegenResults; | 
 |   final EntityLookup _entityLookup; | 
 |   final ComponentLookup _componentLookup; | 
 |   @override | 
 |   final MemberEntity element; | 
 |  | 
 |   KernelCodegenWorkItem( | 
 |       this._backendStrategy, | 
 |       this._closedWorld, | 
 |       this._codegenResults, | 
 |       this._entityLookup, | 
 |       this._componentLookup, | 
 |       this.element); | 
 |  | 
 |   @override | 
 |   WorldImpact run() { | 
 |     return _backendStrategy.generateCode( | 
 |         this, _closedWorld, _codegenResults, _entityLookup, _componentLookup); | 
 |   } | 
 | } | 
 |  | 
 | /// Task for building SSA from kernel IR loaded from .dill. | 
 | class KernelSsaBuilder implements SsaBuilder { | 
 |   final CompilerTask _task; | 
 |   final CompilerOptions _options; | 
 |   final DiagnosticReporter _reporter; | 
 |   final DumpInfoTask _dumpInfoTask; | 
 |   final JsToElementMap _elementMap; | 
 |   final SourceInformationStrategy _sourceInformationStrategy; | 
 |  | 
 |   FunctionInlineCache _inlineCache; | 
 |   InlineDataCache _inlineDataCache; | 
 |  | 
 |   KernelSsaBuilder(this._task, this._options, this._reporter, | 
 |       this._dumpInfoTask, this._elementMap, this._sourceInformationStrategy); | 
 |  | 
 |   @override | 
 |   HGraph build( | 
 |       MemberEntity member, | 
 |       JClosedWorld closedWorld, | 
 |       GlobalTypeInferenceResults results, | 
 |       CodegenInputs codegen, | 
 |       CodegenRegistry registry, | 
 |       ModularNamer namer, | 
 |       ModularEmitter emitter) { | 
 |     _inlineCache ??= FunctionInlineCache(closedWorld.annotationsData); | 
 |     _inlineDataCache ??= InlineDataCache( | 
 |         enableUserAssertions: _options.enableUserAssertions, | 
 |         omitImplicitCasts: _options.omitImplicitChecks); | 
 |     return _task.measure(() { | 
 |       KernelSsaGraphBuilder builder = KernelSsaGraphBuilder( | 
 |           _options, | 
 |           _reporter, | 
 |           member, | 
 |           _elementMap.getMemberThisType(member), | 
 |           _dumpInfoTask, | 
 |           _elementMap, | 
 |           results, | 
 |           closedWorld, | 
 |           registry, | 
 |           namer, | 
 |           emitter, | 
 |           codegen.tracer, | 
 |           _sourceInformationStrategy, | 
 |           _inlineCache, | 
 |           _inlineDataCache); | 
 |       return builder.build(); | 
 |     }); | 
 |   } | 
 | } | 
 |  | 
 | class KernelToTypeInferenceMapImpl implements KernelToTypeInferenceMap { | 
 |   final GlobalTypeInferenceResults _globalInferenceResults; | 
 |   GlobalTypeInferenceMemberResult _targetResults; | 
 |  | 
 |   KernelToTypeInferenceMapImpl( | 
 |       MemberEntity target, this._globalInferenceResults) { | 
 |     _targetResults = _resultOf(target); | 
 |   } | 
 |  | 
 |   GlobalTypeInferenceMemberResult _resultOf(MemberEntity e) => | 
 |       _globalInferenceResults | 
 |           .resultOfMember(e is ConstructorBodyEntity ? e.constructor : e); | 
 |  | 
 |   @override | 
 |   AbstractValue getReturnTypeOf(FunctionEntity function) { | 
 |     return AbstractValueFactory.inferredReturnTypeForElement( | 
 |         function, _globalInferenceResults); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue receiverTypeOfInvocation( | 
 |       ir.Expression node, AbstractValueDomain abstractValueDomain) { | 
 |     return _targetResults.typeOfReceiver(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue receiverTypeOfGet(ir.Expression node) { | 
 |     return _targetResults.typeOfReceiver(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue receiverTypeOfSet( | 
 |       ir.Expression node, AbstractValueDomain abstractValueDomain) { | 
 |     return _targetResults.typeOfReceiver(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue typeOfListLiteral( | 
 |       ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain) { | 
 |     return _globalInferenceResults.typeOfListLiteral(listLiteral) ?? | 
 |         abstractValueDomain.dynamicType; | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue typeOfIterator(ir.ForInStatement node) { | 
 |     return _targetResults.typeOfIterator(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue typeOfIteratorCurrent(ir.ForInStatement node) { | 
 |     return _targetResults.typeOfIteratorCurrent(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue typeOfIteratorMoveNext(ir.ForInStatement node) { | 
 |     return _targetResults.typeOfIteratorMoveNext(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   bool isJsIndexableIterator( | 
 |       ir.ForInStatement node, AbstractValueDomain abstractValueDomain) { | 
 |     AbstractValue mask = typeOfIterator(node); | 
 |     // TODO(sra): Investigate why mask is sometimes null. | 
 |     if (mask == null) return false; | 
 |     return abstractValueDomain.isJsIndexableAndIterable(mask).isDefinitelyTrue; | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue inferredIndexType(ir.ForInStatement node) { | 
 |     return AbstractValueFactory.inferredResultTypeForSelector( | 
 |         Selector.index(), typeOfIterator(node), _globalInferenceResults); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue getInferredTypeOf(MemberEntity member) { | 
 |     return AbstractValueFactory.inferredTypeForMember( | 
 |         member, _globalInferenceResults); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue getInferredTypeOfParameter(Local parameter) { | 
 |     return AbstractValueFactory.inferredTypeForParameter( | 
 |         parameter, _globalInferenceResults); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue resultTypeOfSelector(Selector selector, AbstractValue mask) { | 
 |     return AbstractValueFactory.inferredResultTypeForSelector( | 
 |         selector, mask, _globalInferenceResults); | 
 |   } | 
 |  | 
 |   @override | 
 |   AbstractValue typeFromNativeBehavior( | 
 |       NativeBehavior nativeBehavior, JClosedWorld closedWorld) { | 
 |     return AbstractValueFactory.fromNativeBehavior(nativeBehavior, closedWorld); | 
 |   } | 
 | } |