// Copyright (c) 2018, 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.

library vm.bytecode.gen_bytecode;

import 'package:front_end/src/api_unstable/vm.dart'
    show
        CompilerContext,
        Severity,
        isRedirectingFactoryField,
        messageBytecodeLimitExceededTooManyArguments,
        noLength,
        templateIllegalRecursiveType;

import 'package:kernel/ast.dart' hide MapEntry, Component, FunctionDeclaration;
import 'package:kernel/ast.dart' as ast show Component, FunctionDeclaration;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/external_name.dart'
    show getExternalName, getNativeExtensionUris;
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/text/ast_to_text.dart'
    show globalDebuggingNames, NameSystem;
import 'package:kernel/type_algebra.dart'
    show Substitution, containsTypeVariable;
import 'package:kernel/type_environment.dart'
    show StatefulStaticTypeContext, SubtypeCheckMode, TypeEnvironment;
import 'assembler.dart';
import 'bytecode_serialization.dart' show StringTable;
import 'constant_pool.dart';
import 'dbc.dart';
import 'declarations.dart';
import 'exceptions.dart';
import 'generics.dart'
    show
        flattenInstantiatorTypeArguments,
        getDefaultFunctionTypeArguments,
        getInstantiatorTypeArguments,
        getStaticType,
        getTypeParameterTypes,
        hasFreeTypeParameters,
        hasInstantiatorTypeArguments,
        isAllDynamic,
        isInstantiatedInterfaceCall,
        isUncheckedCall,
        isUncheckedClosureCall;
import 'local_variable_table.dart' show LocalVariableTable;
import 'local_vars.dart' show LocalVariables;
import 'nullability_detector.dart' show NullabilityDetector;
import 'object_table.dart'
    show ObjectHandle, ObjectTable, NameAndType, topLevelClassName;
import 'options.dart' show BytecodeOptions;
import 'recognized_methods.dart' show RecognizedMethods;
import 'recursive_types_validator.dart' show IllegalRecursiveTypeException;
import 'source_positions.dart' show LineStarts, SourcePositions;
import '../metadata/bytecode.dart';
import '../metadata/direct_call.dart'
    show DirectCallMetadata, DirectCallMetadataRepository;
import '../metadata/inferred_type.dart'
    show InferredType, InferredTypeMetadataRepository;
import '../metadata/obfuscation_prohibitions.dart'
    show ObfuscationProhibitionsMetadataRepository;
import '../metadata/procedure_attributes.dart'
    show ProcedureAttributesMetadata, ProcedureAttributesMetadataRepository;

import 'dart:convert' show utf8;
import 'dart:developer';
import 'dart:math' as math;

// This symbol is used as the name in assert assignable's to indicate it comes
// from an explicit 'as' check.  This will cause the runtime to throw the right
// exception.
const String symbolForTypeCast = ' in type cast';

void generateBytecode(
  ast.Component component, {
  BytecodeOptions options,
  List<Library> libraries,
  CoreTypes coreTypes,
  ClassHierarchy hierarchy,
}) {
  Timeline.timeSync("generateBytecode", () {
    options ??= new BytecodeOptions();
    verifyBytecodeInstructionDeclarations();
    coreTypes ??= new CoreTypes(component);
    void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
    hierarchy ??= new ClassHierarchy(component, coreTypes,
        onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
    final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
    libraries ??= component.libraries;

    // Save/restore global NameSystem to avoid accumulating garbage.
    // NameSystem holds the whole AST as it is strongly connected due to
    // parent pointers. Objects are added to NameSystem when toString()
    // is called from AST nodes.  Bytecode generator widely uses
    // Expression.getStaticType, which calls Expression.getStaticTypeAsInstanceOf,
    // which uses toString() when it crashes due to http://dartbug.com/34496.
    final savedGlobalDebuggingNames = globalDebuggingNames;
    globalDebuggingNames = new NameSystem();

    Library library;
    try {
      final bytecodeGenerator = new BytecodeGenerator(
          component, coreTypes, hierarchy, typeEnvironment, options);
      for (library in libraries) {
        bytecodeGenerator.visitLibrary(library);
      }
    } on IllegalRecursiveTypeException catch (e) {
      CompilerContext.current.options.report(
          templateIllegalRecursiveType
              .withArguments(e.type, library.isNonNullableByDefault)
              .withoutLocation(),
          Severity.error);
    } finally {
      globalDebuggingNames = savedGlobalDebuggingNames;
    }
  });
}

class BytecodeGenerator extends RecursiveVisitor<Null> {
  static final Name callName = new Name('call');
  static final Name noSuchMethodName = new Name('noSuchMethod');

  final CoreTypes coreTypes;
  final ClassHierarchy hierarchy;
  final TypeEnvironment typeEnvironment;
  final StatefulStaticTypeContext staticTypeContext;
  final BytecodeOptions options;
  final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository();
  final RecognizedMethods recognizedMethods;
  final int formatVersion;
  final Map<Uri, Source> astUriToSource;
  StringTable stringTable;
  ObjectTable objectTable;
  Component bytecodeComponent;
  NullabilityDetector nullabilityDetector;
  Map<TreeNode, DirectCallMetadata> directCallMetadata;
  ProcedureAttributesMetadataRepository procedureAttributesMetadataRepository;
  ProcedureAttributesMetadata procedureAttributesMetadata;
  Map<TreeNode, InferredType> inferredTypeMetadata;
  List<Constant> inferredTypesAttribute;

  List<ClassDeclaration> classDeclarations;
  List<FieldDeclaration> fieldDeclarations;
  List<FunctionDeclaration> functionDeclarations;
  Class enclosingClass;
  Member enclosingMember;
  FunctionNode enclosingFunction;
  FunctionNode parentFunction;
  bool isClosure;
  Set<TypeParameter> classTypeParameters;
  List<TypeParameter> functionTypeParameters;
  Set<TypeParameter> functionTypeParametersSet;
  List<DartType> instantiatorTypeArguments;
  LocalVariables locals;
  Map<LabeledStatement, Label> labeledStatements;
  Map<SwitchCase, Label> switchCases;
  Map<TryCatch, TryBlock> tryCatches;
  Map<TryFinally, List<FinallyBlock>> finallyBlocks;
  List<Label> yieldPoints;
  Map<TreeNode, int> contextLevels;
  List<ClosureDeclaration> closures;
  Set<Field> initializedFields;
  List<ObjectHandle> nullableFields;
  ConstantPool cp;
  BytecodeAssembler asm;
  List<BytecodeAssembler> savedAssemblers;
  bool hasErrors;
  int currentLoopDepth;
  List<int> savedMaxSourcePositions;
  int maxSourcePosition;

  BytecodeGenerator(
      ast.Component component,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      TypeEnvironment typeEnvironment,
      BytecodeOptions options)
      : this._internal(component, coreTypes, hierarchy, typeEnvironment,
            options, new StatefulStaticTypeContext.flat(typeEnvironment));

  BytecodeGenerator._internal(
      ast.Component component,
      this.coreTypes,
      this.hierarchy,
      this.typeEnvironment,
      this.options,
      this.staticTypeContext)
      : recognizedMethods = new RecognizedMethods(staticTypeContext),
        formatVersion = currentBytecodeFormatVersion,
        astUriToSource = component.uriToSource {
    nullabilityDetector = new NullabilityDetector(recognizedMethods);
    component.addMetadataRepository(metadata);

    bytecodeComponent = new Component(formatVersion, coreTypes);
    metadata.mapping[component] = new BytecodeMetadata(bytecodeComponent);

    stringTable = bytecodeComponent.stringTable;
    objectTable = bytecodeComponent.objectTable;

    if (component.mainMethod != null) {
      bytecodeComponent.mainLibrary =
          objectTable.getHandle(component.mainMethod.enclosingLibrary);
    }

    directCallMetadata =
        component.metadata[DirectCallMetadataRepository.repositoryTag]?.mapping;

    procedureAttributesMetadataRepository =
        component.metadata[ProcedureAttributesMetadataRepository.repositoryTag];

    inferredTypeMetadata = component
        .metadata[InferredTypeMetadataRepository.repositoryTag]?.mapping;

    final obfuscationProhibitionsMetadataRepository = component
        .metadata[ObfuscationProhibitionsMetadataRepository.repositoryTag];
    if (obfuscationProhibitionsMetadataRepository != null) {
      bytecodeComponent.protectedNames =
          obfuscationProhibitionsMetadataRepository
              .mapping[component]?.protectedNames;
    }
  }

  @override
  visitLibrary(Library node) {
    staticTypeContext.enterLibrary(node);

    startMembers();
    visitList(node.procedures, this);
    visitList(node.fields, this);
    final members = endMembers(node);

    classDeclarations = <ClassDeclaration>[
      getTopLevelClassDeclaration(node, members)
    ];

    visitList(node.classes, this);

    bytecodeComponent.libraries
        .add(getLibraryDeclaration(node, classDeclarations));
    classDeclarations = null;
    staticTypeContext.leaveLibrary(node);
  }

  @override
  visitClass(Class node) {
    startMembers();
    visitList(node.constructors, this);
    visitList(node.procedures, this);
    visitList(node.fields, this);
    final members = endMembers(node);

    classDeclarations.add(getClassDeclaration(node, members));
  }

  void startMembers() {
    fieldDeclarations = <FieldDeclaration>[];
    functionDeclarations = <FunctionDeclaration>[];
  }

  Members endMembers(TreeNode node) {
    final members = new Members(fieldDeclarations, functionDeclarations);
    bytecodeComponent.members.add(members);
    fieldDeclarations = null;
    functionDeclarations = null;
    return members;
  }

  ObjectHandle getScript(Uri uri, bool includeSourceInfo) {
    SourceFile source;
    if (options.emitSourceFiles || options.emitSourcePositions) {
      final astSource = astUriToSource[uri];
      if (astSource != null) {
        source = bytecodeComponent.uriToSource[uri];
        if (source == null) {
          final importUri =
              objectTable.getConstStringHandle(astSource.importUri.toString());
          source = new SourceFile(importUri);
          bytecodeComponent.sourceFiles.add(source);
          bytecodeComponent.uriToSource[uri] = source;
        }
        if (options.emitSourcePositions &&
            includeSourceInfo &&
            source.lineStarts == null) {
          LineStarts lineStarts = new LineStarts(astSource.lineStarts);
          bytecodeComponent.lineStarts.add(lineStarts);
          source.lineStarts = lineStarts;
        }
        if (options.emitSourceFiles &&
            includeSourceInfo &&
            source.source == null) {
          String text = astSource.cachedText ??
              utf8.decode(astSource.source, allowMalformed: true);
          source.source = text;
        }
      }
    }
    return objectTable.getScriptHandle(uri, source);
  }

  LibraryDeclaration getLibraryDeclaration(
      Library library, List<ClassDeclaration> classes) {
    final importUri =
        objectTable.getConstStringHandle(library.importUri.toString());
    int flags = 0;
    for (var dependency in library.dependencies) {
      final targetLibrary = dependency.targetLibrary;
      assert(targetLibrary != null);
      if (targetLibrary == coreTypes.mirrorsLibrary) {
        flags |= LibraryDeclaration.usesDartMirrorsFlag;
      } else if (targetLibrary == dartFfiLibrary) {
        flags |= LibraryDeclaration.usesDartFfiFlag;
      }
    }
    final name = objectTable.getPublicNameHandle(library.name ?? '');
    final script = getScript(library.fileUri, true);
    final extensionUris =
        objectTable.getConstStringHandles(getNativeExtensionUris(library));
    if (extensionUris.isNotEmpty) {
      flags |= LibraryDeclaration.hasExtensionsFlag;
    }
    if (library.isNonNullableByDefault) {
      flags |= LibraryDeclaration.isNonNullableByDefaultFlag;
    }
    return new LibraryDeclaration(
        importUri, flags, name, script, extensionUris, classes);
  }

  ClassDeclaration getClassDeclaration(Class cls, Members members) {
    int flags = 0;
    if (cls.isAbstract) {
      flags |= ClassDeclaration.isAbstractFlag;
    }
    if (cls.isEnum) {
      flags |= ClassDeclaration.isEnumFlag;
    }
    int numTypeArguments = 0;
    TypeParametersDeclaration typeParameters;
    if (hasInstantiatorTypeArguments(cls)) {
      flags |= ClassDeclaration.hasTypeArgumentsFlag;
      numTypeArguments = flattenInstantiatorTypeArguments(
              cls, getTypeParameterTypes(cls.typeParameters))
          .length;
      assert(numTypeArguments > 0);
      if (cls.typeParameters.isNotEmpty) {
        flags |= ClassDeclaration.hasTypeParamsFlag;
        typeParameters = getTypeParametersDeclaration(cls.typeParameters);
      }
    }
    if (cls.isEliminatedMixin) {
      flags |= ClassDeclaration.isTransformedMixinApplicationFlag;
    }
    int position = TreeNode.noOffset;
    int endPosition = TreeNode.noOffset;
    if (options.emitSourcePositions && cls.fileOffset != TreeNode.noOffset) {
      flags |= ClassDeclaration.hasSourcePositionsFlag;
      position = cls.startFileOffset;
      endPosition = cls.fileEndOffset;
    }
    Annotations annotations = getAnnotations(cls.annotations);
    if (annotations.object != null) {
      flags |= ClassDeclaration.hasAnnotationsFlag;
      if (annotations.hasPragma) {
        flags |= ClassDeclaration.hasPragmaFlag;
      }
    }

    final nameHandle = objectTable.getNameHandle(
        cls.name.startsWith('_') ? cls.enclosingLibrary : null, cls.name);
    final script = getScript(cls.fileUri, !cls.isAnonymousMixin);
    final superType = objectTable.getHandle(cls.supertype?.asInterfaceType);
    final interfaces = objectTable.getHandles(
        cls.implementedTypes.map((t) => t.asInterfaceType).toList());

    final classDeclaration = new ClassDeclaration(
        nameHandle,
        flags,
        script,
        position,
        endPosition,
        typeParameters,
        numTypeArguments,
        superType,
        interfaces,
        members,
        annotations.object);
    bytecodeComponent.classes.add(classDeclaration);
    return classDeclaration;
  }

  ClassDeclaration getTopLevelClassDeclaration(
      Library library, Members members) {
    int flags = 0;
    int position = TreeNode.noOffset;
    if (options.emitSourcePositions &&
        library.fileOffset != TreeNode.noOffset) {
      flags |= ClassDeclaration.hasSourcePositionsFlag;
      position = library.fileOffset;
    }
    Annotations annotations = getLibraryAnnotations(library);
    if (annotations.object != null) {
      flags |= ClassDeclaration.hasAnnotationsFlag;
      if (annotations.hasPragma) {
        flags |= ClassDeclaration.hasPragmaFlag;
      }
    }

    final nameHandle = objectTable.getPublicNameHandle(topLevelClassName);
    final script = getScript(library.fileUri, true);

    final classDeclaration = new ClassDeclaration(
        nameHandle,
        flags,
        script,
        position,
        /* endPosition */ TreeNode.noOffset,
        /* typeParameters */ null,
        /* numTypeArguments */ 0,
        /* superType */ null,
        /* interfaces */ const <ObjectHandle>[],
        members,
        annotations.object);
    bytecodeComponent.classes.add(classDeclaration);
    return classDeclaration;
  }

  bool _isPragma(Constant annotation) =>
      annotation is InstanceConstant &&
      annotation.classNode == coreTypes.pragmaClass;

  Annotations getAnnotations(List<Expression> nodes) {
    if (nodes.isEmpty) {
      return const Annotations(null, false);
    }
    List<Constant> constants = nodes.map(_getConstant).toList();
    bool hasPragma = constants.any(_isPragma);
    if (!options.emitAnnotations) {
      if (hasPragma) {
        constants = constants.where(_isPragma).toList();
      } else {
        return const Annotations(null, false);
      }
    }
    final object =
        objectTable.getHandle(new ListConstant(const DynamicType(), constants));
    final decl = new AnnotationsDeclaration(object);
    bytecodeComponent.annotations.add(decl);
    return new Annotations(decl, hasPragma);
  }

  ObjectHandle getMemberAttributes() {
    if (procedureAttributesMetadata == null && inferredTypesAttribute == null) {
      return null;
    }
    // List of pairs (tag, value).
    final attrs = <Constant>[];
    if (procedureAttributesMetadata != null) {
      final attribute = procedureAttributesMetadataRepository
          .getBytecodeAttribute(procedureAttributesMetadata);
      attrs.add(
          StringConstant(ProcedureAttributesMetadataRepository.repositoryTag));
      attrs.add(attribute);
    }
    if (inferredTypesAttribute != null) {
      attrs.add(StringConstant(InferredTypeMetadataRepository.repositoryTag));
      attrs.add(ListConstant(const DynamicType(), inferredTypesAttribute));
    }
    return objectTable.getHandle(ListConstant(const DynamicType(), attrs));
  }

  ObjectHandle getClosureAttributes() {
    if (inferredTypesAttribute == null) {
      return null;
    }
    final attrs = <Constant>[
      StringConstant(InferredTypeMetadataRepository.repositoryTag),
      ListConstant(const DynamicType(), inferredTypesAttribute),
    ];
    return objectTable.getHandle(ListConstant(const DynamicType(), attrs));
  }

  // Insert annotations for the function and its parameters into the annotations
  // section. Return the annotations for the function only. The bytecode reader
  // will implicitly find the parameter annotations by reading N packed objects
  // after reading the function's annotations, one for each parameter.
  Annotations getFunctionAnnotations(Member member) {
    final functionNodes = member.annotations;
    final parameterNodeLists = new List<List<Expression>>();
    for (VariableDeclaration variable in member.function.positionalParameters) {
      parameterNodeLists.add(variable.annotations);
    }
    for (VariableDeclaration variable in member.function.namedParameters) {
      parameterNodeLists.add(variable.annotations);
    }

    if (functionNodes.isEmpty &&
        parameterNodeLists.every((nodes) => nodes.isEmpty)) {
      return const Annotations(null, false);
    }

    List<Constant> functionConstants = functionNodes.map(_getConstant).toList();
    bool hasPragma = functionConstants.any(_isPragma);
    if (!options.emitAnnotations && !hasPragma) {
      return const Annotations(null, false);
    }

    final functionObject = objectTable
        .getHandle(new ListConstant(const DynamicType(), functionConstants));
    final functionDecl = new AnnotationsDeclaration(functionObject);
    bytecodeComponent.annotations.add(functionDecl);

    for (final parameterNodes in parameterNodeLists) {
      List<Constant> parameterConstants =
          parameterNodes.map(_getConstant).toList();
      final parameterObject = objectTable
          .getHandle(new ListConstant(const DynamicType(), parameterConstants));
      final parameterDecl = new AnnotationsDeclaration(parameterObject);
      bytecodeComponent.annotations.add(parameterDecl);
    }

    return new Annotations(functionDecl, hasPragma);
  }

  // Insert annotations for library and its dependencies into the
  // annotations section. Returns annotations for the library only.
  // Bytecode reader will implicitly find library dependencies by reading
  // an extra object after reading library annotations.
  Annotations getLibraryAnnotations(Library library) {
    Annotations annotations = getAnnotations(library.annotations);
    final bool emitDependencies =
        options.emitAnnotations && library.dependencies.isNotEmpty;
    if (annotations.object == null && !emitDependencies) {
      return annotations;
    }

    // We need to emit both annotations and dependencies objects, appending
    // null if an object is missing.
    if (annotations.object == null) {
      final annotationsDecl = new AnnotationsDeclaration(null);
      bytecodeComponent.annotations.add(annotationsDecl);
      annotations = new Annotations(annotationsDecl, false);
    }
    if (!emitDependencies) {
      bytecodeComponent.annotations.add(new AnnotationsDeclaration(null));
      return annotations;
    }

    // Create a constant object representing library dependencies.
    // These objects are used by dart:mirrors and vm-service implementation.
    final deps = <Constant>[];
    for (var dependency in library.dependencies) {
      final prefix = dependency.name != null
          ? StringConstant(dependency.name)
          : NullConstant();
      final showNames = dependency.combinators
          .where((c) => c.isShow)
          .expand((c) => c.names)
          .map((name) => StringConstant(name))
          .toList();
      final hideNames = dependency.combinators
          .where((c) => c.isHide)
          .expand((c) => c.names)
          .map((name) => StringConstant(name))
          .toList();
      final depAnnots = dependency.annotations.map(_getConstant).toList();
      deps.add(ListConstant(const DynamicType(), <Constant>[
        StringConstant(dependency.targetLibrary.importUri.toString()),
        BoolConstant(dependency.isExport),
        BoolConstant(dependency.isDeferred),
        prefix,
        ListConstant(const DynamicType(), showNames),
        ListConstant(const DynamicType(), hideNames),
        ListConstant(const DynamicType(), depAnnots),
      ]));
    }
    final ObjectHandle dependenciesObject =
        objectTable.getHandle(ListConstant(const DynamicType(), deps));
    final dependenciesDecl = new AnnotationsDeclaration(dependenciesObject);
    bytecodeComponent.annotations.add(dependenciesDecl);

    return annotations;
  }

  FieldDeclaration getFieldDeclaration(Field field, Code initializer) {
    int flags = 0;
    Constant value;
    if (_hasNonTrivialInitializer(field)) {
      flags |= FieldDeclaration.hasNontrivialInitializerFlag;
    } else if (field.initializer != null) {
      value = _getConstant(field.initializer);
    }
    if (initializer != null) {
      flags |= FieldDeclaration.hasInitializerCodeFlag;
    }
    if (field.initializer != null) {
      flags |= FieldDeclaration.hasInitializerFlag;
    }
    final name = objectTable.getNameHandle(
        field.name.library, objectTable.mangleMemberName(field, false, false));
    ObjectHandle getterName;
    ObjectHandle setterName;
    if (_needsGetter(field)) {
      flags |= FieldDeclaration.hasGetterFlag;
      getterName = objectTable.getNameHandle(
          field.name.library, objectTable.mangleMemberName(field, true, false));
    }
    if (_needsSetter(field)) {
      flags |= FieldDeclaration.hasSetterFlag;
      setterName = objectTable.getNameHandle(
          field.name.library, objectTable.mangleMemberName(field, false, true));
    }
    if (isReflectable(field)) {
      flags |= FieldDeclaration.isReflectableFlag;
    }
    if (field.isStatic) {
      flags |= FieldDeclaration.isStaticFlag;
    }
    if (field.isConst) {
      flags |= FieldDeclaration.isConstFlag;
    }
    // Const fields are implicitly final.
    if (field.isConst || field.isFinal) {
      flags |= FieldDeclaration.isFinalFlag;
    }
    if (field.isCovariant) {
      flags |= FieldDeclaration.isCovariantFlag;
    }
    if (field.isGenericCovariantImpl) {
      flags |= FieldDeclaration.isGenericCovariantImplFlag;
    }
    if (field.isExtensionMember) {
      flags |= FieldDeclaration.isExtensionMemberFlag;
    }
    // In NNBD libraries, static fields with initializers are implicitly late.
    if (field.isLate ||
        (field.isStatic &&
            field.initializer != null &&
            field.isNonNullableByDefault)) {
      flags |= FieldDeclaration.isLateFlag;
    }
    int position = TreeNode.noOffset;
    int endPosition = TreeNode.noOffset;
    if (options.emitSourcePositions && field.fileOffset != TreeNode.noOffset) {
      flags |= FieldDeclaration.hasSourcePositionsFlag;
      position = field.fileOffset;
      endPosition = field.fileEndOffset;
    }
    Annotations annotations = getAnnotations(field.annotations);
    if (annotations.object != null) {
      flags |= FieldDeclaration.hasAnnotationsFlag;
      if (annotations.hasPragma) {
        flags |= FieldDeclaration.hasPragmaFlag;
      }
    }
    final ObjectHandle attributes = getMemberAttributes();
    if (attributes != null) {
      flags |= FieldDeclaration.hasAttributesFlag;
    }
    ObjectHandle script;
    if (field.fileUri != null &&
        field.fileUri != (field.parent as FileUriNode).fileUri) {
      final isInAnonymousMixin =
          enclosingClass != null && enclosingClass.isAnonymousMixin;
      script = getScript(field.fileUri, !isInAnonymousMixin);
      flags |= FieldDeclaration.hasCustomScriptFlag;
    }
    return new FieldDeclaration(
        flags,
        name,
        objectTable.getHandle(field.type),
        objectTable.getHandle(value),
        script,
        position,
        endPosition,
        getterName,
        setterName,
        initializer,
        annotations.object,
        attributes);
  }

  FunctionDeclaration getFunctionDeclaration(Member member, Code code) {
    int flags = 0;
    if (member is Constructor) {
      flags |= FunctionDeclaration.isConstructorFlag;
    }
    if (member is Procedure) {
      if (member.isGetter) {
        flags |= FunctionDeclaration.isGetterFlag;
      } else if (member.isSetter) {
        flags |= FunctionDeclaration.isSetterFlag;
      } else if (member.isFactory) {
        flags |= FunctionDeclaration.isFactoryFlag;
      }
      if (member.isStatic) {
        flags |= FunctionDeclaration.isStaticFlag;
      }
      if (member.isForwardingStub) {
        flags |= FunctionDeclaration.isForwardingStubFlag;
      }
      if (member.isNoSuchMethodForwarder) {
        flags |= FunctionDeclaration.isNoSuchMethodForwarderFlag;
      }
    }
    if (member.isAbstract && !_hasCode(member)) {
      flags |= FunctionDeclaration.isAbstractFlag;
    }
    if (member.isConst) {
      flags |= FunctionDeclaration.isConstFlag;
    }
    if (member.isExtensionMember) {
      flags |= FunctionDeclaration.isExtensionMemberFlag;
    }

    FunctionNode function = member.function;
    if (function.requiredParameterCount !=
        function.positionalParameters.length) {
      flags |= FunctionDeclaration.hasOptionalPositionalParamsFlag;
    }
    if (function.namedParameters.isNotEmpty) {
      flags |= FunctionDeclaration.hasOptionalNamedParamsFlag;
    }
    TypeParametersDeclaration typeParameters;
    if (function.typeParameters.isNotEmpty) {
      flags |= FunctionDeclaration.hasTypeParamsFlag;
      typeParameters = getTypeParametersDeclaration(function.typeParameters);
    }
    if (isReflectable(member)) {
      flags |= FunctionDeclaration.isReflectableFlag;
    }
    if (isDebuggable(member)) {
      flags |= FunctionDeclaration.isDebuggableFlag;
    }
    switch (function.dartAsyncMarker) {
      case AsyncMarker.Async:
        flags |= FunctionDeclaration.isAsyncFlag;
        break;
      case AsyncMarker.AsyncStar:
        flags |= FunctionDeclaration.isAsyncStarFlag;
        break;
      case AsyncMarker.SyncStar:
        flags |= FunctionDeclaration.isSyncStarFlag;
        break;
      default:
        break;
    }
    ObjectHandle nativeName;
    if (member.isExternal) {
      final String externalName = getExternalName(member);
      if (externalName == null) {
        flags |= FunctionDeclaration.isExternalFlag;
      } else {
        flags |= FunctionDeclaration.isNativeFlag;
        nativeName = objectTable.getConstStringHandle(externalName);
      }
    }
    int position = TreeNode.noOffset;
    int endPosition = TreeNode.noOffset;
    if (options.emitSourcePositions && member.fileOffset != TreeNode.noOffset) {
      flags |= FunctionDeclaration.hasSourcePositionsFlag;
      position = (member as dynamic).startFileOffset;
      endPosition = member.fileEndOffset;
    }
    final Annotations annotations = getFunctionAnnotations(member);
    if (annotations.object != null) {
      flags |= FunctionDeclaration.hasAnnotationsFlag;
      if (annotations.hasPragma) {
        flags |= FunctionDeclaration.hasPragmaFlag;
      }
    }
    final ObjectHandle attributes = getMemberAttributes();
    if (attributes != null) {
      flags |= FunctionDeclaration.hasAttributesFlag;
    }
    ObjectHandle script;
    if (member.fileUri != null &&
        member.fileUri != (member.parent as FileUriNode).fileUri) {
      final isInAnonymousMixin =
          enclosingClass != null && enclosingClass.isAnonymousMixin;
      final isSynthetic = member is Procedure &&
          (member.isNoSuchMethodForwarder || member.isSyntheticForwarder);
      script = getScript(member.fileUri, !isInAnonymousMixin && !isSynthetic);
      flags |= FunctionDeclaration.hasCustomScriptFlag;
    }

    final name = objectTable.getNameHandle(member.name.library,
        objectTable.mangleMemberName(member, false, false));

    final parameters = <ParameterDeclaration>[];
    for (var param in function.positionalParameters) {
      parameters.add(getParameterDeclaration(param));
    }
    for (var param in function.namedParameters) {
      parameters.add(getParameterDeclaration(param));
    }
    // We only need the required flags when loading the function declaration.
    final parameterFlags =
        getParameterFlags(function, mask: ParameterDeclaration.isRequiredFlag);
    if (parameterFlags != null) {
      flags |= FunctionDeclaration.hasParameterFlagsFlag;
    }

    return new FunctionDeclaration(
        flags,
        name,
        script,
        position,
        endPosition,
        typeParameters,
        function.requiredParameterCount,
        parameters,
        parameterFlags,
        objectTable.getHandle(function.returnType),
        nativeName,
        code,
        annotations.object,
        attributes);
  }

  bool isReflectable(Member member) {
    if (member is Field && member.fileOffset == TreeNode.noOffset) {
      return false;
    }
    final library = member.enclosingLibrary;
    if (library.importUri.scheme == 'dart' && member.name.isPrivate) {
      return false;
    }
    if (member is Procedure &&
        member.isStatic &&
        library.importUri.toString() == 'dart:_internal') {
      return false;
    }
    if (member is Procedure && member.isMemberSignature) {
      return false;
    }
    return true;
  }

  bool isDebuggable(Member member) {
    if (member is Constructor && member.isSynthetic) {
      return false;
    }
    if (member.function.dartAsyncMarker != AsyncMarker.Sync) {
      return false;
    }
    if (member == asyncAwaitCompleterGetFuture) {
      return false;
    }
    return true;
  }

  TypeParametersDeclaration getTypeParametersDeclaration(
      List<TypeParameter> typeParams) {
    return new TypeParametersDeclaration(
        objectTable.getTypeParameterHandles(typeParams));
  }

  ParameterDeclaration getParameterDeclaration(VariableDeclaration variable) {
    final name = variable.name;
    final lib = name.startsWith('_') ? enclosingMember.enclosingLibrary : null;
    final nameHandle = objectTable.getNameHandle(lib, name);
    final typeHandle = objectTable.getHandle(variable.type);
    return new ParameterDeclaration(nameHandle, typeHandle);
  }

  // Most uses of parameter flags in the VM only nee a subset of the flags,
  // so the optional [mask] argument allows the caller to specify the subset
  // that should be retained.
  List<int> getParameterFlags(FunctionNode function, {int mask = -1}) {
    int getFlags(VariableDeclaration variable, int mask) {
      int flags = 0;
      if (variable.isCovariant) {
        flags |= ParameterDeclaration.isCovariantFlag;
      }
      if (variable.isGenericCovariantImpl) {
        flags |= ParameterDeclaration.isGenericCovariantImplFlag;
      }
      if (variable.isFinal) {
        flags |= ParameterDeclaration.isFinalFlag;
      }
      if (variable.isRequired) {
        flags |= ParameterDeclaration.isRequiredFlag;
      }
      return flags & mask;
    }

    final List<int> paramFlags = <int>[];
    for (var param in function.positionalParameters) {
      paramFlags.add(getFlags(param, mask));
    }
    for (var param in function.namedParameters) {
      paramFlags.add(getFlags(param, mask));
    }

    for (int flags in paramFlags) {
      if (flags != 0) {
        return paramFlags;
      }
    }
    return null;
  }

  @override
  defaultMember(Member node) {
    if (node is Procedure && node.isRedirectingFactoryConstructor) {
      return;
    }
    try {
      final bool hasCode = _hasCode(node);
      start(node, hasCode);
      if (node is Field) {
        if (hasCode) {
          if (node.isConst) {
            _genPushConstExpr(node.initializer);
          } else {
            _generateNode(node.initializer);
          }
          _genReturnTOS();
        }
      } else if ((node is Procedure && !node.isRedirectingFactoryConstructor) ||
          (node is Constructor)) {
        if (hasCode) {
          if (node is Constructor) {
            _genConstructorInitializers(node);
          }
          if (node.isExternal) {
            final String nativeName = getExternalName(node);
            if (nativeName != null) {
              _genNativeCall(nativeName);
            } else {
              // TODO(alexmarkov): generate throwing UnimplementedError
              //  ("No definition given for external method Foo.bar").
              asm.emitPushNull();
            }
          } else {
            _generateNode(node.function?.body);
            // BytecodeAssembler eliminates this bytecode if it is unreachable.
            asm.emitPushNull();
          }
          if (node.function != null) {
            _recordSourcePosition(node.function.fileEndOffset);
          }
          _genReturnTOS();
        }
      } else {
        throw 'Unexpected member ${node.runtimeType} $node';
      }
      end(node, hasCode);
    } on TooManyArgumentsException catch (e) {
      CompilerContext.current.options.report(
          messageBytecodeLimitExceededTooManyArguments.withLocation(
              node.fileUri, e.fileOffset, noLength),
          Severity.error);
      hasErrors = true;
      end(node, false);
    }
  }

  bool _hasCode(Member member) {
    if (member is Procedure && member.isRedirectingFactoryConstructor) {
      return false;
    }
    // Front-end might set abstract flag on static external procedures,
    // but they can be called and should have a body.
    if (member is Procedure && member.isStatic && member.isExternal) {
      return true;
    }
    if (member.isAbstract) {
      return false;
    }
    if (member is Field) {
      // TODO(dartbug.com/34277)
      // Front-end inserts synthetic static fields "_redirecting#" to record
      // information about redirecting constructors in kernel.
      // The problem is that initializers of these synthetic static fields
      // contain incorrect kernel AST, e.g. StaticGet which takes tear-off
      // of a constructor. Do not generate bytecode for them, as they should
      // never be used.
      if (isRedirectingFactoryField(member)) {
        return false;
      }
      return hasInitializerCode(member);
    }
    return true;
  }

  bool hasInitializerCode(Field field) =>
      (field.isStatic ||
          field.isLate ||
          options.emitInstanceFieldInitializers) &&
      _hasNonTrivialInitializer(field);

  bool _needsGetter(Field field) {
    // All instance fields need a getter.
    if (!field.isStatic) return true;

    // Static fields also need a getter if they have a non-trivial initializer,
    // because it needs to be initialized lazily.
    if (_hasNonTrivialInitializer(field)) return true;

    // Static late fields with no initializer also need a getter, to check if
    // it's been initialized.
    return field.isLate && field.initializer == null;
  }

  bool _needsSetter(Field field) {
    // Late fields always need a setter, unless they're static and non-final, or
    // final with an initializer.
    if (field.isLate) {
      if (field.isStatic && !field.isFinal) return false;
      if (field.isFinal && field.initializer != null) return false;
      return true;
    }

    // Non-late static fields never need a setter.
    if (field.isStatic) return false;

    // Otherwise, the field only needs a setter if it isn't final.
    return !field.isFinal;
  }

  void _genNativeCall(String nativeName) {
    final function = enclosingMember.function;
    assert(function != null);

    if (locals.hasFactoryTypeArgsVar) {
      asm.emitPush(locals.getVarIndexInFrame(locals.factoryTypeArgsVar));
    } else if (locals.hasFunctionTypeArgsVar) {
      asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
    }
    if (locals.hasReceiver) {
      asm.emitPush(locals.getVarIndexInFrame(locals.receiverVar));
    }
    for (var param in function.positionalParameters) {
      asm.emitPush(locals.getVarIndexInFrame(param));
    }
    // Native methods access their parameters by indices, so
    // native wrappers should pass arguments in the original declaration
    // order instead of sorted order.
    for (var param in locals.originalNamedParameters) {
      asm.emitPush(locals.getVarIndexInFrame(param));
    }

    final nativeEntryCpIndex = cp.addNativeEntry(nativeName);
    asm.emitNativeCall(nativeEntryCpIndex);
  }

  LibraryIndex get libraryIndex => coreTypes.index;

  Procedure _listFromLiteral;
  Procedure get listFromLiteral => _listFromLiteral ??=
      libraryIndex.getMember('dart:core', 'List', '_fromLiteral');

  Procedure _mapFromLiteral;
  Procedure get mapFromLiteral => _mapFromLiteral ??=
      libraryIndex.getMember('dart:core', 'Map', '_fromLiteral');

  Procedure _interpolateSingle;
  Procedure get interpolateSingle => _interpolateSingle ??=
      libraryIndex.getMember('dart:core', '_StringBase', '_interpolateSingle');

  Procedure _interpolate;
  Procedure get interpolate => _interpolate ??=
      libraryIndex.getMember('dart:core', '_StringBase', '_interpolate');

  Class _closureClass;
  Class get closureClass =>
      _closureClass ??= libraryIndex.getClass('dart:core', '_Closure');

  Procedure _objectInstanceOf;
  Procedure get objectInstanceOf => _objectInstanceOf ??=
      libraryIndex.getMember('dart:core', 'Object', '_instanceOf');

  Procedure _objectSimpleInstanceOf;
  Procedure get objectSimpleInstanceOf => _objectSimpleInstanceOf ??=
      libraryIndex.getMember('dart:core', 'Object', '_simpleInstanceOf');

  Field _closureInstantiatorTypeArguments;
  Field get closureInstantiatorTypeArguments =>
      _closureInstantiatorTypeArguments ??= libraryIndex.getMember(
          'dart:core', '_Closure', '_instantiator_type_arguments');

  Field _closureFunctionTypeArguments;
  Field get closureFunctionTypeArguments =>
      _closureFunctionTypeArguments ??= libraryIndex.getMember(
          'dart:core', '_Closure', '_function_type_arguments');

  Field _closureDelayedTypeArguments;
  Field get closureDelayedTypeArguments =>
      _closureDelayedTypeArguments ??= libraryIndex.getMember(
          'dart:core', '_Closure', '_delayed_type_arguments');

  Field _closureFunction;
  Field get closureFunction => _closureFunction ??=
      libraryIndex.getMember('dart:core', '_Closure', '_function');

  Field _closureContext;
  Field get closureContext => _closureContext ??=
      libraryIndex.getMember('dart:core', '_Closure', '_context');

  Procedure _prependTypeArguments;
  Procedure get prependTypeArguments => _prependTypeArguments ??=
      libraryIndex.getTopLevelMember('dart:_internal', '_prependTypeArguments');

  Procedure _boundsCheckForPartialInstantiation;
  Procedure get boundsCheckForPartialInstantiation =>
      _boundsCheckForPartialInstantiation ??= libraryIndex.getTopLevelMember(
          'dart:_internal', '_boundsCheckForPartialInstantiation');

  Procedure _futureValue;
  Procedure get futureValue =>
      _futureValue ??= libraryIndex.getMember('dart:async', 'Future', 'value');

  Procedure _throwNewLateInitializationError;
  Procedure get throwNewLateInitializationError =>
      _throwNewLateInitializationError ??= libraryIndex.getMember(
          'dart:core', '_LateInitializationError', '_throwNew');

  Procedure _throwNewAssertionError;
  Procedure get throwNewAssertionError => _throwNewAssertionError ??=
      libraryIndex.getMember('dart:core', '_AssertionError', '_throwNew');

  Procedure _allocateInvocationMirror;
  Procedure get allocateInvocationMirror =>
      _allocateInvocationMirror ??= libraryIndex.getMember(
          'dart:core', '_InvocationMirror', '_allocateInvocationMirror');

  Procedure _unsafeCast;
  Procedure get unsafeCast => _unsafeCast ??=
      libraryIndex.getTopLevelMember('dart:_internal', 'unsafeCast');

  Procedure _iterableIterator;
  Procedure get iterableIterator => _iterableIterator ??=
      libraryIndex.getMember('dart:core', 'Iterable', 'get:iterator');

  Procedure _iteratorMoveNext;
  Procedure get iteratorMoveNext => _iteratorMoveNext ??=
      libraryIndex.getMember('dart:core', 'Iterator', 'moveNext');

  Procedure _iteratorCurrent;
  Procedure get iteratorCurrent => _iteratorCurrent ??=
      libraryIndex.getMember('dart:core', 'Iterator', 'get:current');

  Procedure _asyncAwaitCompleterGetFuture;
  Procedure get asyncAwaitCompleterGetFuture =>
      _asyncAwaitCompleterGetFuture ??= libraryIndex.tryGetMember(
          'dart:async', '_AsyncAwaitCompleter', 'get:future');

  Procedure _setAsyncThreadStackTrace;
  Procedure get setAsyncThreadStackTrace => _setAsyncThreadStackTrace ??=
      libraryIndex.getTopLevelMember('dart:async', '_setAsyncThreadStackTrace');

  Procedure _clearAsyncThreadStackTrace;
  Procedure get clearAsyncThreadStackTrace =>
      _clearAsyncThreadStackTrace ??= libraryIndex.getTopLevelMember(
          'dart:async', '_clearAsyncThreadStackTrace');

  Library _dartFfiLibrary;
  Library get dartFfiLibrary =>
      _dartFfiLibrary ??= libraryIndex.tryGetLibrary('dart:ffi');

  void _recordSourcePosition(int fileOffset) {
    asm.currentSourcePosition = fileOffset;
    maxSourcePosition = math.max(maxSourcePosition, fileOffset);
  }

  void _generateNode(TreeNode node) {
    if (node == null) {
      return;
    }
    final savedSourcePosition = asm.currentSourcePosition;
    _recordSourcePosition(node.fileOffset);
    node.accept(this);
    asm.currentSourcePosition = savedSourcePosition;
  }

  void _generateNodeList(List<TreeNode> nodes) {
    nodes.forEach(_generateNode);
  }

  void _genConstructorInitializers(Constructor node) {
    bool isRedirecting = false;
    Set<Field> initializedInInitializersList = new Set<Field>();
    for (var initializer in node.initializers) {
      if (initializer is RedirectingInitializer) {
        isRedirecting = true;
      } else if (initializer is FieldInitializer) {
        initializedInInitializersList.add(initializer.field);
      }
    }

    if (!isRedirecting) {
      initializedFields = new Set<Field>();
      for (var field in node.enclosingClass.fields) {
        if (!field.isStatic) {
          if (field.isLate) {
            if (!initializedInInitializersList.contains(field)) {
              _genLateFieldInitializer(field);
            }
          } else if (field.initializer != null) {
            if (initializedInInitializersList.contains(field)) {
              // Do not store a value into the field as it is going to be
              // overwritten by initializers list.
              _generateNode(field.initializer);
              asm.emitDrop1();
            } else {
              _genFieldInitializer(field, field.initializer);
            }
          }
        }
      }
    }

    _generateNodeList(node.initializers);

    if (!isRedirecting) {
      nullableFields = <ObjectHandle>[];
      for (var field in node.enclosingClass.fields) {
        if (!field.isStatic &&
            !field.isLate &&
            !initializedFields.contains(field)) {
          nullableFields.add(objectTable.getHandle(field));
        }
      }
      initializedFields = null; // No more initialized fields, please.
    }
  }

  void _genFieldInitializer(Field field, Expression initializer) {
    assert(!field.isStatic);

    if (initializer is NullLiteral && !initializedFields.contains(field)) {
      return;
    }

    _genPushReceiver();
    _generateNode(initializer);

    final int cpIndex = cp.addInstanceField(field);
    asm.emitStoreFieldTOS(cpIndex);

    initializedFields.add(field);
  }

  void _genLateFieldInitializer(Field field) {
    assert(!field.isStatic);

    if (_isTrivialInitializer(field.initializer)) {
      _genFieldInitializer(field, field.initializer);
      return;
    }

    _genPushReceiver();

    final int cpIndex = cp.addInstanceField(field);
    asm.emitInitLateField(cpIndex);

    initializedFields.add(field);
  }

  void _genArguments(Expression receiver, Arguments arguments,
      {int storeReceiverToLocal}) {
    if (arguments.types.isNotEmpty) {
      _genTypeArguments(arguments.types);
    }
    _generateNode(receiver);
    if (storeReceiverToLocal != null) {
      asm.emitStoreLocal(storeReceiverToLocal);
    }
    _generateNodeList(arguments.positional);
    arguments.named.forEach((NamedExpression ne) => _generateNode(ne.value));
  }

  void _genPushBool(bool value) {
    if (value) {
      asm.emitPushTrue();
    } else {
      asm.emitPushFalse();
    }
  }

  void _genPushInt(int value) {
    // TODO(alexmarkov): relax this constraint as PushInt instruction can
    // hold up to 32-bit signed operand (note that interpreter assumes
    // it is Smi).
    if (value.bitLength + 1 <= 16) {
      asm.emitPushInt(value);
    } else {
      asm.emitPushConstant(cp.addObjectRef(new IntConstant(value)));
    }
  }

  Constant _getConstant(Expression expr) {
    if (expr is ConstantExpression) {
      return expr.constant;
    }

    // Literals outside of const expressions are not transformed by the
    // constant transformer, but they need to be treated as constants here.
    if (expr is BoolLiteral) return new BoolConstant(expr.value);
    if (expr is DoubleLiteral) return new DoubleConstant(expr.value);
    if (expr is IntLiteral) return new IntConstant(expr.value);
    if (expr is NullLiteral) return new NullConstant();
    if (expr is StringLiteral) return new StringConstant(expr.value);

    throw 'Expected constant, got ${expr.runtimeType}';
  }

  void _genPushConstant(Constant constant) {
    if (constant is NullConstant) {
      asm.emitPushNull();
    } else if (constant is BoolConstant) {
      _genPushBool(constant.value);
    } else if (constant is IntConstant) {
      _genPushInt(constant.value);
    } else {
      asm.emitPushConstant(cp.addObjectRef(constant));
    }
  }

  void _genPushConstExpr(Expression expr) {
    if (expr is ConstantExpression) {
      _genPushConstant(expr.constant);
    } else if (expr is NullLiteral) {
      asm.emitPushNull();
    } else if (expr is BoolLiteral) {
      _genPushBool(expr.value);
    } else if (expr is IntLiteral) {
      _genPushInt(expr.value);
    } else {
      _genPushConstant(_getConstant(expr));
    }
  }

  void _genReturnTOS([int yieldSourcePosition = null]) {
    if (options.causalAsyncStacks &&
        parentFunction != null &&
        (parentFunction.dartAsyncMarker == AsyncMarker.Async ||
            parentFunction.dartAsyncMarker == AsyncMarker.AsyncStar)) {
      final savedSourcePosition = asm.currentSourcePosition;
      _recordSourcePosition(TreeNode.noOffset);
      _genDirectCall(
          clearAsyncThreadStackTrace, objectTable.getArgDescHandle(0), 0);
      asm.emitDrop1();
      asm.currentSourcePosition = savedSourcePosition;
    }

    if (yieldSourcePosition != null && options.emitSourcePositions) {
      asm.emitYieldPointSourcePosition(yieldSourcePosition);
    }
    asm.emitReturnTOS();
  }

  void _genDirectCall(Member target, ObjectHandle argDesc, int totalArgCount,
      {bool isGet: false,
      bool isSet: false,
      bool isDynamicForwarder: false,
      bool isUnchecked: false,
      TreeNode node}) {
    assert(!isGet || !isSet);
    final kind = isGet
        ? InvocationKind.getter
        : (isSet ? InvocationKind.setter : InvocationKind.method);
    final cpIndex = cp.addDirectCall(kind, target, argDesc, isDynamicForwarder);

    if (totalArgCount >= argumentsLimit) {
      throw new TooManyArgumentsException(node.fileOffset);
    }
    if (inferredTypeMetadata != null && node != null) {
      _appendInferredType(node, asm.offset);
    }
    if (isUnchecked) {
      asm.emitUncheckedDirectCall(cpIndex, totalArgCount);
    } else {
      asm.emitDirectCall(cpIndex, totalArgCount);
    }
    if (inferredTypeMetadata != null && node != null) {
      _replaceWithConstantValue(node);
    }
  }

  void _genDirectCallWithArgs(Member target, Arguments args,
      {bool hasReceiver: false,
      bool isFactory: false,
      bool isUnchecked: false,
      TreeNode node}) {
    final argDesc = objectTable.getArgDescHandleByArguments(args,
        hasReceiver: hasReceiver, isFactory: isFactory);

    int totalArgCount = args.positional.length + args.named.length;
    if (hasReceiver) {
      totalArgCount++;
    }
    if (args.types.isNotEmpty || isFactory) {
      // VM needs type arguments for every invocation of a factory constructor.
      // TODO(alexmarkov): Clean this up.
      totalArgCount++;
    }

    _genDirectCall(target, argDesc, totalArgCount,
        isUnchecked: isUnchecked, node: node);
  }

  void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
    int typeArgsCPIndex() {
      if (instantiatingClass != null) {
        typeArgs = getInstantiatorTypeArguments(instantiatingClass, typeArgs);
      }
      return cp.addTypeArguments(typeArgs);
    }

    if (typeArgs.isEmpty || !hasFreeTypeParameters(typeArgs)) {
      asm.emitPushConstant(typeArgsCPIndex());
    } else {
      final flattenedTypeArgs = (instantiatingClass != null &&
              (instantiatorTypeArguments != null ||
                  functionTypeParameters != null))
          ? flattenInstantiatorTypeArguments(instantiatingClass, typeArgs)
          : typeArgs;
      if (_canReuseInstantiatorTypeArguments(flattenedTypeArgs)) {
        _genPushInstantiatorTypeArguments();
      } else if (_canReuseFunctionTypeArguments(flattenedTypeArgs)) {
        _genPushFunctionTypeArguments();
      } else {
        _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
        // TODO(alexmarkov): Optimize type arguments instantiation
        // by passing rA = 1 in InstantiateTypeArgumentsTOS.
        // For this purpose, we need to detect if type arguments
        // would be all-dynamic in case of all-dynamic instantiator and
        // function type arguments.
        // Corresponding check is implemented in VM in
        // TypeArguments::IsRawWhenInstantiatedFromRaw.
        asm.emitInstantiateTypeArgumentsTOS(0, typeArgsCPIndex());
      }
    }
  }

  void _genPushInstantiatorAndFunctionTypeArguments(List<DartType> types) {
    if (classTypeParameters != null &&
        types.any((t) => containsTypeVariable(t, classTypeParameters))) {
      assert(instantiatorTypeArguments != null);
      _genPushInstantiatorTypeArguments();
    } else {
      asm.emitPushNull();
    }
    if (functionTypeParametersSet != null &&
        types.any((t) => containsTypeVariable(t, functionTypeParametersSet))) {
      _genPushFunctionTypeArguments();
    } else {
      asm.emitPushNull();
    }
  }

  void _genPushInstantiatorTypeArguments() {
    if (instantiatorTypeArguments != null) {
      if (locals.hasFactoryTypeArgsVar) {
        assert(enclosingMember is Procedure &&
            (enclosingMember as Procedure).isFactory);
        _genLoadVar(locals.factoryTypeArgsVar);
      } else {
        _genPushReceiver();
        final int cpIndex = cp.addTypeArgumentsField(enclosingClass);
        asm.emitLoadTypeArgumentsField(cpIndex);
      }
    } else {
      asm.emitPushNull();
    }
  }

  bool _canReuseInstantiatorTypeArguments(List<DartType> typeArgs) {
    if (instantiatorTypeArguments == null) {
      return false;
    }

    if (typeArgs.length > instantiatorTypeArguments.length) {
      return false;
    }

    for (int i = 0; i < typeArgs.length; ++i) {
      if (typeArgs[i] != instantiatorTypeArguments[i]) {
        return false;
      }
    }

    return true;
  }

  bool _canReuseFunctionTypeArguments(List<DartType> typeArgs) {
    if (functionTypeParameters == null) {
      return false;
    }

    if (typeArgs.length > functionTypeParameters.length) {
      return false;
    }

    for (int i = 0; i < typeArgs.length; ++i) {
      final typeArg = typeArgs[i];
      if (!(typeArg is TypeParameterType &&
          typeArg.parameter == functionTypeParameters[i] &&
          (typeArg.nullability == Nullability.nonNullable ||
              typeArg.nullability == Nullability.undetermined))) {
        return false;
      }
    }

    return true;
  }

  void _genPushFunctionTypeArguments() {
    if (locals.hasFunctionTypeArgsVar) {
      asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
    } else {
      asm.emitPushNull();
    }
  }

  void _genPushContextForVariable(VariableDeclaration variable,
      {int currentContextLevel}) {
    currentContextLevel ??= locals.currentContextLevel;
    int depth = currentContextLevel - locals.getContextLevelOfVar(variable);
    assert(depth >= 0);

    asm.emitPush(locals.contextVarIndexInFrame);
    if (depth > 0) {
      for (; depth > 0; --depth) {
        asm.emitLoadContextParent();
      }
    }
  }

  void _genPushContextIfCaptured(VariableDeclaration variable) {
    if (locals.isCaptured(variable)) {
      _genPushContextForVariable(variable);
    }
  }

  void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
    if (locals.isCaptured(v)) {
      _genPushContextForVariable(v, currentContextLevel: currentContextLevel);
      asm.emitLoadContextVar(
          locals.getVarContextId(v), locals.getVarIndexInContext(v));
    } else {
      asm.emitPush(locals.getVarIndexInFrame(v));
    }
  }

  void _genPushReceiver() {
    // TODO(alexmarkov): generate more efficient access to receiver
    // even if it is captured.
    _genLoadVar(locals.receiverVar);
  }

  // Stores value into variable.
  // If variable is captured, context should be pushed before value.
  void _genStoreVar(VariableDeclaration variable) {
    if (locals.isCaptured(variable)) {
      asm.emitStoreContextVar(locals.getVarContextId(variable),
          locals.getVarIndexInContext(variable));
    } else {
      asm.emitPopLocal(locals.getVarIndexInFrame(variable));
    }
  }

  /// Generates bool condition. Returns `true` if condition is negated.
  bool _genCondition(Expression condition) {
    bool negated = false;
    if (condition is Not) {
      condition = (condition as Not).operand;
      negated = true;
    }
    _generateNode(condition);
    if (nullabilityDetector.isNullable(condition)) {
      asm.emitAssertBoolean(0);
    }
    return negated;
  }

  /// Returns value of the given expression if it is a bool constant.
  /// Otherwise, returns `null`.
  bool _constantConditionValue(Expression condition) {
    if (options.keepUnreachableCode) {
      return null;
    }
    // TODO(dartbug.com/34585): use constant evaluator to evaluate
    // expressions in a non-constant context.
    if (condition is Not) {
      final operand = _constantConditionValue(condition.operand);
      return (operand != null) ? !operand : null;
    }
    if (condition is BoolLiteral) {
      return condition.value;
    }
    if (condition is ConstantExpression) {
      Constant constant = condition.constant;
      if (constant is BoolConstant) {
        return constant.value;
      }
    }
    return null;
  }

  void _genConditionAndJumpIf(Expression condition, bool value, Label dest) {
    final bool constantValue = _constantConditionValue(condition);
    if (constantValue != null) {
      if (constantValue == value) {
        asm.emitJump(dest);
      }
      return;
    }
    if (condition is MethodInvocation &&
        condition.name.text == '==' &&
        (condition.receiver is NullLiteral ||
            condition.arguments.positional.single is NullLiteral)) {
      if (condition.receiver is NullLiteral) {
        _generateNode(condition.arguments.positional.single);
      } else {
        _generateNode(condition.receiver);
      }
      if (options.emitDebuggerStops &&
          condition.fileOffset != TreeNode.noOffset) {
        final savedSourcePosition = asm.currentSourcePosition;
        _recordSourcePosition(condition.fileOffset);
        asm.emitDebugCheck();
        asm.currentSourcePosition = savedSourcePosition;
      }
      if (value) {
        asm.emitJumpIfNull(dest);
      } else {
        asm.emitJumpIfNotNull(dest);
      }
      return;
    }
    if (condition is Not) {
      _genConditionAndJumpIf(condition.operand, !value, dest);
    } else if (condition is LogicalExpression) {
      final isOR = (condition.operatorEnum == LogicalExpressionOperator.OR);

      Label shortCircuit, done;
      if (isOR == value) {
        shortCircuit = dest;
      } else {
        shortCircuit = done = new Label();
      }
      _genConditionAndJumpIf(condition.left, isOR, shortCircuit);
      _genConditionAndJumpIf(condition.right, value, dest);
      if (done != null) {
        asm.bind(done);
      }
    } else {
      bool negated = _genCondition(condition);
      if (negated) {
        value = !value;
      }
      if (value) {
        asm.emitJumpIfTrue(dest);
      } else {
        asm.emitJumpIfFalse(dest);
      }
    }
  }

  int _getDefaultParamConstIndex(VariableDeclaration param) {
    if (param.initializer == null) {
      return cp.addObjectRef(null);
    }
    final constant = _getConstant(param.initializer);
    return cp.addObjectRef(constant);
  }

  // Duplicates value on top of the stack using temporary variable with
  // given index.
  void _genDupTOS(int tempIndexInFrame) {
    // TODO(alexmarkov): Consider introducing Dup bytecode or keeping track of
    // expression stack depth.
    asm.emitStoreLocal(tempIndexInFrame);
    asm.emitPush(tempIndexInFrame);
  }

  /// Generates is-test for the value at TOS.
  void _genInstanceOf(DartType type) {
    if (typeEnvironment.isTop(type)) {
      asm.emitDrop1();
      asm.emitPushTrue();
      return;
    }

    if (type is InterfaceType &&
        (type.typeArguments.isEmpty || isAllDynamic(type.typeArguments))) {
      asm.emitPushConstant(cp.addType(type));
      final argDesc = objectTable.getArgDescHandle(2);
      final cpIndex = cp.addInterfaceCall(
          InvocationKind.method, objectSimpleInstanceOf, argDesc);
      asm.emitInterfaceCall(cpIndex, 2);
      return;
    }

    if (hasFreeTypeParameters([type])) {
      _genPushInstantiatorAndFunctionTypeArguments([type]);
    } else {
      asm.emitPushNull(); // Instantiator type arguments.
      asm.emitPushNull(); // Function type arguments.
    }
    asm.emitPushConstant(cp.addType(type));
    final argDesc = objectTable.getArgDescHandle(4);
    final cpIndex =
        cp.addInterfaceCall(InvocationKind.method, objectInstanceOf, argDesc);
    asm.emitInterfaceCall(cpIndex, 4);
  }

  void start(Member node, bool hasCode) {
    enclosingClass = node.enclosingClass;
    enclosingMember = node;
    enclosingFunction = node.function;
    parentFunction = null;
    isClosure = false;
    hasErrors = false;
    staticTypeContext.enterMember(node);
    final isFactory = node is Procedure && node.isFactory;
    if (node.isInstanceMember || node is Constructor || isFactory) {
      if (enclosingClass.typeParameters.isNotEmpty) {
        classTypeParameters =
            new Set<TypeParameter>.from(enclosingClass.typeParameters);
        // Treat type arguments of factory constructors as class
        // type parameters.
        if (isFactory) {
          classTypeParameters.addAll(node.function.typeParameters);
        }
      }
      if (hasInstantiatorTypeArguments(enclosingClass)) {
        final typeParameters = getTypeParameterTypes(isFactory
            ? node.function.typeParameters
            : enclosingClass.typeParameters);
        instantiatorTypeArguments =
            flattenInstantiatorTypeArguments(enclosingClass, typeParameters);
      }
    }
    if (enclosingFunction != null &&
        enclosingFunction.typeParameters.isNotEmpty) {
      functionTypeParameters =
          new List<TypeParameter>.from(enclosingFunction.typeParameters);
      functionTypeParametersSet = functionTypeParameters.toSet();
    }
    procedureAttributesMetadata = procedureAttributesMetadataRepository != null
        ? procedureAttributesMetadataRepository.mapping[node]
        : null;

    if (inferredTypeMetadata != null) {
      if (node is Field) {
        // Field type is at PC = -1.
        _appendInferredType(node, -1);
      } else if (enclosingFunction != null && hasCode) {
        assert(node is Procedure || node is Constructor);
        // Parameter types are at PC = -N,..,-1 where N - number of declared
        // (explicit) parameters.
        int i = -(enclosingFunction.positionalParameters.length +
            enclosingFunction.namedParameters.length);
        for (var v in enclosingFunction.positionalParameters) {
          _appendInferredType(v, i);
          ++i;
        }
        for (var v in enclosingFunction.namedParameters) {
          _appendInferredType(v, i);
          ++i;
        }
      }
    }

    if (!hasCode) {
      return;
    }

    labeledStatements = null;
    switchCases = null;
    tryCatches = null;
    finallyBlocks = null;
    yieldPoints = null; // Initialized when entering sync-yielding closure.
    contextLevels = null;
    closures = null;
    initializedFields = null; // Tracked for constructors only.
    nullableFields = const <ObjectHandle>[];
    cp = new ConstantPool(stringTable, objectTable);
    asm = new BytecodeAssembler(options);
    savedAssemblers = null;
    currentLoopDepth = 0;
    savedMaxSourcePositions = <int>[];
    maxSourcePosition = node.fileOffset;

    locals = new LocalVariables(
        node, options, staticTypeContext, directCallMetadata);
    locals.enterScope(node);
    assert(!locals.isSyncYieldingFrame);

    int position;
    if (node is Procedure) {
      position = node.startFileOffset;
    } else if (node is Constructor) {
      position = node.startFileOffset;
    } else {
      position = node.fileOffset;
    }
    _recordSourcePosition(position);
    _genPrologue(node, node.function);
    _setupInitialContext(node.function);
    _emitFirstDebugCheck(node.function);
    if (node is Procedure && node.isInstanceMember) {
      _checkArguments(node.function);
    }
    _genEqualsOperatorNullHandling(node);
  }

  void _appendInferredType(TreeNode node, int pc) {
    final InferredType md = inferredTypeMetadata[node];
    if (md == null || (pc >= 0 && asm.isUnreachable)) {
      return;
    }
    inferredTypesAttribute ??= <Constant>[];
    // List of triplets (PC, concreteClass, flags).
    // Verify that PCs are monotonically increasing.
    assert(inferredTypesAttribute.isEmpty ||
        (inferredTypesAttribute[inferredTypesAttribute.length - 3]
                    as IntConstant)
                .value <
            pc);
    inferredTypesAttribute.add(IntConstant(pc));
    Class concreteClass = md.concreteClass;
    // VM uses more specific function type and doesn't expect to
    // see inferred _Closure class.
    if (concreteClass != null && concreteClass != closureClass) {
      inferredTypesAttribute.add(TypeLiteralConstant(coreTypes.rawType(
          concreteClass,
          (concreteClass == coreTypes.nullClass)
              ? Nullability.nullable
              : staticTypeContext.nonNullable)));
    } else {
      inferredTypesAttribute.add(NullConstant());
    }
    // Inferred constant values are handled in bytecode generator
    // (_replaceWithConstantValue, _initConstantParameters) and
    // not propagated to VM.
    final flags = md.flags & ~InferredType.flagConstant;
    inferredTypesAttribute.add(IntConstant(flags));
  }

  void _replaceWithConstantValue(TreeNode node) {
    final InferredType md = inferredTypeMetadata[node];
    if (md == null || md.constantValue == null || asm.isUnreachable) {
      return;
    }
    asm.emitDrop1();
    _genPushConstant(md.constantValue);
  }

  // Generate additional code for 'operator ==' to handle nulls.
  void _genEqualsOperatorNullHandling(Member member) {
    if (member.name.text != '==' ||
        locals.numParameters != 2 ||
        member.enclosingClass == coreTypes.objectClass) {
      return;
    }

    Label done = new Label();

    _genLoadVar(member.function.positionalParameters[0]);
    asm.emitJumpIfNotNull(done);

    asm.emitPushFalse();
    _genReturnTOS();

    asm.bind(done);
  }

  void end(Member node, bool hasCode) {
    if (!hasErrors) {
      Code code;
      if (hasCode) {
        if (options.emitLocalVarInfo) {
          // Leave the scopes which were entered in _genPrologue and
          // _setupInitialContext.
          asm.localVariableTable.leaveAllScopes(
              asm.offset,
              node.function != null
                  ? node.function.fileEndOffset
                  : node.fileEndOffset);
        }

        List<int> parameterFlags = null;
        int forwardingStubTargetCpIndex = null;
        int defaultFunctionTypeArgsCpIndex = null;

        // We don't need the required flag when loading the code, but do need
        // all other parameter flags.
        final parameterFlagMask = ~ParameterDeclaration.isRequiredFlag;

        if (node is Constructor) {
          parameterFlags =
              getParameterFlags(node.function, mask: parameterFlagMask);
        } else if (node is Procedure) {
          parameterFlags =
              getParameterFlags(node.function, mask: parameterFlagMask);

          if (node.isForwardingStub) {
            forwardingStubTargetCpIndex =
                cp.addObjectRef(node.forwardingStubSuperTarget);
          }

          final defaultTypes = getDefaultFunctionTypeArguments(node.function);
          if (defaultTypes != null) {
            defaultFunctionTypeArgsCpIndex = cp.addTypeArguments(defaultTypes);
          }
        }
        code = new Code(
            cp,
            asm.bytecode,
            asm.exceptionsTable,
            finalizeSourcePositions(),
            finalizeLocalVariables(),
            nullableFields,
            closures ?? const <ClosureDeclaration>[],
            parameterFlags,
            forwardingStubTargetCpIndex,
            defaultFunctionTypeArgsCpIndex);
        bytecodeComponent.codes.add(code);
      }
      if (node is Field) {
        fieldDeclarations.add(getFieldDeclaration(node, code));
      } else {
        functionDeclarations.add(getFunctionDeclaration(node, code));
      }
    }

    staticTypeContext.leaveMember(node);
    enclosingClass = null;
    enclosingMember = null;
    enclosingFunction = null;
    parentFunction = null;
    isClosure = null;
    classTypeParameters = null;
    functionTypeParameters = null;
    functionTypeParametersSet = null;
    instantiatorTypeArguments = null;
    locals = null;
    labeledStatements = null;
    switchCases = null;
    tryCatches = null;
    finallyBlocks = null;
    yieldPoints = null;
    contextLevels = null;
    closures = null;
    initializedFields = null;
    nullableFields = null;
    cp = null;
    asm = null;
    savedAssemblers = null;
    hasErrors = false;
    procedureAttributesMetadata = null;
    inferredTypesAttribute = null;
  }

  SourcePositions finalizeSourcePositions() {
    if (asm.sourcePositions.isEmpty) {
      return null;
    }
    bytecodeComponent.sourcePositions.add(asm.sourcePositions);
    return asm.sourcePositions;
  }

  LocalVariableTable finalizeLocalVariables() {
    final localVariables = asm.localVariableTable;
    assert(!localVariables.hasActiveScopes);
    if (localVariables.isEmpty) {
      return null;
    }
    bytecodeComponent.localVariables.add(localVariables);
    return localVariables;
  }

  void _genPrologue(Node node, FunctionNode function) {
    if (locals.hasOptionalParameters) {
      final int numOptionalPositional = function.positionalParameters.length -
          function.requiredParameterCount;
      final int numOptionalNamed = function.namedParameters.length;
      final int numFixed =
          locals.numParameters - (numOptionalPositional + numOptionalNamed);

      asm.emitEntryOptional(numFixed, numOptionalPositional, numOptionalNamed);

      if (numOptionalPositional != 0) {
        assert(numOptionalNamed == 0);
        for (int i = 0; i < numOptionalPositional; i++) {
          final param = function
              .positionalParameters[function.requiredParameterCount + i];
          asm.emitLoadConstant(numFixed + i, _getDefaultParamConstIndex(param));
        }
      } else {
        assert(numOptionalNamed != 0);
        for (int i = 0; i < numOptionalNamed; i++) {
          final param = locals.sortedNamedParameters[i];
          asm.emitLoadConstant(numFixed + i, cp.addName(param.name));
          asm.emitLoadConstant(numFixed + i, _getDefaultParamConstIndex(param));
        }
      }

      asm.emitFrame(locals.frameSize - locals.numParameters);
    } else {
      asm.emitEntry(locals.frameSize);
    }

    if (isClosure) {
      asm.emitPush(locals.closureVarIndexInFrame);
      asm.emitLoadFieldTOS(cp.addInstanceField(closureContext));
      asm.emitPopLocal(locals.contextVarIndexInFrame);
    }

    if (locals.hasFunctionTypeArgsVar && function.typeParameters.isNotEmpty) {
      assert(!(node is Procedure && node.isFactory));

      Label done = new Label();

      if (isClosure) {
        _handleDelayedTypeArguments(done);
      }

      asm.emitCheckFunctionTypeArgs(function.typeParameters.length,
          locals.functionTypeArgsVarIndexInFrame);

      _handleDefaultTypeArguments(function, done);

      asm.bind(done);
    }

    // Open initial scope before the first CheckStack, as VM might
    // need to know context level.
    if (options.emitLocalVarInfo && function != null) {
      asm.localVariableTable.enterScope(
          asm.offset,
          isClosure ? locals.contextLevelAtEntry : locals.currentContextLevel,
          function.fileOffset);
      if (locals.hasContextVar) {
        asm.localVariableTable
            .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
      }
      if (locals.hasReceiver &&
          (!isClosure || locals.isCaptured(locals.receiverVar))) {
        _declareLocalVariable(locals.receiverVar, function.fileOffset);
      }
      for (var v in function.positionalParameters) {
        if (!locals.isCaptured(v)) {
          _declareLocalVariable(v, function.fileOffset);
        }
      }
      for (var v in locals.sortedNamedParameters) {
        if (!locals.isCaptured(v)) {
          _declareLocalVariable(v, function.fileOffset);
        }
      }
      if (locals.hasFunctionTypeArgsVar) {
        _declareLocalVariable(locals.functionTypeArgsVar, function.fileOffset);
      }
    }

    // CheckStack must see a properly initialized context when stress-testing
    // stack trace collection.
    asm.emitCheckStack(0);

    if (locals.hasFunctionTypeArgsVar && isClosure) {
      if (function.typeParameters.isNotEmpty) {
        final int numParentTypeArgs = locals.numParentTypeArguments;
        asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
        asm.emitPush(locals.closureVarIndexInFrame);
        asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));
        _genPushInt(numParentTypeArgs);
        _genPushInt(numParentTypeArgs + function.typeParameters.length);
        _genDirectCall(
            prependTypeArguments, objectTable.getArgDescHandle(4), 4);
        asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
      } else {
        asm.emitPush(locals.closureVarIndexInFrame);
        asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));
        asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
      }
    }

    if (inferredTypeMetadata != null && function != null) {
      _initConstantParameters(function);
    }
  }

  void _handleDelayedTypeArguments(Label doneCheckingTypeArguments) {
    Label noDelayedTypeArgs = new Label();

    asm.emitPush(locals.closureVarIndexInFrame);
    asm.emitLoadFieldTOS(cp.addInstanceField(closureDelayedTypeArguments));
    asm.emitStoreLocal(locals.functionTypeArgsVarIndexInFrame);
    asm.emitPushConstant(cp.addEmptyTypeArguments());
    asm.emitJumpIfEqStrict(noDelayedTypeArgs);

    // There are non-empty delayed type arguments, and they are stored
    // into function type args variable already.
    // Just verify that there are no passed type arguments.
    asm.emitCheckFunctionTypeArgs(0, locals.scratchVarIndexInFrame);
    asm.emitJump(doneCheckingTypeArguments);

    asm.bind(noDelayedTypeArgs);
  }

  void _handleDefaultTypeArguments(
      FunctionNode function, Label doneCheckingTypeArguments) {
    List<DartType> defaultTypes = getDefaultFunctionTypeArguments(function);
    if (defaultTypes == null) {
      return;
    }

    asm.emitJumpIfNotZeroTypeArgs(doneCheckingTypeArguments);

    // Load parent function type arguments if they are used to
    // instantiate default types.
    if (isClosure &&
        defaultTypes
            .any((t) => containsTypeVariable(t, functionTypeParametersSet))) {
      asm.emitPush(locals.closureVarIndexInFrame);
      asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));
      asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
    }

    _genTypeArguments(defaultTypes);
    asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
  }

  void _initConstantParameters(FunctionNode function) {
    function.positionalParameters.forEach(_initParameterIfConstant);
    locals.sortedNamedParameters.forEach(_initParameterIfConstant);
  }

  void _initParameterIfConstant(VariableDeclaration variable) {
    final md = inferredTypeMetadata[variable];
    if (md != null && md.constantValue != null) {
      _genPushConstant(md.constantValue);
      asm.emitPopLocal(locals.isCaptured(variable)
          ? locals.getOriginalParamSlotIndex(variable)
          : locals.getVarIndexInFrame(variable));
    }
  }

  void _setupInitialContext(FunctionNode function) {
    _allocateContextIfNeeded();

    if (options.emitLocalVarInfo && locals.currentContextSize > 0) {
      // Open a new scope after allocating context.
      asm.localVariableTable.enterScope(asm.offset, locals.currentContextLevel,
          function != null ? function.fileOffset : enclosingMember.fileOffset);
    }

    if (locals.hasCapturedParameters) {
      // Copy captured parameters to their respective locations in the context.
      if (!isClosure) {
        if (locals.hasFactoryTypeArgsVar) {
          _copyParamIfCaptured(locals.factoryTypeArgsVar);
        }
        if (locals.hasCapturedReceiverVar) {
          _genPushContextForVariable(locals.capturedReceiverVar);
          asm.emitPush(locals.getVarIndexInFrame(locals.receiverVar));
          _genStoreVar(locals.capturedReceiverVar);
        }
      }
      if (function != null) {
        function.positionalParameters.forEach(_copyParamIfCaptured);
        locals.sortedNamedParameters.forEach(_copyParamIfCaptured);
      }
    }
  }

  void _emitFirstDebugCheck(FunctionNode function) {
    if (options.emitDebuggerStops) {
      // DebugCheck instruction should be emitted after parameter variables
      // are declared and copied into context.
      // The debugger expects the source position to correspond to the
      // declaration position of the last parameter, if any, or of the function.
      // The DebugCheck must be encountered each time an async op is reentered.
      if (options.emitSourcePositions && function != null) {
        var pos = TreeNode.noOffset;
        if (function.namedParameters.isNotEmpty) {
          pos = function.namedParameters.last.fileOffset;
        } else if (function.positionalParameters.isNotEmpty) {
          pos = function.positionalParameters.last.fileOffset;
        }
        if (pos == TreeNode.noOffset) {
          pos = function.fileOffset;
        }
        _recordSourcePosition(pos);
      }
      asm.emitDebugCheck();
    }
  }

  void _copyParamIfCaptured(VariableDeclaration variable) {
    if (locals.isCaptured(variable)) {
      if (options.emitLocalVarInfo) {
        _declareLocalVariable(variable, enclosingFunction.fileOffset);
      }
      _genPushContextForVariable(variable);
      asm.emitPush(locals.getOriginalParamSlotIndex(variable));
      _genStoreVar(variable);
      // TODO(alexmarkov): We need to store null at the original parameter
      // location, because the original value may need to be GC'ed.
    }
  }

  void _declareLocalVariable(
      VariableDeclaration variable, int initializedPosition) {
    assert(variable.name != null);
    bool isCaptured = locals.isCaptured(variable);
    asm.localVariableTable.declareVariable(
        asm.offset,
        isCaptured,
        isCaptured
            ? locals.getVarIndexInContext(variable)
            : locals.getVarIndexInFrame(variable),
        cp.addName(variable.name),
        cp.addType(variable.type),
        variable.fileOffset,
        initializedPosition);
  }

  // TODO(dartbug.com/40813): Remove the closure case when we move the
  // type checks out of closure bodies.
  bool get canSkipTypeChecksForNonCovariantArguments => !isClosure;

  bool get skipTypeChecksForGenericCovariantImplArguments =>
      procedureAttributesMetadata != null &&
      !procedureAttributesMetadata.hasNonThisUses &&
      // TODO(alexmarkov): fix building of flow graph for implicit closures so
      // it would include missing checks and remove this condition.
      !procedureAttributesMetadata.hasTearOffUses;

  Member _getForwardingStubSuperTarget() {
    if (!isClosure) {
      final member = enclosingMember;
      if (member.isInstanceMember &&
          member is Procedure &&
          member.isForwardingStub) {
        return member.forwardingStubSuperTarget;
      }
    }
    return null;
  }

  // Types in a target of a forwarding stub are encoded in terms of target type
  // parameters. Substitute them with host type parameters to be able
  // to use them (e.g. instantiate) in the context of host.
  Substitution _getForwardingSubstitution(
      FunctionNode host, Member forwardingTarget) {
    if (forwardingTarget == null) {
      return null;
    }
    final Class targetClass = forwardingTarget.enclosingClass;
    final Supertype instantiatedTargetClass =
        hierarchy.getClassAsInstanceOf(enclosingClass, targetClass);
    if (instantiatedTargetClass == null) {
      throw 'Class $targetClass is not found among implemented interfaces of'
          ' $enclosingClass (for forwarding stub $enclosingMember)';
    }
    assert(instantiatedTargetClass.classNode == targetClass);
    assert(instantiatedTargetClass.typeArguments.length ==
        targetClass.typeParameters.length);
    final Map<TypeParameter, DartType> map =
        new Map<TypeParameter, DartType>.fromIterables(
            targetClass.typeParameters, instantiatedTargetClass.typeArguments);
    if (forwardingTarget.function != null) {
      final targetTypeParameters = forwardingTarget.function.typeParameters;
      assert(host.typeParameters.length == targetTypeParameters.length);
      for (int i = 0; i < targetTypeParameters.length; ++i) {
        map[targetTypeParameters[i]] =
            new TypeParameterType(host.typeParameters[i], Nullability.legacy);
      }
    }
    return Substitution.fromMap(map);
  }

  /// If member being compiled is a forwarding stub, then returns type
  /// parameter bounds to check for the forwarding stub target.
  Map<TypeParameter, DartType> _getForwardingBounds(FunctionNode function,
      Member forwardingTarget, Substitution forwardingSubstitution) {
    if (function.typeParameters.isEmpty || forwardingTarget == null) {
      return null;
    }
    final forwardingBounds = <TypeParameter, DartType>{};
    for (int i = 0; i < function.typeParameters.length; ++i) {
      DartType bound = forwardingSubstitution
          .substituteType(forwardingTarget.function.typeParameters[i].bound);
      forwardingBounds[function.typeParameters[i]] = bound;
    }
    return forwardingBounds;
  }

  /// If member being compiled is a forwarding stub, then returns parameter
  /// types to check for the forwarding stub target.
  Map<VariableDeclaration, DartType> _getForwardingParameterTypes(
      FunctionNode function,
      Member forwardingTarget,
      Substitution forwardingSubstitution) {
    if (forwardingTarget == null) {
      return null;
    }

    if (forwardingTarget is Field) {
      if ((enclosingMember as Procedure).isGetter) {
        return const <VariableDeclaration, DartType>{};
      } else {
        // Forwarding stub for a covariant field setter.
        assert((enclosingMember as Procedure).isSetter);
        assert(function.typeParameters.isEmpty &&
            function.positionalParameters.length == 1 &&
            function.namedParameters.length == 0);
        return <VariableDeclaration, DartType>{
          function.positionalParameters.single:
              forwardingSubstitution.substituteType(forwardingTarget.type)
        };
      }
    }

    final forwardingParams = <VariableDeclaration, DartType>{};
    for (int i = 0; i < function.positionalParameters.length; ++i) {
      DartType type = forwardingSubstitution.substituteType(
          forwardingTarget.function.positionalParameters[i].type);
      forwardingParams[function.positionalParameters[i]] = type;
    }
    for (var hostParam in function.namedParameters) {
      VariableDeclaration targetParam = forwardingTarget
          .function.namedParameters
          .firstWhere((p) => p.name == hostParam.name);
      forwardingParams[hostParam] =
          forwardingSubstitution.substituteType(targetParam.type);
    }
    return forwardingParams;
  }

  void _checkArguments(FunctionNode function) {
    // When checking arguments of a forwarding stub, we need to use parameter
    // types (and bounds of type parameters) from stub's target.
    // These more accurate type checks is the sole purpose of a forwarding stub.
    final forwardingTarget = _getForwardingStubSuperTarget();
    final forwardingSubstitution =
        _getForwardingSubstitution(function, forwardingTarget);
    final forwardingBounds = _getForwardingBounds(
        function, forwardingTarget, forwardingSubstitution);
    final forwardingParamTypes = _getForwardingParameterTypes(
        function, forwardingTarget, forwardingSubstitution);

    if (_hasSkippableTypeChecks(
        function, forwardingBounds, forwardingParamTypes)) {
      final Label skipChecks = new Label();
      asm.emitJumpIfUnchecked(skipChecks);

      // We can skip bounds checks of type parameter and type checks of
      // non-covariant parameters if function is called via unchecked call.

      for (var typeParam in function.typeParameters) {
        if (_typeParameterNeedsBoundCheck(typeParam, forwardingBounds)) {
          _genTypeParameterBoundCheck(typeParam, forwardingBounds);
        }
      }
      for (var param in function.positionalParameters) {
        if (!param.isCovariant &&
            _parameterNeedsTypeCheck(param, forwardingParamTypes)) {
          _genArgumentTypeCheck(param, forwardingParamTypes);
        }
      }
      for (var param in locals.sortedNamedParameters) {
        if (!param.isCovariant &&
            _parameterNeedsTypeCheck(param, forwardingParamTypes)) {
          _genArgumentTypeCheck(param, forwardingParamTypes);
        }
      }

      asm.bind(skipChecks);
    }

    // Covariant parameters need to be checked even if function is called
    // via unchecked call, so they are generated outside of JumpIfUnchecked.

    for (var param in function.positionalParameters) {
      if (param.isCovariant &&
          _parameterNeedsTypeCheck(param, forwardingParamTypes)) {
        _genArgumentTypeCheck(param, forwardingParamTypes);
      }
    }
    for (var param in locals.sortedNamedParameters) {
      if (param.isCovariant &&
          _parameterNeedsTypeCheck(param, forwardingParamTypes)) {
        _genArgumentTypeCheck(param, forwardingParamTypes);
      }
    }
  }

  /// Returns true if bound of [typeParam] should be checked.
  bool _typeParameterNeedsBoundCheck(TypeParameter typeParam,
      Map<TypeParameter, DartType> forwardingTypeParameterBounds) {
    if (canSkipTypeChecksForNonCovariantArguments &&
        (!typeParam.isGenericCovariantImpl ||
            skipTypeChecksForGenericCovariantImplArguments)) {
      return false;
    }
    final DartType bound = (forwardingTypeParameterBounds != null)
        ? forwardingTypeParameterBounds[typeParam]
        : typeParam.bound;
    if (typeEnvironment.isTop(bound)) {
      return false;
    }
    return true;
  }

  /// Returns true if type of [param] should be checked.
  bool _parameterNeedsTypeCheck(VariableDeclaration param,
      Map<VariableDeclaration, DartType> forwardingParameterTypes) {
    if (canSkipTypeChecksForNonCovariantArguments &&
        !param.isCovariant &&
        (!param.isGenericCovariantImpl ||
            skipTypeChecksForGenericCovariantImplArguments)) {
      return false;
    }
    final DartType type = (forwardingParameterTypes != null)
        ? forwardingParameterTypes[param]
        : param.type;
    if (typeEnvironment.isTop(type)) {
      return false;
    }
    return true;
  }

  /// Returns true if there are parameter type/bound checks which can
  /// be skipped on unchecked call.
  bool _hasSkippableTypeChecks(
      FunctionNode function,
      Map<TypeParameter, DartType> forwardingBounds,
      Map<VariableDeclaration, DartType> forwardingParamTypes) {
    for (var typeParam in function.typeParameters) {
      if (_typeParameterNeedsBoundCheck(typeParam, forwardingBounds)) {
        return true;
      }
    }
    for (var param in function.positionalParameters) {
      if (!param.isCovariant &&
          _parameterNeedsTypeCheck(param, forwardingParamTypes)) {
        return true;
      }
    }
    for (var param in locals.sortedNamedParameters) {
      if (!param.isCovariant &&
          _parameterNeedsTypeCheck(param, forwardingParamTypes)) {
        return true;
      }
    }
    return false;
  }

  void _genTypeParameterBoundCheck(TypeParameter typeParam,
      Map<TypeParameter, DartType> forwardingTypeParameterBounds) {
    final DartType bound = (forwardingTypeParameterBounds != null)
        ? forwardingTypeParameterBounds[typeParam]
        : typeParam.bound;
    final DartType type = new TypeParameterType(typeParam, Nullability.legacy);
    _genPushInstantiatorAndFunctionTypeArguments([type, bound]);
    asm.emitPushConstant(cp.addType(type));
    asm.emitPushConstant(cp.addType(bound));
    asm.emitPushConstant(cp.addName(typeParam.name));
    asm.emitAssertSubtype();
  }

  void _genArgumentTypeCheck(VariableDeclaration variable,
      Map<VariableDeclaration, DartType> forwardingParameterTypes) {
    final DartType type = (forwardingParameterTypes != null)
        ? forwardingParameterTypes[variable]
        : variable.type;
    if (locals.isCaptured(variable)) {
      asm.emitPush(locals.getOriginalParamSlotIndex(variable));
    } else {
      asm.emitPush(locals.getVarIndexInFrame(variable));
    }
    _genAssertAssignable(type, name: variable.name);
    asm.emitDrop1();
  }

  void _genAssertAssignable(DartType type, {String name, String message}) {
    assert(!typeEnvironment.isTop(type));
    asm.emitPushConstant(cp.addType(type));
    _genPushInstantiatorAndFunctionTypeArguments([type]);
    asm.emitPushConstant(
        name != null ? cp.addName(name) : cp.addString(message));
    bool isIntOk = typeEnvironment.isSubtypeOf(
        typeEnvironment.coreTypes.intLegacyRawType,
        type,
        SubtypeCheckMode.ignoringNullabilities);
    int subtypeTestCacheCpIndex = cp.addSubtypeTestCache();
    asm.emitAssertAssignable(isIntOk ? 1 : 0, subtypeTestCacheCpIndex);
  }

  void _pushAssemblerState() {
    savedAssemblers ??= <BytecodeAssembler>[];
    savedAssemblers.add(asm);
    asm = new BytecodeAssembler(options);
  }

  void _popAssemblerState() {
    asm = savedAssemblers.removeLast();
  }

  int _genClosureBytecode(
      LocalFunction node, String name, FunctionNode function) {
    _pushAssemblerState();

    locals.enterScope(node);

    final savedParentFunction = parentFunction;
    parentFunction = enclosingFunction;
    final savedIsClosure = isClosure;
    isClosure = true;
    enclosingFunction = function;
    final savedLoopDepth = currentLoopDepth;
    currentLoopDepth = 0;
    final savedInferredTypesAttribute = inferredTypesAttribute;
    inferredTypesAttribute = null;

    if (function.typeParameters.isNotEmpty) {
      functionTypeParameters ??= new List<TypeParameter>();
      functionTypeParameters.addAll(function.typeParameters);
      functionTypeParametersSet = functionTypeParameters.toSet();
    }

    List<Label> savedYieldPoints = yieldPoints;
    yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;

    closures ??= <ClosureDeclaration>[];
    final int closureIndex = closures.length;
    final closure = getClosureDeclaration(node, function, name, closureIndex,
        savedIsClosure ? parentFunction : enclosingMember);
    closures.add(closure);

    final int closureFunctionIndex = cp.addClosureFunction(closureIndex);

    _recordSourcePosition(function.fileOffset);
    _genPrologue(node, function);

    if (options.causalAsyncStacks &&
        parentFunction != null &&
        (parentFunction.dartAsyncMarker == AsyncMarker.Async ||
            parentFunction.dartAsyncMarker == AsyncMarker.AsyncStar)) {
      final savedSourcePosition = asm.currentSourcePosition;
      _recordSourcePosition(TreeNode.noOffset);
      _genLoadVar(locals.asyncStackTraceVar,
          currentContextLevel: locals.contextLevelAtEntry);
      _genDirectCall(
          setAsyncThreadStackTrace, objectTable.getArgDescHandle(1), 1);
      asm.emitDrop1();
      asm.currentSourcePosition = savedSourcePosition;
    }

    Label continuationSwitchLabel;
    int continuationSwitchVar;
    if (locals.isSyncYieldingFrame) {
      continuationSwitchLabel = new Label();
      continuationSwitchVar = locals.scratchVarIndexInFrame;
      _genSyncYieldingPrologue(
          function, continuationSwitchLabel, continuationSwitchVar);
    } else {
      _setupInitialContext(function);
      _emitFirstDebugCheck(function);
    }
    _checkArguments(function);

    _generateNode(function.body);

    // BytecodeAssembler eliminates this bytecode if it is unreachable.
    _recordSourcePosition(function.fileEndOffset);
    asm.emitPushNull();
    _genReturnTOS();

    if (locals.isSyncYieldingFrame) {
      _genSyncYieldingEpilogue(
          function, continuationSwitchLabel, continuationSwitchVar);
    }

    if (options.emitLocalVarInfo) {
      // Leave the scopes which were entered in _genPrologue and
      // _setupInitialContext.
      asm.localVariableTable.leaveAllScopes(asm.offset, function.fileEndOffset);
    }

    cp.addEndClosureFunctionScope();

    if (function.typeParameters.isNotEmpty) {
      functionTypeParameters.length -= function.typeParameters.length;
      functionTypeParametersSet = functionTypeParameters.toSet();
    }

    enclosingFunction = parentFunction;
    parentFunction = savedParentFunction;
    isClosure = savedIsClosure;
    currentLoopDepth = savedLoopDepth;

    final attributes = getClosureAttributes();
    if (attributes != null) {
      closure.attributes = attributes;
      closure.flags |= ClosureDeclaration.hasAttributesFlag;
    }
    inferredTypesAttribute = savedInferredTypesAttribute;

    locals.leaveScope();

    closure.code = new ClosureCode(asm.bytecode, asm.exceptionsTable,
        finalizeSourcePositions(), finalizeLocalVariables());

    _popAssemblerState();
    yieldPoints = savedYieldPoints;

    return closureFunctionIndex;
  }

  ClosureDeclaration getClosureDeclaration(LocalFunction node,
      FunctionNode function, String name, int closureIndex, TreeNode parent) {
    objectTable.declareClosure(function, enclosingMember, closureIndex);

    int flags = 0;
    int position = TreeNode.noOffset;
    int endPosition = TreeNode.noOffset;
    if (options.emitSourcePositions) {
      position = (node is ast.FunctionDeclaration)
          ? node.fileOffset
          : function.fileOffset;
      endPosition = function.fileEndOffset;
      if (position != TreeNode.noOffset) {
        flags |= ClosureDeclaration.hasSourcePositionsFlag;
      }
    }

    switch (function.dartAsyncMarker) {
      case AsyncMarker.Async:
        flags |= ClosureDeclaration.isAsyncFlag;
        break;
      case AsyncMarker.AsyncStar:
        flags |= ClosureDeclaration.isAsyncStarFlag;
        break;
      case AsyncMarker.SyncStar:
        flags |= ClosureDeclaration.isSyncStarFlag;
        break;
      default:
        flags |= ClosureDeclaration.isDebuggableFlag;
        break;
    }

    final List<NameAndType> parameters = <NameAndType>[];
    for (var v in function.positionalParameters) {
      parameters.add(new NameAndType(objectTable.getPublicNameHandle(v.name),
          objectTable.getHandle(v.type)));
    }
    for (var v in function.namedParameters) {
      parameters.add(new NameAndType(objectTable.getPublicNameHandle(v.name),
          objectTable.getHandle(v.type)));
    }
    if (function.requiredParameterCount != parameters.length) {
      if (function.namedParameters.isNotEmpty) {
        flags |= ClosureDeclaration.hasOptionalNamedParamsFlag;
      } else {
        flags |= ClosureDeclaration.hasOptionalPositionalParamsFlag;
      }
    }

    final typeParams =
        objectTable.getTypeParameterHandles(function.typeParameters);
    if (typeParams.isNotEmpty) {
      flags |= ClosureDeclaration.hasTypeParamsFlag;
    }

    // We only need the required flags when loading the closure declaration.
    final parameterFlags =
        getParameterFlags(function, mask: ParameterDeclaration.isRequiredFlag);
    if (parameterFlags != null) {
      flags |= ClosureDeclaration.hasParameterFlagsFlag;
    }

    return new ClosureDeclaration(
        flags,
        objectTable.getHandle(parent),
        objectTable.getPublicNameHandle(name),
        position,
        endPosition,
        typeParams,
        function.requiredParameterCount,
        function.namedParameters.length,
        parameters,
        parameterFlags,
        objectTable.getHandle(function.returnType));
  }

  void _genSyncYieldingPrologue(FunctionNode function, Label continuationLabel,
      int switchVarIndexInFrame) {
    Label debugCheckLabel = new Label();

    // switch_var = :await_jump_var
    _genLoadVar(locals.awaitJumpVar);
    asm.emitStoreLocal(switchVarIndexInFrame);

    _genPushInt(0);

    if (options.emitDebuggerStops) {
      // if (switch_var != 0) goto debugCheckLabel
      asm.emitJumpIfNeStrict(debugCheckLabel);

      _setupInitialContext(function);

      asm.bind(debugCheckLabel);
      // The debugger may set a breakpoint on this DebugCheck opcode and it
      // expects to hit it on the first entry to the async op, as well as on
      // each subsequent reentry.
      _emitFirstDebugCheck(function);

      _genLoadVar(locals.awaitJumpVar);

      // if (switch_var != 0) goto continuationLabel
      _genPushInt(0);
      asm.emitJumpIfNeStrict(continuationLabel);
    } else {
      // if (switch_var != 0) goto continuationLabel
      asm.emitJumpIfNeStrict(continuationLabel);

      _setupInitialContext(function);
    }

    // Proceed to normal entry.
  }

  void _genSyncYieldingEpilogue(FunctionNode function, Label continuationLabel,
      int switchVarIndexInFrame) {
    asm.bind(continuationLabel);

    if (yieldPoints.isEmpty) {
      asm.emitTrap();
      return;
    }

    // context = :await_ctx_var
    _genLoadVar(locals.awaitContextVar);
    asm.emitPopLocal(locals.contextVarIndexInFrame);

    for (int i = 0; i < yieldPoints.length; i++) {
      // 0 is reserved for normal entry, yield points are counted from 1.
      final int index = i + 1;

      // if (switch_var == #index) goto yieldPoints[i]
      // There is no need to test switch_var for the last yield statement.
      if (i != yieldPoints.length - 1) {
        asm.emitPush(switchVarIndexInFrame);
        _genPushInt(index);
        asm.emitJumpIfEqStrict(yieldPoints[i]);
      } else {
        asm.emitJump(yieldPoints[i]);
      }
    }
  }

  void _genAllocateClosureInstance(
      TreeNode node, int closureFunctionIndex, FunctionNode function) {
    asm.emitAllocateClosure(closureFunctionIndex);

    final int temp = locals.tempIndexInFrame(node);
    asm.emitStoreLocal(temp);

    // TODO(alexmarkov): We need to fill _instantiator_type_arguments field
    // only if function signature uses instantiator type arguments.
    asm.emitPush(temp);
    _genPushInstantiatorTypeArguments();
    asm.emitStoreFieldTOS(
        cp.addInstanceField(closureInstantiatorTypeArguments));

    asm.emitPush(temp);
    _genPushFunctionTypeArguments();
    asm.emitStoreFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));

    // Delayed type arguments are only used by generic closures.
    if (function.typeParameters.isNotEmpty) {
      asm.emitPush(temp);
      asm.emitPushConstant(cp.addEmptyTypeArguments());
      asm.emitStoreFieldTOS(cp.addInstanceField(closureDelayedTypeArguments));
    }

    asm.emitPush(temp);
    asm.emitPushConstant(closureFunctionIndex);
    asm.emitStoreFieldTOS(cp.addInstanceField(closureFunction));

    asm.emitPush(temp);
    asm.emitPush(locals.contextVarIndexInFrame);
    asm.emitStoreFieldTOS(cp.addInstanceField(closureContext));
  }

  void _genClosure(LocalFunction node, String name, FunctionNode function) {
    final int closureFunctionIndex = _genClosureBytecode(node, name, function);
    _genAllocateClosureInstance(node, closureFunctionIndex, function);
  }

  void _allocateContextIfNeeded() {
    final int contextSize = locals.currentContextSize;
    if (contextSize > 0) {
      asm.emitAllocateContext(locals.currentContextId, contextSize);

      if (locals.currentContextLevel > 0) {
        _genDupTOS(locals.scratchVarIndexInFrame);
        asm.emitPush(locals.contextVarIndexInFrame);
        asm.emitStoreContextParent();
      }

      asm.emitPopLocal(locals.contextVarIndexInFrame);
    }
  }

  void _enterScope(TreeNode node) {
    locals.enterScope(node);
    _allocateContextIfNeeded();
    if (options.emitLocalVarInfo) {
      asm.localVariableTable
          .enterScope(asm.offset, locals.currentContextLevel, node.fileOffset);
      _startRecordingMaxPosition(node.fileOffset);
    }
  }

  void _leaveScope() {
    if (options.emitLocalVarInfo) {
      asm.localVariableTable.leaveScope(asm.offset, _endRecordingMaxPosition());
    }
    if (locals.currentContextSize > 0) {
      _genUnwindContext(locals.currentContextLevel - 1);
    }
    locals.leaveScope();
  }

  void _startRecordingMaxPosition(int fileOffset) {
    savedMaxSourcePositions.add(maxSourcePosition);
    maxSourcePosition = fileOffset;
  }

  int _endRecordingMaxPosition() {
    int localMax = maxSourcePosition;
    maxSourcePosition =
        math.max(localMax, savedMaxSourcePositions.removeLast());
    return localMax;
  }

  void _genUnwindContext(int targetContextLevel) {
    int currentContextLevel = locals.currentContextLevel;
    assert(currentContextLevel >= targetContextLevel);
    while (currentContextLevel > targetContextLevel) {
      asm.emitPush(locals.contextVarIndexInFrame);
      asm.emitLoadContextParent();
      asm.emitPopLocal(locals.contextVarIndexInFrame);
      --currentContextLevel;
    }
  }

  /// Returns the list of try-finally blocks between [from] and [to],
  /// ordered from inner to outer. If [to] is null, returns all enclosing
  /// try-finally blocks up to the function boundary.
  List<TryFinally> _getEnclosingTryFinallyBlocks(TreeNode from, TreeNode to) {
    List<TryFinally> blocks = <TryFinally>[];
    TreeNode node = from;
    for (;;) {
      if (node == to) {
        return blocks;
      }
      if (node == null || node is FunctionNode || node is Member) {
        if (to == null) {
          return blocks;
        } else {
          throw 'Unable to find node $to up from $from';
        }
      }
      // Inspect parent as we only need try-finally blocks enclosing [node]
      // in the body, and not in the finally-block.
      final parent = node.parent;
      if (parent is TryFinally && parent.body == node) {
        blocks.add(parent);
      }
      node = parent;
    }
  }

  /// Appends chained [FinallyBlock]s to each try-finally in the given
  /// list [tryFinallyBlocks] (ordered from inner to outer).
  /// [continuation] is invoked to generate control transfer code following
  /// the last finally block.
  void _addFinallyBlocks(
      List<TryFinally> tryFinallyBlocks, GenerateContinuation continuation) {
    // Add finally blocks to all try-finally from outer to inner.
    // The outermost finally block should generate continuation, each inner
    // finally block should proceed to a corresponding outer block.
    for (var tryFinally in tryFinallyBlocks.reversed) {
      final finallyBlock = new FinallyBlock(continuation);
      finallyBlocks[tryFinally].add(finallyBlock);

      final Label nextFinally = finallyBlock.entry;
      continuation = () {
        asm.emitJump(nextFinally);
      };
    }

    // Generate jump to the innermost finally (or to the original
    // continuation if there are no try-finally blocks).
    continuation();
  }

  /// Generates non-local transfer from inner node [from] into the outer
  /// node, executing finally blocks on the way out. [to] can be null,
  /// in such case all enclosing finally blocks are executed.
  /// [continuation] is invoked to generate control transfer code following
  /// the last finally block.
  void _generateNonLocalControlTransfer(
      TreeNode from, TreeNode to, GenerateContinuation continuation) {
    if (options.emitDebuggerStops && from.fileOffset != TreeNode.noOffset) {
      asm.emitDebugCheck(); // Before context is unwound.
    }
    List<TryFinally> tryFinallyBlocks = _getEnclosingTryFinallyBlocks(from, to);
    _addFinallyBlocks(tryFinallyBlocks, continuation);
  }

  // For certain expressions wrapped into ExpressionStatement we can
  // omit pushing result on the stack.
  bool isExpressionWithoutResult(Expression expr) =>
      expr.parent is ExpressionStatement &&
      (expr is VariableSet ||
          expr is PropertySet ||
          expr is StaticSet ||
          expr is SuperPropertySet ||
          expr is DirectPropertySet);

  void _createArgumentsArray(int temp, List<DartType> typeArgs,
      List<Expression> args, bool storeLastArgumentToTemp) {
    final int totalCount = (typeArgs.isNotEmpty ? 1 : 0) + args.length;

    _genTypeArguments([const DynamicType()]);
    _genPushInt(totalCount);
    asm.emitCreateArrayTOS();

    asm.emitStoreLocal(temp);

    int index = 0;
    if (typeArgs.isNotEmpty) {
      asm.emitPush(temp);
      _genPushInt(index++);
      _genTypeArguments(typeArgs);
      asm.emitStoreIndexedTOS();
    }

    for (Expression arg in args) {
      asm.emitPush(temp);
      _genPushInt(index++);
      _generateNode(arg);
      if (storeLastArgumentToTemp && index == totalCount) {
        // Arguments array in 'temp' is replaced with the last argument
        // in order to return result of RHS value in case of setter.
        asm.emitStoreLocal(temp);
      }
      asm.emitStoreIndexedTOS();
    }
  }

  void _genNoSuchMethodForSuperCall(String name, int temp, int argDescCpIndex,
      List<DartType> typeArgs, List<Expression> args,
      {bool storeLastArgumentToTemp: false}) {
    // Receiver for noSuchMethod() call.
    _genPushReceiver();

    // Argument 0 for _allocateInvocationMirror(): function name.
    asm.emitPushConstant(cp.addName(name));

    // Argument 1 for _allocateInvocationMirror(): arguments descriptor.
    asm.emitPushConstant(argDescCpIndex);

    // Argument 2 for _allocateInvocationMirror(): list of arguments.
    _createArgumentsArray(temp, typeArgs, args, storeLastArgumentToTemp);

    // Argument 3 for _allocateInvocationMirror(): isSuperInvocation flag.
    asm.emitPushTrue();

    _genDirectCall(
        allocateInvocationMirror, objectTable.getArgDescHandle(4), 4);

    final Member target = hierarchy.getDispatchTarget(
        enclosingClass.superclass, noSuchMethodName);
    assert(target != null);
    _genDirectCall(target, objectTable.getArgDescHandle(2), 2);
  }

  @override
  defaultTreeNode(Node node) => throw new UnsupportedOperationError(
      'Unsupported node ${node.runtimeType}');

  @override
  visitAsExpression(AsExpression node) {
    _generateNode(node.operand);

    final type = node.type;
    if (typeEnvironment.isTop(type)) {
      return;
    }

    _genAssertAssignable(type,
        message: node.isTypeError ? '' : symbolForTypeCast);
  }

  @override
  visitBoolLiteral(BoolLiteral node) {
    _genPushBool(node.value);
  }

  @override
  visitIntLiteral(IntLiteral node) {
    _genPushInt(node.value);
  }

  @override
  visitDoubleLiteral(DoubleLiteral node) {
    final cpIndex = cp.addObjectRef(new DoubleConstant(node.value));
    asm.emitPushConstant(cpIndex);
  }

  @override
  visitConditionalExpression(ConditionalExpression node) {
    final Label otherwisePart = new Label();
    final Label done = new Label();
    final int temp = locals.tempIndexInFrame(node);

    _genConditionAndJumpIf(node.condition, false, otherwisePart);

    _generateNode(node.then);
    asm.emitPopLocal(temp);
    asm.emitJump(done);

    asm.bind(otherwisePart);
    _generateNode(node.otherwise);
    asm.emitPopLocal(temp);

    asm.bind(done);
    asm.emitPush(temp);
  }

  @override
  visitConstructorInvocation(ConstructorInvocation node) {
    if (node.isConst) {
      _genPushConstExpr(node);
      return;
    }

    final constructedClass = node.constructedType.classNode;
    final classIndex = cp.addClass(constructedClass);

    if (hasInstantiatorTypeArguments(constructedClass)) {
      _genTypeArguments(node.arguments.types,
          instantiatingClass: constructedClass);
      asm.emitPushConstant(cp.addClass(constructedClass));
      asm.emitAllocateT();
    } else {
      assert(node.arguments.types.isEmpty);
      asm.emitAllocate(classIndex);
    }

    _genDupTOS(locals.tempIndexInFrame(node));

    // Remove type arguments as they are only passed to instance allocation,
    // and not passed to a constructor.
    final args =
        new Arguments(node.arguments.positional, named: node.arguments.named)
          ..parent = node;
    _genArguments(null, args);
    _genDirectCallWithArgs(node.target, args, hasReceiver: true, node: node);
    asm.emitDrop1();
  }

  @override
  visitDirectMethodInvocation(DirectMethodInvocation node) {
    final args = node.arguments;
    _genArguments(node.receiver, args);
    final target = node.target;
    if (target is Procedure && !target.isGetter && !target.isSetter) {
      _genDirectCallWithArgs(target, args, hasReceiver: true, node: node);
    } else {
      throw new UnsupportedOperationError(
          'Unsupported DirectMethodInvocation with target ${target.runtimeType} $target');
    }
  }

  @override
  visitDirectPropertyGet(DirectPropertyGet node) {
    _generateNode(node.receiver);
    final target = node.target;
    if (target is Field || (target is Procedure && target.isGetter)) {
      _genDirectCall(target, objectTable.getArgDescHandle(1), 1,
          isGet: true, node: node);
    } else {
      throw new UnsupportedOperationError(
          'Unsupported DirectPropertyGet with ${target.runtimeType} $target');
    }
  }

  @override
  visitDirectPropertySet(DirectPropertySet node) {
    final int temp = locals.tempIndexInFrame(node);
    final bool hasResult = !isExpressionWithoutResult(node);

    _generateNode(node.receiver);
    _generateNode(node.value);

    if (hasResult) {
      asm.emitStoreLocal(temp);
    }

    final target = node.target;
    assert(target is Field || (target is Procedure && target.isSetter));
    _genDirectCall(target, objectTable.getArgDescHandle(2), 2,
        isSet: true, node: node);
    asm.emitDrop1();

    if (hasResult) {
      asm.emitPush(temp);
    }
  }

  @override
  visitFunctionExpression(FunctionExpression node) {
    _genClosure(node, '<anonymous closure>', node.function);
  }

  @override
  visitInstantiation(Instantiation node) {
    final int oldClosure = locals.tempIndexInFrame(node, tempIndex: 0);
    final int newClosure = locals.tempIndexInFrame(node, tempIndex: 1);
    final int typeArguments = locals.tempIndexInFrame(node, tempIndex: 2);

    _generateNode(node.expression);
    asm.emitStoreLocal(oldClosure);

    _genTypeArguments(node.typeArguments);
    asm.emitStoreLocal(typeArguments);

    _genDirectCall(
        boundsCheckForPartialInstantiation, objectTable.getArgDescHandle(2), 2);
    asm.emitDrop1();

    assert(closureClass.typeParameters.isEmpty);
    asm.emitAllocate(cp.addClass(closureClass));
    asm.emitStoreLocal(newClosure);

    asm.emitPush(typeArguments);
    asm.emitStoreFieldTOS(cp.addInstanceField(closureDelayedTypeArguments));

    // Copy the rest of the fields from old closure to a new closure.
    final fieldsToCopy = <Field>[
      closureInstantiatorTypeArguments,
      closureFunctionTypeArguments,
      closureFunction,
      closureContext,
    ];

    for (Field field in fieldsToCopy) {
      final fieldOffsetCpIndex = cp.addInstanceField(field);
      asm.emitPush(newClosure);
      asm.emitPush(oldClosure);
      asm.emitLoadFieldTOS(fieldOffsetCpIndex);
      asm.emitStoreFieldTOS(fieldOffsetCpIndex);
    }

    asm.emitPush(newClosure);
  }

  @override
  visitIsExpression(IsExpression node) {
    _generateNode(node.operand);
    _genInstanceOf(node.type);
  }

  @override
  visitLet(Let node) {
    _enterScope(node);
    _generateNode(node.variable);
    _generateNode(node.body);
    _leaveScope();
  }

  @override
  visitListLiteral(ListLiteral node) {
    if (node.isConst) {
      _genPushConstExpr(node);
      return;
    }

    _genTypeArguments([node.typeArgument]);

    if (node.expressions.isEmpty) {
      asm.emitPushConstant(
          cp.addObjectRef(new ListConstant(const DynamicType(), const [])));
    } else {
      _genDupTOS(locals.tempIndexInFrame(node));
      _genPushInt(node.expressions.length);
      asm.emitCreateArrayTOS();
      final int temp = locals.tempIndexInFrame(node);
      asm.emitStoreLocal(temp);

      for (int i = 0; i < node.expressions.length; i++) {
        asm.emitPush(temp);
        _genPushInt(i);
        _generateNode(node.expressions[i]);
        asm.emitStoreIndexedTOS();
      }
    }

    // List._fromLiteral is a factory constructor.
    // Type arguments passed to a factory constructor are counted as a normal
    // argument and not counted in number of type arguments.
    assert(listFromLiteral.isFactory);
    _genDirectCall(listFromLiteral, objectTable.getArgDescHandle(2), 2);
  }

  @override
  visitLogicalExpression(LogicalExpression node) {
    final Label shortCircuit = new Label();
    final Label done = new Label();
    final int temp = locals.tempIndexInFrame(node);
    final isOR = (node.operatorEnum == LogicalExpressionOperator.OR);

    _genConditionAndJumpIf(node.left, isOR, shortCircuit);

    bool negated = _genCondition(node.right);
    if (negated) {
      asm.emitBooleanNegateTOS();
    }
    asm.emitPopLocal(temp);
    asm.emitJump(done);

    asm.bind(shortCircuit);
    _genPushBool(isOR);
    asm.emitPopLocal(temp);

    asm.bind(done);
    asm.emitPush(temp);
  }

  @override
  visitMapLiteral(MapLiteral node) {
    if (node.isConst) {
      _genPushConstExpr(node);
      return;
    }

    _genTypeArguments([node.keyType, node.valueType]);

    if (node.entries.isEmpty) {
      asm.emitPushConstant(
          cp.addObjectRef(new ListConstant(const DynamicType(), const [])));
    } else {
      _genTypeArguments([const DynamicType()]);
      _genPushInt(node.entries.length * 2);
      asm.emitCreateArrayTOS();

      final int temp = locals.tempIndexInFrame(node);
      asm.emitStoreLocal(temp);

      for (int i = 0; i < node.entries.length; i++) {
        // key
        asm.emitPush(temp);
        _genPushInt(i * 2);
        _generateNode(node.entries[i].key);
        asm.emitStoreIndexedTOS();
        // value
        asm.emitPush(temp);
        _genPushInt(i * 2 + 1);
        _generateNode(node.entries[i].value);
        asm.emitStoreIndexedTOS();
      }
    }

    // Map._fromLiteral is a factory constructor.
    // Type arguments passed to a factory constructor are counted as a normal
    // argument and not counted in number of type arguments.
    assert(mapFromLiteral.isFactory);
    _genDirectCall(mapFromLiteral, objectTable.getArgDescHandle(2), 2);
  }

  void _genMethodInvocationUsingSpecializedBytecode(
      Opcode opcode, MethodInvocation node) {
    switch (opcode) {
      case Opcode.kEqualsNull:
        if (node.receiver is NullLiteral) {
          _generateNode(node.arguments.positional.single);
        } else {
          _generateNode(node.receiver);
        }
        break;

      case Opcode.kNegateInt:
      case Opcode.kNegateDouble:
        _generateNode(node.receiver);
        break;

      case Opcode.kAddInt:
      case Opcode.kSubInt:
      case Opcode.kMulInt:
      case Opcode.kTruncDivInt:
      case Opcode.kModInt:
      case Opcode.kBitAndInt:
      case Opcode.kBitOrInt:
      case Opcode.kBitXorInt:
      case Opcode.kShlInt:
      case Opcode.kShrInt:
      case Opcode.kCompareIntEq:
      case Opcode.kCompareIntGt:
      case Opcode.kCompareIntLt:
      case Opcode.kCompareIntGe:
      case Opcode.kCompareIntLe:
      case Opcode.kAddDouble:
      case Opcode.kSubDouble:
      case Opcode.kMulDouble:
      case Opcode.kDivDouble:
      case Opcode.kCompareDoubleEq:
      case Opcode.kCompareDoubleGt:
      case Opcode.kCompareDoubleLt:
      case Opcode.kCompareDoubleGe:
      case Opcode.kCompareDoubleLe:
        _generateNode(node.receiver);
        _generateNode(node.arguments.positional.single);
        break;

      default:
        throw 'Unexpected specialized bytecode $opcode';
    }

    asm.emitSpecializedBytecode(opcode);
  }

  bool _isUncheckedCall(
          Node node, Member interfaceTarget, Expression receiver) =>
      isUncheckedCall(interfaceTarget, receiver, staticTypeContext) ||
      (inferredTypeMetadata != null &&
          inferredTypeMetadata[node]?.skipCheck == true);

  void _genInstanceCall(
      Node node,
      InvocationKind invocationKind,
      Member interfaceTarget,
      Name targetName,
      Expression receiver,
      int totalArgCount,
      ObjectHandle argDesc) {
    final isDynamic = interfaceTarget == null;
    final isUnchecked = invocationKind != InvocationKind.getter &&
        _isUncheckedCall(node, interfaceTarget, receiver);

    if (inferredTypeMetadata != null && node != null) {
      _appendInferredType(node, asm.offset);
    }

    bool generated = false;
    if (invocationKind != InvocationKind.getter && !isDynamic && !isUnchecked) {
      final staticReceiverType = getStaticType(receiver, staticTypeContext);
      if (isInstantiatedInterfaceCall(interfaceTarget, staticReceiverType)) {
        final callCpIndex = cp.addInstantiatedInterfaceCall(
            invocationKind, interfaceTarget, argDesc, staticReceiverType);
        asm.emitInstantiatedInterfaceCall(callCpIndex, totalArgCount);
        generated = true;
      }
    }

    if (!generated) {
      final callCpIndex = cp.addInstanceCall(
          invocationKind, interfaceTarget, targetName, argDesc);
      if (isDynamic) {
        assert(!isUnchecked);
        asm.emitDynamicCall(callCpIndex, totalArgCount);
      } else if (isUnchecked) {
        asm.emitUncheckedInterfaceCall(callCpIndex, totalArgCount);
      } else {
        asm.emitInterfaceCall(callCpIndex, totalArgCount);
      }
    }

    if (inferredTypeMetadata != null && node != null) {
      _replaceWithConstantValue(node);
    }
  }

  @override
  visitMethodInvocation(MethodInvocation node) {
    final directCall =
        directCallMetadata != null ? directCallMetadata[node] : null;
    final Opcode opcode = recognizedMethods.specializedBytecodeFor(node);
    if (opcode != null && directCall == null) {
      _genMethodInvocationUsingSpecializedBytecode(opcode, node);
      return;
    }
    final args = node.arguments;
    final totalArgCount = args.positional.length +
        args.named.length +
        1 /* receiver */ +
        (args.types.isNotEmpty ? 1 : 0) /* type arguments */;
    if (totalArgCount >= argumentsLimit) {
      throw new TooManyArgumentsException(node.fileOffset);
    }
    // Front-end guarantees that all calls with known function type
    // do not need any argument type checks.
    if (isUncheckedClosureCall(node, staticTypeContext, options)) {
      final int receiverTemp = locals.tempIndexInFrame(node);
      _genArguments(node.receiver, args, storeReceiverToLocal: receiverTemp);
      // Duplicate receiver (closure) for UncheckedClosureCall.
      asm.emitPush(receiverTemp);
      final argDescCpIndex = cp.addArgDescByArguments(args, hasReceiver: true);
      asm.emitUncheckedClosureCall(argDescCpIndex, totalArgCount);
      return;
    }

    final Member interfaceTarget = node.interfaceTarget;
    if (!(interfaceTarget == null ||
        interfaceTarget is Procedure && !interfaceTarget.isGetter)) {
      throw new UnsupportedOperationError(
          'Unsupported MethodInvocation with interface target ${interfaceTarget.runtimeType} $interfaceTarget');
    }

    if (directCall != null && directCall.checkReceiverForNull) {
      final int receiverTemp = locals.tempIndexInFrame(node);
      _genArguments(node.receiver, args, storeReceiverToLocal: receiverTemp);
      asm.emitPush(receiverTemp);
      asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.method));
    } else {
      _genArguments(node.receiver, args);
    }

    final argDesc =
        objectTable.getArgDescHandleByArguments(args, hasReceiver: true);

    if (directCall != null) {
      final isDynamicForwarder = (interfaceTarget == null);
      final isUnchecked =
          _isUncheckedCall(node, interfaceTarget, node.receiver);
      _genDirectCall(directCall.target, argDesc, totalArgCount,
          isDynamicForwarder: isDynamicForwarder,
          isUnchecked: isUnchecked,
          node: node);
    } else {
      _genInstanceCall(node, InvocationKind.method, interfaceTarget, node.name,
          node.receiver, totalArgCount, argDesc);
    }
  }

  @override
  visitPropertyGet(PropertyGet node) {
    _generateNode(node.receiver);
    final argDesc = objectTable.getArgDescHandle(1);

    final directCall =
        directCallMetadata != null ? directCallMetadata[node] : null;
    if (directCall != null) {
      if (directCall.checkReceiverForNull) {
        final int receiverTemp = locals.tempIndexInFrame(node);
        asm.emitStoreLocal(receiverTemp);
        asm.emitPush(receiverTemp);
        asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.getter));
      }
      _genDirectCall(directCall.target, argDesc, 1, isGet: true, node: node);
    } else {
      _genInstanceCall(node, InvocationKind.getter, node.interfaceTarget,
          node.name, node.receiver, 1, argDesc);
    }
  }

  @override
  visitPropertySet(PropertySet node) {
    final int temp = locals.tempIndexInFrame(node);
    final bool hasResult = !isExpressionWithoutResult(node);

    _generateNode(node.receiver);

    final directCall =
        directCallMetadata != null ? directCallMetadata[node] : null;
    if (directCall != null && directCall.checkReceiverForNull) {
      asm.emitStoreLocal(temp);
      _generateNode(node.value);
      asm.emitPush(temp);
      asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.setter));
    } else {
      _generateNode(node.value);
    }

    if (hasResult) {
      asm.emitStoreLocal(temp);
    }

    const int numArguments = 2;
    final argDesc = objectTable.getArgDescHandle(numArguments);

    if (directCall != null) {
      final isDynamicForwarder = (node.interfaceTarget == null);
      final isUnchecked =
          _isUncheckedCall(node, node.interfaceTarget, node.receiver);
      _genDirectCall(directCall.target, argDesc, numArguments,
          isSet: true,
          isDynamicForwarder: isDynamicForwarder,
          isUnchecked: isUnchecked,
          node: node);
    } else {
      _genInstanceCall(node, InvocationKind.setter, node.interfaceTarget,
          node.name, node.receiver, numArguments, argDesc);
    }

    asm.emitDrop1();

    if (hasResult) {
      asm.emitPush(temp);
    }
  }

  @override
  visitSuperMethodInvocation(SuperMethodInvocation node) {
    final args = node.arguments;
    final Member target =
        hierarchy.getDispatchTarget(enclosingClass.superclass, node.name);
    if (target == null) {
      final int temp = locals.tempIndexInFrame(node);
      _genNoSuchMethodForSuperCall(
          node.name.text,
          temp,
          cp.addArgDescByArguments(args, hasReceiver: true),
          args.types,
          <Expression>[new ThisExpression()]
            ..addAll(args.positional)
            ..addAll(args.named.map((x) => x.value)));
      return;
    }
    if (!(target is Procedure && !target.isGetter)) {
      throw new UnsupportedOperationError(
          'Unsupported SuperMethodInvocation with target ${target.runtimeType} $target');
    }
    _genArguments(new ThisExpression(), args);
    _genDirectCallWithArgs(target, args,
        hasReceiver: true, isUnchecked: true, node: node);
  }

  @override
  visitSuperPropertyGet(SuperPropertyGet node) {
    final Member target =
        hierarchy.getDispatchTarget(enclosingClass.superclass, node.name);
    if (target == null) {
      final int temp = locals.tempIndexInFrame(node);
      _genNoSuchMethodForSuperCall(node.name.text, temp, cp.addArgDesc(1), [],
          <Expression>[new ThisExpression()]);
      return;
    }
    _genPushReceiver();
    _genDirectCall(target, objectTable.getArgDescHandle(1), 1,
        isGet: true, node: node);
  }

  @override
  visitSuperPropertySet(SuperPropertySet node) {
    final int temp = locals.tempIndexInFrame(node);
    final bool hasResult = !isExpressionWithoutResult(node);

    final Member target = hierarchy
        .getDispatchTarget(enclosingClass.superclass, node.name, setter: true);
    if (target == null) {
      _genNoSuchMethodForSuperCall(node.name.text, temp, cp.addArgDesc(2), [],
          <Expression>[new ThisExpression(), node.value],
          storeLastArgumentToTemp: hasResult);
    } else {
      _genPushReceiver();
      _generateNode(node.value);

      if (hasResult) {
        asm.emitStoreLocal(temp);
      }

      assert(target is Field || (target is Procedure && target.isSetter));
      _genDirectCall(target, objectTable.getArgDescHandle(2), 2,
          isSet: true, isUnchecked: true, node: node);
    }

    asm.emitDrop1();

    if (hasResult) {
      asm.emitPush(temp);
    }
  }

  @override
  visitNot(Not node) {
    bool negated = _genCondition(node.operand);
    if (!negated) {
      asm.emitBooleanNegateTOS();
    }
  }

  @override
  visitNullCheck(NullCheck node) {
    _generateNode(node.operand);
    final operandTemp = locals.tempIndexInFrame(node);
    asm.emitStoreLocal(operandTemp);
    asm.emitPush(operandTemp);
    asm.emitNullCheck(cp.addObjectRef(null));
  }

  @override
  visitNullLiteral(NullLiteral node) {
    asm.emitPushNull();
  }

  @override
  visitRethrow(Rethrow node) {
    TryCatch tryCatch;
    for (var parent = node.parent;; parent = parent.parent) {
      if (parent is Catch) {
        tryCatch = parent.parent as TryCatch;
        break;
      }
      if (parent == null || parent is FunctionNode) {
        throw 'Unable to find enclosing catch for $node';
      }
    }
    tryCatches[tryCatch].needsStackTrace = true;

    if (options.emitDebuggerStops) {
      asm.emitDebugCheck(); // Allow breakpoint on explicit rethrow statement.
    }
    _genRethrow(tryCatch);
  }

  bool _hasNonTrivialInitializer(Field field) {
    if (field.initializer == null) return false;
    return !_isTrivialInitializer(field.initializer);
  }

  bool _isTrivialInitializer(Expression initializer) {
    if (initializer == null) return false;
    if (initializer is StringLiteral ||
        initializer is BoolLiteral ||
        initializer is IntLiteral ||
        initializer is DoubleLiteral ||
        initializer is NullLiteral) {
      return true;
    }
    if (initializer is ConstantExpression &&
        initializer.constant is PrimitiveConstant) {
      return true;
    }
    return false;
  }

  @override
  visitStaticGet(StaticGet node) {
    final target = node.target;
    if (target is Field) {
      if (target.isConst) {
        _genPushConstExpr(target.initializer);
      } else if (!_needsGetter(target)) {
        if (inferredTypeMetadata != null) {
          final InferredType md = inferredTypeMetadata[node];
          if (md != null && md.constantValue != null) {
            _genPushConstant(md.constantValue);
            return;
          }
        }
        asm.emitLoadStatic(cp.addStaticField(target));
      } else {
        _genDirectCall(target, objectTable.getArgDescHandle(0), 0,
            isGet: true, node: node);
      }
    } else if (target is Procedure) {
      if (target.isGetter) {
        _genDirectCall(target, objectTable.getArgDescHandle(0), 0,
            isGet: true, node: node);
      } else if (target.isFactory || target.isRedirectingFactoryConstructor) {
        throw 'Unexpected target for StaticGet: factory $target';
      } else {
        asm.emitPushConstant(cp.addObjectRef(new TearOffConstant(target)));
      }
    } else {
      throw 'Unexpected target for StaticGet: ${target.runtimeType} $target';
    }
  }

  @override
  visitStaticInvocation(StaticInvocation node) {
    if (node.isConst) {
      _genPushConstExpr(node);
      return;
    }
    Arguments args = node.arguments;
    final target = node.target;
    if (target == unsafeCast) {
      // The result of the unsafeCast() intrinsic method is its sole argument,
      // without any additional checks or type casts.
      assert(args.named.isEmpty);
      _generateNode(args.positional.single);
      return;
    }
    if (!options.causalAsyncStacks &&
        target == coreTypes.asyncStackTraceHelperProcedure) {
      // Eliminate calls to _asyncStackTraceHelper as causal async stacks are
      // disabled. These calls are inserted by async transformation
      // (pkg/kernel/lib/transformations/continuation.dart), but they should be
      // consistent with _setAsyncThreadStackTrace and
      // _clearAsyncThreadStackTrace calls generated by bytecode generator.
      //
      // Push null as _asyncStackTraceHelper call should leave result
      // on the stack.
      asm.emitPushNull();
      return;
    }
    if (target.isFactory) {
      final constructedClass = target.enclosingClass;
      if (hasInstantiatorTypeArguments(constructedClass)) {
        _genTypeArguments(args.types, instantiatingClass: constructedClass);
      } else {
        assert(args.types.isEmpty);
        // VM needs type arguments for every invocation of a factory
        // constructor. TODO(alexmarkov): Clean this up.
        asm.emitPushNull();
      }
      args =
          new Arguments(node.arguments.positional, named: node.arguments.named)
            ..parent = node;
    }
    _genArguments(null, args);
    _genDirectCallWithArgs(target, args,
        isFactory: target.isFactory, node: node);
  }

  @override
  visitStaticSet(StaticSet node) {
    final bool hasResult = !isExpressionWithoutResult(node);

    _generateNode(node.value);

    if (hasResult) {
      _genDupTOS(locals.tempIndexInFrame(node));
    }

    final target = node.target;
    if (target is Field && !_needsSetter(target)) {
      if (options.emitDebuggerStops &&
          _variableSetNeedsDebugCheck(node.value)) {
        asm.emitDebugCheck();
      }
      int cpIndex = cp.addStaticField(target);
      asm.emitStoreStaticTOS(cpIndex);
    } else {
      _genDirectCall(target, objectTable.getArgDescHandle(1), 1,
          isSet: true, node: node);
      asm.emitDrop1();
    }
  }

  @override
  visitStringConcatenation(StringConcatenation node) {
    if (node.expressions.length == 1) {
      _generateNode(node.expressions.single);
      _genDirectCall(interpolateSingle, objectTable.getArgDescHandle(1), 1);
    } else {
      asm.emitPushNull();
      _genPushInt(node.expressions.length);
      asm.emitCreateArrayTOS();

      final int temp = locals.tempIndexInFrame(node);
      asm.emitStoreLocal(temp);

      for (int i = 0; i < node.expressions.length; i++) {
        asm.emitPush(temp);
        _genPushInt(i);
        _generateNode(node.expressions[i]);
        asm.emitStoreIndexedTOS();
      }

      _genDirectCall(interpolate, objectTable.getArgDescHandle(1), 1);
    }
  }

  @override
  visitStringLiteral(StringLiteral node) {
    final cpIndex = cp.addString(node.value);
    asm.emitPushConstant(cpIndex);
  }

  @override
  visitSymbolLiteral(SymbolLiteral node) {
    _genPushConstExpr(node);
  }

  @override
  visitThisExpression(ThisExpression node) {
    _genPushReceiver();
  }

  @override
  visitThrow(Throw node) {
    _generateNode(node.expression);

    if (options.emitDebuggerStops) {
      asm.emitDebugCheck();
    }
    asm.emitThrow(0);
  }

  @override
  visitTypeLiteral(TypeLiteral node) {
    final DartType type = node.type;
    final int typeCPIndex = cp.addType(type);
    if (!hasFreeTypeParameters([type])) {
      asm.emitPushConstant(typeCPIndex);
    } else {
      _genPushInstantiatorAndFunctionTypeArguments([type]);
      asm.emitInstantiateType(typeCPIndex);
    }
  }

  @override
  visitVariableGet(VariableGet node) {
    final v = node.variable;
    if (v.isConst) {
      _genPushConstExpr(v.initializer);
    } else if (v.isLate) {
      _genLoadVar(v);

      final Label done = new Label();
      asm.emitJumpIfInitialized(done);

      if (v.initializer != null) {
        final init = v.initializer;
        _genPushContextIfCaptured(v);
        // Late local variable initializers are transformed to wrap the
        // initializer in a closure (see late_var_init_transformer.dart). The
        // closure call needs one temporary, so withTemp lets us use this
        // VariableGet's temporary when visiting the initializer.
        assert(init is MethodInvocation &&
            init.name.text == "call" &&
            init.arguments.positional.length == 0);
        locals.withTemp(
            init, locals.tempIndexInFrame(node), () => _generateNode(init));
        _genStoreVar(v);
      } else {
        asm.emitPushConstant(cp.addName(v.name));
        _genDirectCall(throwNewLateInitializationError,
            objectTable.getArgDescHandle(1), 1);
        asm.emitDrop1();
      }

      asm.bind(done);
      _genLoadVar(v);
    } else {
      _genLoadVar(v);
    }
  }

  @override
  visitVariableSet(VariableSet node) {
    final v = node.variable;
    final bool hasResult = !isExpressionWithoutResult(node);
    final bool isLateFinal = v.isLate && v.isFinal;

    if (!isLateFinal) {
      _genPushContextIfCaptured(v);
    }

    _generateNode(node.value);

    if (options.emitDebuggerStops && _variableSetNeedsDebugCheck(node.value)) {
      asm.emitDebugCheck();
    }

    if (isLateFinal) {
      final int temp = locals.tempIndexInFrame(node);
      asm.emitPopLocal(temp);

      final Label error = new Label();
      final Label done = new Label();
      _genLoadVar(v);
      asm.emitJumpIfInitialized(error);

      _genPushContextIfCaptured(v);
      asm.emitPush(temp);
      _genStoreVar(v);
      asm.emitJump(done);

      asm.bind(error);
      asm.emitPushConstant(cp.addName(v.name));
      _genDirectCall(
          throwNewLateInitializationError, objectTable.getArgDescHandle(1), 1);
      asm.emitDrop1();

      asm.bind(done);

      if (hasResult) {
        asm.emitPush(temp);
      }
    } else if (locals.isCaptured(v)) {
      final int temp = locals.tempIndexInFrame(node);
      if (hasResult) {
        asm.emitStoreLocal(temp);
      }

      _genStoreVar(v);

      if (hasResult) {
        asm.emitPush(temp);
      }
    } else {
      final int localIndex = locals.getVarIndexInFrame(v);
      if (hasResult) {
        asm.emitStoreLocal(localIndex);
      } else {
        asm.emitPopLocal(localIndex);
      }
    }
  }

  bool _variableSetNeedsDebugCheck(Expression rhs) =>
      rhs is BasicLiteral ||
      rhs is ConstantExpression ||
      rhs is StaticGet ||
      rhs is FunctionExpression ||
      rhs is VariableGet ||
      rhs is AsExpression;

  void _genFutureNull() {
    asm.emitPushNull();
    _genDirectCall(futureValue, objectTable.getArgDescHandle(1), 1);
  }

  @override
  visitLoadLibrary(LoadLibrary node) {
    _genFutureNull();
  }

  @override
  visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
    _genFutureNull();
  }

  @override
  visitAssertStatement(AssertStatement node) {
    if (!options.enableAsserts) {
      return;
    }

    final Label done = new Label();
    asm.emitJumpIfNoAsserts(done);

    _genConditionAndJumpIf(node.condition, true, done);

    _genPushInt(
        options.omitAssertSourcePositions ? 0 : node.conditionStartOffset);
    _genPushInt(
        options.omitAssertSourcePositions ? 0 : node.conditionEndOffset);

    if (node.message != null) {
      _generateNode(node.message);
    } else {
      asm.emitPushNull();
    }

    _genDirectCall(throwNewAssertionError, objectTable.getArgDescHandle(3), 3);
    asm.emitDrop1();

    asm.bind(done);
  }

  @override
  visitBlock(Block node) {
    _enterScope(node);
    _generateNodeList(node.statements);
    _leaveScope();
  }

  @override
  visitAssertBlock(AssertBlock node) {
    if (!options.enableAsserts) {
      return;
    }

    final Label done = new Label();
    asm.emitJumpIfNoAsserts(done);

    _enterScope(node);
    _generateNodeList(node.statements);
    _leaveScope();

    asm.bind(done);
  }

  @override
  visitBlockExpression(BlockExpression node) {
    _enterScope(node);
    _generateNodeList(node.body.statements);
    _generateNode(node.value);
    _leaveScope();
  }

  @override
  visitBreakStatement(BreakStatement node) {
    final targetLabel = labeledStatements[node.target] ??
        (throw 'Target label ${node.target} was not registered for break $node');
    final targetContextLevel = contextLevels[node.target];

    _generateNonLocalControlTransfer(node, node.target, () {
      _genUnwindContext(targetContextLevel);
      asm.emitJump(targetLabel);
    });
  }

  @override
  visitContinueSwitchStatement(ContinueSwitchStatement node) {
    final targetLabel = switchCases[node.target] ??
        (throw 'Target label ${node.target} was not registered for continue-switch $node');
    final targetContextLevel = contextLevels[node.target.parent];

    _generateNonLocalControlTransfer(node, node.target.parent, () {
      _genUnwindContext(targetContextLevel);
      asm.emitJump(targetLabel);
    });
  }

  @override
  visitDoStatement(DoStatement node) {
    if (asm.isUnreachable) {
      // Bail out before binding a label which allows backward jumps,
      // as it is not handled by local unreachable code elimination.
      return;
    }

    final Label join = new Label(allowsBackwardJumps: true);
    asm.bind(join);

    asm.emitCheckStack(++currentLoopDepth);

    _generateNode(node.body);

    _genConditionAndJumpIf(node.condition, true, join);

    --currentLoopDepth;
  }

  @override
  visitEmptyStatement(EmptyStatement node) {
    // no-op
  }

  @override
  visitExpressionStatement(ExpressionStatement node) {
    final expr = node.expression;
    _generateNode(expr);
    if (!isExpressionWithoutResult(expr)) {
      asm.emitDrop1();
    }
  }

  @override
  visitForInStatement(ForInStatement node) {
    // Should be lowered by the async transformation.
    throw "unreachable";
  }

  @override
  visitForStatement(ForStatement node) {
    _enterScope(node);
    try {
      _generateNodeList(node.variables);

      if (asm.isUnreachable) {
        // Bail out before binding a label which allows backward jumps,
        // as it is not handled by local unreachable code elimination.
        return;
      }

      final Label done = new Label();
      final Label join = new Label(allowsBackwardJumps: true);
      asm.bind(join);

      asm.emitCheckStack(++currentLoopDepth);

      if (node.condition != null) {
        _genConditionAndJumpIf(node.condition, false, done);
      }

      _generateNode(node.body);

      if (locals.currentContextSize > 0) {
        asm.emitPush(locals.contextVarIndexInFrame);
        asm.emitCloneContext(
            locals.currentContextId, locals.currentContextSize);
        asm.emitPopLocal(locals.contextVarIndexInFrame);
      }

      for (var update in node.updates) {
        _generateNode(update);
        asm.emitDrop1();
      }

      asm.emitJump(join);

      asm.bind(done);
      --currentLoopDepth;
    } finally {
      _leaveScope();
    }
  }

  @override
  visitFunctionDeclaration(ast.FunctionDeclaration node) {
    if (options.emitDebuggerStops) {
      asm.emitDebugCheck();
    }
    _genPushContextIfCaptured(node.variable);
    _genClosure(node, node.variable.name, node.function);
    _genStoreVar(node.variable);
  }

  @override
  visitIfStatement(IfStatement node) {
    final Label otherwisePart = new Label();

    _genConditionAndJumpIf(node.condition, false, otherwisePart);

    _generateNode(node.then);

    if (node.otherwise != null) {
      final Label done = new Label();
      asm.emitJump(done);
      asm.bind(otherwisePart);
      _generateNode(node.otherwise);
      asm.bind(done);
    } else {
      asm.bind(otherwisePart);
    }
  }

  @override
  visitLabeledStatement(LabeledStatement node) {
    final label = new Label();
    labeledStatements ??= new Map<LabeledStatement, Label>();
    labeledStatements[node] = label;
    contextLevels ??= new Map<TreeNode, int>();
    contextLevels[node] = locals.currentContextLevel;
    _generateNode(node.body);
    asm.bind(label);
    labeledStatements.remove(node);
    contextLevels.remove(node);
  }

  @override
  visitReturnStatement(ReturnStatement node) {
    final expr = node.expression ?? new NullLiteral();

    final List<TryFinally> tryFinallyBlocks =
        _getEnclosingTryFinallyBlocks(node, null);
    if (tryFinallyBlocks.isEmpty) {
      _generateNode(expr);
      _genReturnTOS();
    } else {
      if (options.emitDebuggerStops) {
        // Stop on the return statement before executing finally blocks.
        asm.emitDebugCheck();
      }
      if (expr is BasicLiteral) {
        _addFinallyBlocks(tryFinallyBlocks, () {
          _generateNode(expr);
          _genReturnTOS();
        });
      } else {
        // Keep return value in a variable as try-catch statements
        // inside finally can zap expression stack.
        _generateNode(node.expression);
        asm.emitPopLocal(locals.returnVarIndexInFrame);

        _addFinallyBlocks(tryFinallyBlocks, () {
          asm.emitPush(locals.returnVarIndexInFrame);
          _genReturnTOS();
        });
      }
    }
  }

  @override
  visitSwitchStatement(SwitchStatement node) {
    contextLevels ??= new Map<TreeNode, int>();
    contextLevels[node] = locals.currentContextLevel;

    _generateNode(node.expression);

    if (asm.isUnreachable) {
      // Bail out before binding labels which allow backward jumps,
      // as they are not handled by local unreachable code elimination.
      return;
    }

    final int temp = locals.tempIndexInFrame(node);
    asm.emitPopLocal(temp);

    final Label done = new Label();
    final List<Label> caseLabels = new List<Label>.generate(
        node.cases.length, (_) => new Label(allowsBackwardJumps: true));
    final equalsArgDesc = objectTable.getArgDescHandle(2);

    switchCases ??= new Map<SwitchCase, Label>();

    Label defaultLabel = done;
    for (int i = 0; i < node.cases.length; i++) {
      final SwitchCase switchCase = node.cases[i];
      final Label caseLabel = caseLabels[i];
      switchCases[switchCase] = caseLabel;

      if (switchCase.isDefault) {
        defaultLabel = caseLabel;
      } else {
        final savedSourcePosition = asm.currentSourcePosition;
        for (int i = 0; i < switchCase.expressions.length; ++i) {
          _recordSourcePosition(switchCase.expressionOffsets[i]);
          _genPushConstExpr(switchCase.expressions[i]);
          asm.emitPush(temp);
          asm.emitInterfaceCall(
              cp.addInterfaceCall(
                  InvocationKind.method, coreTypes.objectEquals, equalsArgDesc),
              2);
          asm.emitJumpIfTrue(caseLabel);
        }
        asm.currentSourcePosition = savedSourcePosition;
      }
    }

    asm.emitJump(defaultLabel);

    for (int i = 0; i < node.cases.length; i++) {
      final SwitchCase switchCase = node.cases[i];
      final Label caseLabel = caseLabels[i];

      asm.bind(caseLabel);
      _generateNode(switchCase.body);

      // Front-end issues a compile-time error if there is a fallthrough
      // between cases. Also, default case should be the last one.
    }

    asm.bind(done);
    node.cases.forEach(switchCases.remove);
    contextLevels.remove(node);
  }

  bool _isTryBlock(TreeNode node) => node is TryCatch || node is TryFinally;

  int _savedContextVar(TreeNode node) {
    assert(_isTryBlock(node));
    assert(locals.capturedSavedContextVar(node) == null);
    return locals.tempIndexInFrame(node, tempIndex: 0);
  }

  // Exception var occupies the same slot as saved context, so context
  // should be restored first, before loading exception.
  int _exceptionVar(TreeNode node) {
    assert(_isTryBlock(node));
    return locals.tempIndexInFrame(node, tempIndex: 0);
  }

  int _stackTraceVar(TreeNode node) {
    assert(_isTryBlock(node));
    return locals.tempIndexInFrame(node, tempIndex: 1);
  }

  _saveContextForTryBlock(TreeNode node) {
    if (!locals.hasContextVar) {
      return;
    }
    final capturedSavedContextVar = locals.capturedSavedContextVar(node);
    if (capturedSavedContextVar != null) {
      assert(locals.isSyncYieldingFrame);
      _genPushContextForVariable(capturedSavedContextVar);
      asm.emitPush(locals.contextVarIndexInFrame);
      _genStoreVar(capturedSavedContextVar);
    } else {
      asm.emitPush(locals.contextVarIndexInFrame);
      asm.emitPopLocal(_savedContextVar(node));
    }
  }

  _restoreContextForTryBlock(TreeNode node) {
    if (!locals.hasContextVar) {
      return;
    }
    final capturedSavedContextVar = locals.capturedSavedContextVar(node);
    if (capturedSavedContextVar != null) {
      // 1. Restore context from closure var.
      // This context has a context level at frame entry.
      asm.emitPush(locals.closureVarIndexInFrame);
      asm.emitLoadFieldTOS(cp.addInstanceField(closureContext));
      asm.emitPopLocal(locals.contextVarIndexInFrame);

      // 2. Restore context from captured :saved_try_context_var${depth}.
      assert(locals.isCaptured(capturedSavedContextVar));
      _genLoadVar(capturedSavedContextVar,
          currentContextLevel: locals.contextLevelAtEntry);
    } else {
      asm.emitPush(_savedContextVar(node));
    }
    asm.emitPopLocal(locals.contextVarIndexInFrame);
  }

  /// Start try block
  TryBlock _startTryBlock(TreeNode node) {
    assert(_isTryBlock(node));

    _saveContextForTryBlock(node);

    return asm.exceptionsTable.enterTryBlock(asm.offset);
  }

  /// End try block and start its handler.
  void _endTryBlock(TreeNode node, TryBlock tryBlock) {
    tryBlock.endPC = asm.offset;
    tryBlock.handlerPC = asm.offset;

    // Exception handlers are reachable although there are no labels or jumps.
    asm.isUnreachable = false;

    asm.emitSetFrame(locals.frameSize);

    _restoreContextForTryBlock(node);

    asm.emitMoveSpecial(SpecialIndex.exception, _exceptionVar(node));
    asm.emitMoveSpecial(SpecialIndex.stackTrace, _stackTraceVar(node));

    final capturedExceptionVar = locals.capturedExceptionVar(node);
    if (capturedExceptionVar != null) {
      _genPushContextForVariable(capturedExceptionVar);
      asm.emitPush(_exceptionVar(node));
      _genStoreVar(capturedExceptionVar);
    }

    final capturedStackTraceVar = locals.capturedStackTraceVar(node);
    if (capturedStackTraceVar != null) {
      _genPushContextForVariable(capturedStackTraceVar);
      asm.emitPush(_stackTraceVar(node));
      _genStoreVar(capturedStackTraceVar);
    }
  }

  void _genRethrow(TreeNode node) {
    final capturedExceptionVar = locals.capturedExceptionVar(node);
    if (capturedExceptionVar != null) {
      assert(locals.isCaptured(capturedExceptionVar));
      _genLoadVar(capturedExceptionVar);
    } else {
      asm.emitPush(_exceptionVar(node));
    }

    final capturedStackTraceVar = locals.capturedStackTraceVar(node);
    if (capturedStackTraceVar != null) {
      assert(locals.isCaptured(capturedStackTraceVar));
      _genLoadVar(capturedStackTraceVar);
    } else {
      asm.emitPush(_stackTraceVar(node));
    }

    asm.emitThrow(1);
  }

  @override
  visitTryCatch(TryCatch node) {
    if (asm.isUnreachable) {
      return;
    }

    final Label done = new Label();

    final TryBlock tryBlock = _startTryBlock(node);
    tryBlock.isSynthetic = node.isSynthetic;
    tryCatches ??= new Map<TryCatch, TryBlock>();
    tryCatches[node] = tryBlock; // Used by rethrow.

    _generateNode(node.body);
    asm.emitJump(done);

    _endTryBlock(node, tryBlock);

    final int exception = _exceptionVar(node);
    final int stackTrace = _stackTraceVar(node);

    bool hasCatchAll = false;

    final savedSourcePosition = asm.currentSourcePosition;
    for (Catch catchClause in node.catches) {
      _recordSourcePosition(catchClause.fileOffset);
      tryBlock.types.add(cp.addType(catchClause.guard));

      Label skipCatch;
      final guardType = catchClause.guard;
      // Exception objects are guaranteed to be non-nullable, so
      // non-nullable Object is also a catch-all type.
      if (guardType is DynamicType ||
          (guardType is InterfaceType &&
              guardType.classNode == coreTypes.objectClass)) {
        hasCatchAll = true;
      } else {
        asm.emitPush(exception);
        _genInstanceOf(catchClause.guard);

        skipCatch = new Label();
        asm.emitJumpIfFalse(skipCatch);
      }

      _enterScope(catchClause);

      if (catchClause.exception != null) {
        _genPushContextIfCaptured(catchClause.exception);
        asm.emitPush(exception);
        _genStoreVar(catchClause.exception);
      }

      if (catchClause.stackTrace != null) {
        tryBlock.needsStackTrace = true;
        _genPushContextIfCaptured(catchClause.stackTrace);
        asm.emitPush(stackTrace);
        _genStoreVar(catchClause.stackTrace);
      }

      _generateNode(catchClause.body);

      _leaveScope();
      asm.emitJump(done);

      if (skipCatch != null) {
        asm.bind(skipCatch);
      }
    }
    asm.currentSourcePosition = savedSourcePosition;

    if (!hasCatchAll) {
      tryBlock.needsStackTrace = true;
      _genRethrow(node);
    }

    asm.bind(done);
    tryCatches.remove(node);
  }

  @override
  visitTryFinally(TryFinally node) {
    if (asm.isUnreachable) {
      return;
    }

    final TryBlock tryBlock = _startTryBlock(node);
    tryBlock.isSynthetic = true;
    finallyBlocks ??= new Map<TryFinally, List<FinallyBlock>>();
    finallyBlocks[node] = <FinallyBlock>[];

    _generateNode(node.body);

    if (!asm.isUnreachable) {
      final normalContinuation = new FinallyBlock(() {
        /* do nothing (fall through) */
      });
      finallyBlocks[node].add(normalContinuation);
      asm.emitJump(normalContinuation.entry);
    }

    _endTryBlock(node, tryBlock);

    tryBlock.types.add(cp.addType(const DynamicType()));

    _generateNode(node.finalizer);

    tryBlock.needsStackTrace = true; // For rethrowing.
    _genRethrow(node);

    for (var finallyBlock in finallyBlocks[node]) {
      asm.bind(finallyBlock.entry);
      _restoreContextForTryBlock(node);
      _generateNode(node.finalizer);
      finallyBlock.generateContinuation();
    }

    finallyBlocks.remove(node);
  }

  bool _skipVariableInitialization(VariableDeclaration v, bool isCaptured) {
    // We can skip variable initialization if the variable is supposed to be
    // initialized to null and it's captured. This is because all the slots in
    // the capture context are implicitly initialized to null.

    // Check if the variable is supposed to be initialized to null.
    if (!(v.initializer == null || v.initializer is NullLiteral)) {
      return false;
    }

    // Late variables need to be initialized to a sentinel, not null.
    if (v.isLate) return false;

    // Non-captured variables go in stack slots that aren't implicitly nulled.
    return isCaptured;
  }

  @override
  visitVariableDeclaration(VariableDeclaration node) {
    if (!node.isConst) {
      final bool isCaptured = locals.isCaptured(node);
      final initializer = node.initializer;
      final bool emitStore = !_skipVariableInitialization(node, isCaptured);
      int maxInitializerPosition = node.fileOffset;
      if (emitStore) {
        if (isCaptured) {
          _genPushContextForVariable(node);
        }
        if (node.isLate && !_isTrivialInitializer(initializer)) {
          asm.emitPushUninitializedSentinel();
        } else if (initializer != null) {
          _startRecordingMaxPosition(node.fileOffset);
          _generateNode(initializer);
          maxInitializerPosition = _endRecordingMaxPosition();
        } else {
          asm.emitPushNull();
        }
      }

      if (options.emitDebuggerStops &&
          (initializer == null || _variableSetNeedsDebugCheck(initializer))) {
        final savedSourcePosition = asm.currentSourcePosition;
        if (node.fileEqualsOffset != TreeNode.noOffset) {
          _recordSourcePosition(node.fileEqualsOffset);
        }
        asm.emitDebugCheck();
        asm.currentSourcePosition = savedSourcePosition;
      }

      if (options.emitLocalVarInfo && !asm.isUnreachable && node.name != null) {
        _declareLocalVariable(node, maxInitializerPosition + 1);
      }

      if (emitStore) {
        _genStoreVar(node);
      }
    }
  }

  @override
  visitWhileStatement(WhileStatement node) {
    if (asm.isUnreachable) {
      // Bail out before binding a label which allows backward jumps,
      // as it is not handled by local unreachable code elimination.
      return;
    }

    final Label done = new Label();
    final Label join = new Label(allowsBackwardJumps: true);
    asm.bind(join);

    asm.emitCheckStack(++currentLoopDepth);

    _genConditionAndJumpIf(node.condition, false, done);

    _generateNode(node.body);

    asm.emitJump(join);
    --currentLoopDepth;

    asm.bind(done);
  }

  @override
  visitYieldStatement(YieldStatement node) {
    if (!node.isNative) {
      throw 'YieldStatement must be desugared: $node';
    }

    if (asm.isUnreachable) {
      return;
    }

    // 0 is reserved for normal entry, yield points are counted from 1.
    final int yieldIndex = yieldPoints.length + 1;
    final Label continuationLabel = new Label(allowsBackwardJumps: true);
    yieldPoints.add(continuationLabel);

    // :await_jump_var = #index
    assert(locals.isCaptured(locals.awaitJumpVar));
    _genPushContextForVariable(locals.awaitJumpVar);
    _genPushInt(yieldIndex);
    _genStoreVar(locals.awaitJumpVar);

    // :await_ctx_var = context
    assert(locals.isCaptured(locals.awaitContextVar));
    _genPushContextForVariable(locals.awaitContextVar);
    asm.emitPush(locals.contextVarIndexInFrame);
    _genStoreVar(locals.awaitContextVar);

    // return <expression>
    // Note: finally blocks are *not* executed on the way out.
    _generateNode(node.expression);
    _genReturnTOS(node.fileOffset);

    asm.bind(continuationLabel);

    if (parentFunction.dartAsyncMarker == AsyncMarker.Async ||
        parentFunction.dartAsyncMarker == AsyncMarker.AsyncStar) {
      final int exceptionParam = locals.asyncExceptionParamIndexInFrame;
      final int stackTraceParam = locals.asyncStackTraceParamIndexInFrame;

      // if (:exception != null) rethrow (:exception, :stack_trace)
      final Label cont = new Label();
      asm.emitPush(exceptionParam);
      asm.emitJumpIfNull(cont);

      asm.emitPush(exceptionParam);
      asm.emitPush(stackTraceParam);
      asm.emitThrow(1);

      asm.bind(cont);
    }
  }

  @override
  visitFieldInitializer(FieldInitializer node) {
    _genFieldInitializer(node.field, node.value);
  }

  @override
  visitRedirectingInitializer(RedirectingInitializer node) {
    final args = node.arguments;
    assert(args.types.isEmpty);
    _genArguments(new ThisExpression(), args);
    _genDirectCallWithArgs(node.target, args, hasReceiver: true, node: node);
    asm.emitDrop1();
  }

  @override
  visitSuperInitializer(SuperInitializer node) {
    final args = node.arguments;
    assert(args.types.isEmpty);
    _genArguments(new ThisExpression(), args);
    // Re-resolve target due to partial mixin resolution.
    Member target;
    for (var replacement in enclosingClass.superclass.constructors) {
      if (node.target.name == replacement.name) {
        target = replacement;
        break;
      }
    }
    assert(target != null);
    _genDirectCallWithArgs(target, args, hasReceiver: true, node: node);
    asm.emitDrop1();
  }

  @override
  visitLocalInitializer(LocalInitializer node) {
    _generateNode(node.variable);
  }

  @override
  visitAssertInitializer(AssertInitializer node) {
    _generateNode(node.statement);
  }

  @override
  visitConstantExpression(ConstantExpression node) {
    _genPushConstant(node.constant);
  }
}

class UnsupportedOperationError {
  final String message;
  UnsupportedOperationError(this.message);

  @override
  String toString() => message;
}

class TooManyArgumentsException extends BytecodeLimitExceededException {
  final int fileOffset;
  TooManyArgumentsException(this.fileOffset);
}

typedef void GenerateContinuation();

class FinallyBlock {
  final Label entry = new Label();
  final GenerateContinuation generateContinuation;

  FinallyBlock(this.generateContinuation);
}

class Annotations {
  final AnnotationsDeclaration object;
  final bool hasPragma;

  const Annotations(this.object, this.hasPragma);
}

ast.Component createFreshComponentWithBytecode(ast.Component component) {
  final newComponent = new ast.Component();
  final newRepository = new BytecodeMetadataRepository();
  newComponent.addMetadataRepository(newRepository);

  final oldRepository = component.metadata.remove(newRepository.tag);
  final metadata = oldRepository.mapping[component];
  newRepository.mapping[newComponent] = metadata;

  return newComponent;
}
