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

part of dart2js.js_emitter.startup_emitter.model_emitter;

/// The name of the property that stores the tear-off getter on a static
/// function.
///
/// This property is only used when isolates are used.
///
/// When serializing static functions we transmit the
/// name of the static function, but not the name of the function's getter. We
/// store the getter-function on the static function itself, which allows us to
/// find it easily.
const String tearOffPropertyName = r'$tearOff';

/// The name of the property that stores the list of fields on a constructor.
///
/// This property is only used when isolates are used.
///
/// When serializing objects we extract all fields from any given object.
/// We extract the names of all fields from a fresh empty object. This list
/// is cached on the constructor in this property to to avoid too many
/// allocations.
const String cachedClassFieldNames = r'$cachedFieldNames';

/// The fast startup emitter's goal is to minimize the amount of work that the
/// JavaScript engine has to do before it can start running user code.
///
/// Whenever possible, the emitter uses object literals instead of updating
/// objects.
///
/// Example:
///
///     // Holders are initialized directly with the classes and static
///     // functions.
///     var A = { Point: function Point(x, y) { this.x = x; this.y = y },
///               someStaticFunction: function someStaticFunction() { ... } };
///
///     // Class-behavior is emitted in a prototype object that is directly
///     // assigned:
///     A.Point.prototype = { distanceTo: function(other) { ... } };
///
///     // Inheritance is achieved by updating the prototype objects (hidden in
///     // a helper function):
///     A.Point.prototype.__proto__ = H.Object.prototype;
///
/// The emitter doesn't try to be clever and emits everything beforehand. This
/// increases the output size, but improves performance.
///
// The code relies on the fact that all Dart code is inside holders. As such
// we can use "global" names however we want. As long as we don't shadow
// JavaScript variables (like `Array`) we are free to chose whatever variable
// names we want. Furthermore, the pretty-printer minifies local variables, thus
// reducing their size.
const String mainBoilerplate = '''
{
// Declare deferred-initializer global, which is used to keep track of the
// loaded fragments.
#deferredInitializer;

(function() {
// Copies the own properties from [from] to [to].
function copyProperties(from, to) {
  var keys = Object.keys(from);
  for (var i = 0; i < keys.length; i++) {
    to[keys[i]] = from[keys[i]];
  }
}

var supportsDirectProtoAccess = (function () {
  var cls = function () {};
  cls.prototype = {'p': {}};
  var object = new cls();
  return object.__proto__ &&
         object.__proto__.p === cls.prototype.p;
})();

var functionsHaveName = (function() {
  function t() {};
  return (typeof t.name == 'string')
})();

var isChrome = (typeof window != 'undefined') &&
    (typeof window.chrome != 'undefined');

// Sets the name property of functions, if the JS engine doesn't set the name
// itself.
// As of 2015 only IE doesn't set the name.
function setFunctionNamesIfNecessary(holders) {
  if (functionsHaveName) return;
  for (var i = 0; i < holders.length; i++) {
    var holder = holders[i];
    var keys = Object.keys(holder);
    for (var j = 0; j < keys.length; j++) {
      var key = keys[j];
      var f = holder[key];
      if (typeof f == 'function') f.name = key;
    }
  }
}

// Makes [cls] inherit from [sup].
// On Chrome, Firefox and recent IEs this happens by updating the internal
// proto-property of the classes 'prototype' field.
// Older IEs use `Object.create` and copy over the properties.
function inherit(cls, sup) {
  cls.#typeNameProperty = cls.name;  // Needed for RTI.
  cls.prototype.constructor = cls;
  cls.prototype[#operatorIsPrefix + cls.name] = cls;

  // The superclass is only null for the Dart Object.
  if (sup != null) {
    if (supportsDirectProtoAccess) {
      // Firefox doesn't like to update the prototypes, but when setting up
      // the hierarchy chain it's ok.
      cls.prototype.__proto__ = sup.prototype;
      return;
    }
    var clsPrototype = Object.create(sup.prototype);
    copyProperties(cls.prototype, clsPrototype);
    cls.prototype = clsPrototype;
  }
}

// Mixes in the properties of [mixin] into [cls].
function mixin(cls, mixin) {
  copyProperties(mixin.prototype, cls.prototype);
}

// Creates a lazy field.
//
// A lazy field has a storage entry, [name], which holds the value, and a
// getter ([getterName]) to access the field. If the field wasn't set before
// the first access, it is initialized with the [initializer].
function lazy(holder, name, getterName, initializer) {
  var uninitializedSentinel = holder;
  holder[name] = uninitializedSentinel;
  holder[getterName] = function() {
    holder[getterName] = function() { #cyclicThrow(name) };
    var result;
    var sentinelInProgress = initializer;
    try {
      if (holder[name] === uninitializedSentinel) {
        result = holder[name] = sentinelInProgress;
        result = holder[name] = initializer();
      } else {
        result = holder[name];
      }
    } finally {
      // Use try-finally, not try-catch/throw as it destroys the stack
      // trace.
      if (result === sentinelInProgress) {
        // The lazy static (holder[name]) might have been set to a different
        // value. According to spec we still have to reset it to null, if
        // the initialization failed.
        holder[name] = null;
      }
      // TODO(floitsch): for performance reasons the function should probably
      // be unique for each static.
      holder[getterName] = function() { return this[name]; };
    }
    return result;
  };
}

// Given a list, marks it as constant.
//
// The runtime ensures that const-lists cannot be modified.
function makeConstList(list) {
  // By assigning a function to the properties they become part of the
  // hidden class. The actual values of the fields don't matter, since we
  // only check if they exist.
  list.immutable\$list = Array;
  list.fixed\$length = Array;
  return list;
}

function convertToFastObject(properties) {
  // Create an instance that uses 'properties' as prototype. This should
  // make 'properties' a fast object.
  function t() {};
  t.prototype = properties;
  new t();
  return properties;
}

// This variable is used by the tearOffCode to guarantee unique functions per
// tear-offs.
var functionCounter = 0;
#tearOffCode;

// Each deferred hunk comes with its own types which are added to the end
// of the types-array.
// The `funTypes` passed to the `installTearOff` function below is relative to
// the hunk the function comes from. The `typesOffset` variable encodes the
// offset at which the new types will be added.
var typesOffset = 0;

// Adapts the stored data, so it's suitable for a tearOff call.
//
// Stores the tear-off getter-function in the [container]'s [getterName]
// property.
//
// The [container] is either a class (that is, its prototype), or the holder for
// static functions.
//
// The argument [funsOrNames] is an array of strings or functions. If it is a
// name, then the function should be fetched from the container. The first
// entry in that array *must* be a string.
//
// TODO(floitsch): Change tearOffCode to accept the data directly, or create a
// different tearOffCode?
function installTearOff(
    container, getterName, isStatic, isIntercepted, requiredParameterCount,
    optionalParameterDefaultValues, callNames, funsOrNames, funType) {
  // A function can have several stubs (for example to fill in optional
  // arguments). We collect these functions in the `funs` array.
  var funs = [];
  for (var i = 0; i < funsOrNames.length; i++) {
    var fun = funsOrNames[i];
    if ((typeof fun) == 'string') fun = container[fun];
    fun.#callName = callNames[i];
    funs.push(fun);
  }

  // The main function to which all stubs redirect.
  var fun = funs[0];

  fun[#argumentCount] = requiredParameterCount;
  fun[#defaultArgumentValues] = optionalParameterDefaultValues;
  var reflectionInfo = funType;
  if (typeof reflectionInfo == "number") {
    // The reflectionInfo can either be a function, or a pointer into the types
    // table. If it points into the types-table we need to update the index,
    // in case the tear-off is part of a deferred hunk.
    reflectionInfo = reflectionInfo + typesOffset;
  }
  var name = funsOrNames[0];
  var getterFunction =
      tearOff(funs, reflectionInfo, isStatic, name, isIntercepted);
  container[getterName] = getterFunction;
  if (isStatic) {
    fun.$tearOffPropertyName = getterFunction;
  }
}

// Instead of setting the interceptor tags directly we use this update
// function. This makes it easier for deferred fragments to contribute to the
// embedded global.
function setOrUpdateInterceptorsByTag(newTags) {
  var tags = #embeddedInterceptorTags;
  if (!tags) {
    #embeddedInterceptorTags = newTags;
    return;
  }
  copyProperties(newTags, tags);
}

// Instead of setting the leaf tags directly we use this update
// function. This makes it easier for deferred fragments to contribute to the
// embedded global.
function setOrUpdateLeafTags(newTags) {
  var tags = #embeddedLeafTags;
  if (!tags) {
    #embeddedLeafTags = newTags;
    return;
  }
  copyProperties(newTags, tags);
}

// Updates the types embedded global.
function updateTypes(newTypes) {
  var types = #embeddedTypes;
  // This relies on the fact that types are added *after* the tear-offs have
  // been installed. The tear-off function uses the types-length to figure
  // out at which offset its types are located. If the types were added earlier
  // the offset would be wrong.
  types.push.apply(types, newTypes);
}

// Updates the given holder with the properties of the [newHolder].
// This function is used when a deferred fragment is initialized.
function updateHolder(holder, newHolder) {
  // Firefox doesn't like when important objects have their prototype chain
  // updated. We therefore do this only on V8.
  if (isChrome) {
    var oldPrototype = holder.__proto__;
    newHolder.__proto__ = oldPrototype;
    holder.__proto__ = newHolder;
  } else {
    copyProperties(newHolder, holder);
  }
  return holder;
}

// Every deferred hunk (i.e. fragment) is a function that we can invoke to
// initialize it. At this moment it contributes its data to the main hunk.
function initializeDeferredHunk(hunk) {
  // Update the typesOffset for the next deferred library.
  typesOffset = #embeddedTypes.length;

  // TODO(floitsch): extend natives.
  hunk(inherit, mixin, lazy, makeConstList, convertToFastObject, installTearOff,
       setFunctionNamesIfNecessary, updateHolder, updateTypes,
       setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
       #embeddedGlobalsObject, #holdersList, #staticState);
}

// Returns the global with the given [name].
function getGlobalFromName(name) {
  // TODO(floitsch): we are running through all holders. Since negative
  // lookups are expensive we might need to improve this.
  // Relies on the fact that all names are unique across all holders.
  for (var i = 0; i < holders.length; i++) {
    // The constant holder reuses the same names. Therefore we must skip it.
    if (holders[i] == #constantHolderReference) continue;
    // Relies on the fact that all variables are unique.
    if (holders[i][name]) return holders[i][name];
  }
}

// Creates the holders.
#holders;

// If the name is not set on the functions, do it now.
setFunctionNamesIfNecessary(#holdersList);

// TODO(floitsch): we should build this object as a literal.
var #staticStateDeclaration = {};

// Sets the prototypes of classes.
#prototypes;
// Sets aliases of methods (on the prototypes of classes).
#aliases;
// Installs the tear-offs of functions.
#tearOffs;
// Builds the inheritance structure.
#inheritance;

// Instantiates all constants.
#constants;
// Initializes the static non-final fields (with their constant values).
#staticNonFinalFields;
// Creates lazy getters for statics that must run initializers on first access.
#lazyStatics;

// Emits the embedded globals.
#embeddedGlobals;

// Sets up the native support.
// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
#nativeSupport;

// Invokes main (making sure that it records the 'current-script' value).
#invokeMain;
})();
}''';

/// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
///
/// However, at specific moments they need to contribute their data.
/// For example, once the holders have been created, they are included into
/// the main holders.
const String deferredBoilerplate = '''
function(inherit, mixin, lazy, makeConstList, convertToFastObject,
         installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes,
         setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
         #embeddedGlobalsObject, holdersList, #staticState) {

// Builds the holders. They only contain the data for new holders.
#holders;

// If the name is not set on the functions, do it now.
setFunctionNamesIfNecessary(#deferredHoldersList);

// Updates the holders of the main-fragment. Uses the provided holdersList to
// access the main holders.
// The local holders are replaced by the combined holders. This is necessary
// for the inheritance setup below.
#updateHolders;
// Sets the prototypes of the new classes.
#prototypes;
// Sets aliases of methods (on the prototypes of classes).
#aliases;
// Installs the tear-offs of functions.
#tearOffs;
// Builds the inheritance structure.
#inheritance;

// Instantiates all constants of this deferred fragment.
// Note that the constant-holder has been updated earlier and storing the
// constant values in the constant-holder makes them available globally.
#constants;
// Initializes the static non-final fields (with their constant values).
#staticNonFinalFields;
// Creates lazy getters for statics that must run initializers on first access.
#lazyStatics;

updateTypes(#types);

// Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
#nativeSupport;
}''';

/**
 * This class builds a JavaScript tree for a given fragment.
 *
 * A fragment is generally written into a separate file so that it can be
 * loaded dynamically when a deferred library is loaded.
 *
 * This class is stateless and can be reused for different fragments.
 */
class FragmentEmitter {
  final Compiler compiler;
  final Namer namer;
  final JavaScriptBackend backend;
  final ConstantEmitter constantEmitter;
  final ModelEmitter modelEmitter;

  FragmentEmitter(this.compiler, this.namer, this.backend, this.constantEmitter,
      this.modelEmitter);

  js.Expression generateEmbeddedGlobalAccess(String global) =>
      modelEmitter.generateEmbeddedGlobalAccess(global);

  js.Expression generateConstantReference(ConstantValue value) =>
      modelEmitter.generateConstantReference(value);

  js.Expression classReference(Class cls) {
    return js.js('#.#', [cls.holder.name, cls.name]);
  }

  js.Statement emitMainFragment(
      Program program,
      Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
    MainFragment fragment = program.fragments.first;

    Iterable<Holder> nonStaticStateHolders = program.holders
        .where((Holder holder) => !holder.isStaticStateHolder);

    return js.js.statement(mainBoilerplate,
        {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
         'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
         'cyclicThrow': backend.emitter.staticFunctionAccess(
                 backend.getCyclicThrowHelper()),
         'operatorIsPrefix': js.string(namer.operatorIsPrefix),
         'tearOffCode': new js.Block(buildTearOffCode(backend)),
         'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
         'embeddedInterceptorTags':
             generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
         'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS),
         'embeddedGlobalsObject': js.js("init"),
         'holdersList': new js.ArrayInitializer(nonStaticStateHolders
             .map((holder) => js.js("#", holder.name))
             .toList(growable: false)),
         'staticStateDeclaration': new js.VariableDeclaration(
             namer.staticStateHolder, allowRename: false),
         'staticState': js.js('#', namer.staticStateHolder),
         'constantHolderReference': buildConstantHolderReference(program),
         'holders': emitHolders(program.holders, fragment),
         'callName': js.string(namer.callNameField),
         'argumentCount': js.string(namer.requiredParameterField),
         'defaultArgumentValues': js.string(namer.defaultValuesField),
         'prototypes': emitPrototypes(fragment),
         'inheritance': emitInheritance(fragment),
         'aliases': emitInstanceMethodAliases(fragment),
         'tearOffs': emitInstallTearOffs(fragment),
         'constants': emitConstants(fragment),
         'staticNonFinalFields': emitStaticNonFinalFields(fragment),
         'lazyStatics': emitLazilyInitializedStatics(fragment),
         'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes),
         'nativeSupport': program.needsNativeSupport
              ? emitNativeSupport(fragment)
              : new js.EmptyStatement(),
         'invokeMain': fragment.invokeMain,
         });
  }

  js.Expression emitDeferredFragment(DeferredFragment fragment,
                                     js.Expression deferredTypes,
                                     List<Holder> holders) {
    List<Holder> nonStaticStateHolders = holders
        .where((Holder holder) => !holder.isStaticStateHolder)
        .toList(growable: false);

    List<js.Statement> updateHolderAssignments = <js.Statement>[];
    for (int i = 0; i < nonStaticStateHolders.length; i++) {
      Holder holder = nonStaticStateHolders[i];
      updateHolderAssignments.add(js.js.statement(
          '#holder = updateHolder(holdersList[#index], #holder)',
          {'index': js.number(i),
           'holder': new js.VariableUse(holder.name)}));
    }

    // TODO(floitsch): don't just reference 'init'.
    return js.js(deferredBoilerplate,
    {'embeddedGlobalsObject': new js.Parameter('init'),
     'staticState': new js.Parameter(namer.staticStateHolder),
     'holders': emitHolders(holders, fragment),
     'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders
         .map((holder) => js.js("#", holder.name))
         .toList(growable: false)),
     'updateHolders': new js.Block(updateHolderAssignments),
     'prototypes': emitPrototypes(fragment),
     'inheritance': emitInheritance(fragment),
     'aliases': emitInstanceMethodAliases(fragment),
     'tearOffs': emitInstallTearOffs(fragment),
     'constants': emitConstants(fragment),
     'staticNonFinalFields': emitStaticNonFinalFields(fragment),
     'lazyStatics': emitLazilyInitializedStatics(fragment),
     'types': deferredTypes,
     // TODO(floitsch): only call emitNativeSupport if we need native.
     'nativeSupport': emitNativeSupport(fragment),
    });
  }

  js.Statement emitDeferredInitializerGlobal(Map loadMap) {
    if (loadMap.isEmpty) return new js.Block.empty();

    String global = ModelEmitter.deferredInitializersGlobal;
    return js.js.statement(
        "if (typeof($global) === 'undefined') var # = Object.create(null);",
        new js.VariableDeclaration(global, allowRename: false));
  }

  /// Emits all holders, except for the static-state holder.
  ///
  /// The emitted holders contain classes (only the constructors) and all
  /// static functions.
  js.Statement emitHolders(List<Holder> holders, Fragment fragment) {
    // Skip the static-state holder in this function.
    holders = holders
        .where((Holder holder) => !holder.isStaticStateHolder)
        .toList(growable: false);

    Map<Holder, Map<js.Name, js.Expression>> holderCode =
        <Holder, Map<js.Name, js.Expression>>{};

    for (Holder holder in holders) {
      holderCode[holder] = <js.Name, js.Expression>{};
    }

    for (Library library in fragment.libraries) {
      for (StaticMethod method in library.statics) {
        assert(!method.holder.isStaticStateHolder);
        holderCode[method.holder].addAll(emitStaticMethod(method));
      }
      for (Class cls in library.classes) {
        assert(!cls.holder.isStaticStateHolder);
        holderCode[cls.holder][cls.name] = emitConstructor(cls);
      }
    }

    js.VariableInitialization emitHolderInitialization(Holder holder) {
      List<js.Property> properties = <js.Property>[];
      holderCode[holder].forEach((js.Name key, js.Expression value) {
        properties.add(new js.Property(js.quoteName(key), value));
      });

      return new js.VariableInitialization(
          new js.VariableDeclaration(holder.name, allowRename: false),
          new js.ObjectInitializer(properties));
    }

    // The generated code looks like this:
    //
    //    {
    //      var H = {...}, ..., G = {...};
    //      var holders = [ H, ..., G ];
    //    }

    List<js.Statement> statements = [
      new js.ExpressionStatement(
          new js.VariableDeclarationList(holders
              .map(emitHolderInitialization)
              .toList())),
      js.js.statement('var holders = #', new js.ArrayInitializer(
          holders
              .map((holder) => new js.VariableUse(holder.name))
              .toList(growable: false)))];
    return new js.Block(statements);
  }

  /// Returns a reference to the constant holder, or the JS-literal `null`.
  js.Expression buildConstantHolderReference(Program program) {
    Holder constantHolder = program.holders
        .firstWhere((Holder holder) => holder.isConstantsHolder,
                    orElse: () => null);
    if (constantHolder == null) return new js.LiteralNull();
    return new js.VariableUse(constantHolder.name);
  }

  /// Emits the given [method].
  ///
  /// A Dart method might result in several JavaScript functions, if it
  /// requires stubs. The returned map contains the original method and all
  /// the stubs it needs.
  Map<js.Name, js.Expression> emitStaticMethod(StaticMethod method) {
    Map<js.Name, js.Expression> jsMethods = <js.Name, js.Expression>{};

    // We don't need to install stub-methods. They can only be used when there
    // are tear-offs, in which case they are emitted there.
    assert(() {
      if (method is StaticDartMethod) {
        return method.needsTearOff || method.parameterStubs.isEmpty;
      }
      return true;
    });
    jsMethods[method.name] = method.code;

    return jsMethods;
  }

  /// Emits a constructor for the given class [cls].
  ///
  /// The constructor is statically built.
  js.Expression emitConstructor(Class cls) {
    List<js.Name> fieldNames = const <js.Name>[];

    // If the class is not directly instantiated we only need it for inheritance
    // or RTI. In either case we don't need its fields.
    if (cls.isDirectlyInstantiated && !cls.isNative) {
      fieldNames = cls.fields.map((Field field) => field.name).toList();
    }
    js.Name name = cls.name;

    Iterable<js.Name> assignments = fieldNames.map((js.Name field) {
      return js.js("this.#field = #field", {"field": field});
    });

    return js.js('function #(#) { # }', [name, fieldNames, assignments]);
  }

  /// Emits the prototype-section of the fragment.
  ///
  /// This section updates the prototype-property of all constructors in the
  /// global holders.
  js.Statement emitPrototypes(Fragment fragment) {
    List<js.Statement> assignments = fragment.libraries
        .expand((Library library) => library.classes)
        .map((Class cls) => js.js.statement(
            '#.prototype = #;',
            [classReference(cls), emitPrototype(cls)]))
        .toList(growable: false);

    return new js.Block(assignments);
  }

  /// Emits the prototype of the given class [cls].
  ///
  /// The prototype is generated as object literal. Inheritance is ignored.
  ///
  /// The prototype also includes the `is-property` that every class must have.
  // TODO(floitsch): we could avoid that property if we knew that it wasn't
  //    needed.
  js.Expression emitPrototype(Class cls) {
    Iterable<Method> methods = cls.methods;
    Iterable<Method> checkedSetters = cls.checkedSetters;
    Iterable<Method> isChecks = cls.isChecks;
    Iterable<Method> callStubs = cls.callStubs;
    Iterable<Method> typeVariableReaderStubs = cls.typeVariableReaderStubs;
    Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
    Iterable<Method> gettersSetters = generateGettersSetters(cls);
    Iterable<Method> allMethods =
        [methods, checkedSetters, isChecks, callStubs, typeVariableReaderStubs,
         noSuchMethodStubs, gettersSetters].expand((x) => x);

    List<js.Property> properties = <js.Property>[];

    if (cls.superclass == null) {
      properties.add(new js.Property(js.string("constructor"),
      classReference(cls)));
      properties.add(new js.Property(namer.operatorIs(cls.element),
      js.number(1)));
    }

    allMethods.forEach((Method method) {
      emitInstanceMethod(method)
          .forEach((js.Expression name, js.Expression code) {
        properties.add(new js.Property(name, code));
      });
    });

    return new js.ObjectInitializer(properties);
  }

  /// Generates a getter for the given [field].
  Method generateGetter(Field field) {
    assert(field.needsGetter);

    String template;
    if (field.needsInterceptedGetterOnReceiver) {
      template = "function(receiver) { return receiver[#]; }";
    } else if (field.needsInterceptedGetterOnThis) {
      template = "function(receiver) { return this[#]; }";
    } else {
      assert(!field.needsInterceptedGetter);
      template = "function() { return this[#]; }";
    }
    js.Expression fieldName = js.quoteName(field.name);
    js.Expression code = js.js(template, fieldName);
    js.Name getterName = namer.deriveGetterName(field.accessorName);
    return new StubMethod(getterName, code);
  }

  /// Generates a setter for the given [field].
  Method generateSetter(Field field) {
    assert(field.needsUncheckedSetter);

    String template;
    if (field.needsInterceptedSetterOnReceiver) {
      template = "function(receiver, val) { return receiver[#] = val; }";
    } else if (field.needsInterceptedSetterOnThis) {
      template = "function(receiver, val) { return this[#] = val; }";
    } else {
      assert(!field.needsInterceptedSetter);
      template = "function(val) { return this[#] = val; }";
    }

    js.Expression fieldName = js.quoteName(field.name);
    js.Expression code = js.js(template, fieldName);
    js.Name setterName = namer.deriveSetterName(field.accessorName);
    return new StubMethod(setterName, code);
  }

  /// Generates all getters and setters the given class [cls] needs.
  Iterable<Method> generateGettersSetters(Class cls) {
    Iterable<Method> getters = cls.fields
        .where((Field field) => field.needsGetter)
        .map(generateGetter);

    Iterable<Method> setters = cls.fields
        .where((Field field) => field.needsUncheckedSetter)
        .map(generateSetter);

    return [getters, setters].expand((x) => x);
  }

  /// Emits the given instance [method].
  ///
  /// The given method may be a stub-method (for example for is-checks).
  ///
  /// If it is a Dart-method, all necessary stub-methods are emitted, too. In
  /// that case the returned map contains more than just one entry.
  ///
  /// If the method is a closure call-method, also returns the necessary
  /// properties in case the closure can be applied.
  Map<js.Expression, js.Expression> emitInstanceMethod(Method method) {
    var properties = <js.Expression, js.Expression>{};

    properties[method.name] = method.code;
    if (method is InstanceMethod) {
      for (ParameterStubMethod stubMethod in method.parameterStubs) {
        properties[stubMethod.name] = stubMethod.code;
      }

      if (method.isClosureCallMethod && method.canBeApplied) {
        properties[js.string(namer.callCatchAllName)] =
            js.quoteName(method.name);
        properties[js.string(namer.requiredParameterField)] =
            js.number(method.requiredParameterCount);
        properties[js.string(namer.defaultValuesField)] =
             _encodeOptionalParameterDefaultValues(method);
      }
    }

    return properties;
  }

  /// Emits the inheritance block of the fragment.
  ///
  /// In this section prototype chains are updated and mixin functions are
  /// copied.
  js.Statement emitInheritance(Fragment fragment) {
    List<js.Expression> inheritCalls = <js.Expression>[];
    List<js.Expression> mixinCalls = <js.Expression>[];

    for (Library library in fragment.libraries) {
      for (Class cls in library.classes) {
        js.Expression superclassReference = (cls.superclass == null)
            ? new js.LiteralNull()
            : classReference(cls.superclass);

        inheritCalls.add(js.js('inherit(#, #)',
            [classReference(cls), superclassReference]));

        if (cls.isMixinApplication) {
          MixinApplication mixin = cls;
          mixinCalls.add(js.js('mixin(#, #)',
              [classReference(cls), classReference(mixin.mixinClass)]));
        }
      }
    }

    return new js.Block([inheritCalls, mixinCalls]
        .expand((e) => e)
        .map((e) => new js.ExpressionStatement(e))
        .toList(growable: false));
  }

  /// Emits the setup of method aliases.
  ///
  /// This step consists of simply copying JavaScript functions to their
  /// aliased names so they point to the same function.
  js.Statement emitInstanceMethodAliases(Fragment fragment) {
    List<js.Statement> assignments = <js.Statement>[];

    for (Library library in fragment.libraries) {
      for (Class cls in library.classes) {
        for (InstanceMethod method in cls.methods) {
          if (method.aliasName != null) {
            assignments.add(js.js.statement(
                '#.prototype.# = #.prototype.#',
                [classReference(cls), js.quoteName(method.aliasName),
                 classReference(cls), js.quoteName(method.name)]));

          }
        }
      }
    }
    return new js.Block(assignments);
  }

  /// Encodes the optional default values so that the runtime Function.apply
  /// can use them.
  js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
    // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
    if (method.optionalParameterDefaultValues is List) {
      List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
      Iterable<js.Expression> elements =
          defaultValues.map(generateConstantReference);
      return js.js('function() { return #; }',
          new js.ArrayInitializer(elements.toList()));
    } else {
      Map<String, ConstantValue> defaultValues =
          method.optionalParameterDefaultValues;
      List<js.Property> properties = <js.Property>[];
      List<String> names = defaultValues.keys.toList(growable: false);
      // Sort the names the same way we sort them for the named-argument calling
      // convention.
      names.sort();

      for (String name in names) {
        ConstantValue value = defaultValues[name];
        properties.add(new js.Property(js.string(name),
        generateConstantReference(value)));
      }
      return js.js('function() { return #; }',
          new js.ObjectInitializer(properties));
    }
  }

  /// Emits the statement that installs a tear off for a method.
  ///
  /// Tear-offs might be passed to `Function.apply` which means that all
  /// calling-conventions (with or without optional positional/named arguments)
  /// are possible. As such, the tear-off needs enough information to fill in
  /// missing parameters.
  js.Statement emitInstallTearOff(js.Expression container, DartMethod method) {
    List<js.Name> callNames = <js.Name>[];
    List<js.Expression> funsOrNames = <js.Expression>[];

    /// Adds the stub-method's code or name to the [funsOrNames] array.
    ///
    /// Static methods don't need stub-methods except for tear-offs. As such,
    /// they are not emitted in the prototype, but directly passed here.
    ///
    /// Instance-methods install the stub-methods in their prototype, and we
    /// use string-based redirections to find them there.
    void addFunOrName(StubMethod stubMethod) {
      if (method.isStatic) {
        funsOrNames.add(stubMethod.code);
      } else {
        funsOrNames.add(js.quoteName(stubMethod.name));
      }
    }

    callNames.add(method.callName);
    // The first entry in the funsOrNames-array must be a string.
    funsOrNames.add(js.quoteName(method.name));
    for (ParameterStubMethod stubMethod in method.parameterStubs) {
      callNames.add(stubMethod.callName);
      addFunOrName(stubMethod);
    }

    js.ArrayInitializer callNameArray =
        new js.ArrayInitializer(callNames.map(js.quoteName).toList());
    js.ArrayInitializer funsOrNamesArray = new js.ArrayInitializer(funsOrNames);

    bool isIntercepted = false;
    if (method is InstanceMethod) {
      isIntercepted = backend.isInterceptedMethod(method.element);
    }
    int requiredParameterCount = 0;
    js.Expression optionalParameterDefaultValues = new js.LiteralNull();
    if (method.canBeApplied) {
      requiredParameterCount = method.requiredParameterCount;
      optionalParameterDefaultValues =
          _encodeOptionalParameterDefaultValues(method);
    }

    return js.js.statement('''
        installTearOff(#container, #getterName, #isStatic, #isIntercepted,
                       #requiredParameterCount, #optionalParameterDefaultValues,
                       #callNames, #funsOrNames, #funType)''',
        {
          "container": container,
          "getterName": js.quoteName(method.tearOffName),
          "isStatic": new js.LiteralBool(method.isStatic),
          "isIntercepted": new js.LiteralBool(isIntercepted),
          "requiredParameterCount": js.number(requiredParameterCount),
          "optionalParameterDefaultValues": optionalParameterDefaultValues,
          "callNames": callNameArray,
          "funsOrNames": funsOrNamesArray,
          "funType": method.functionType,
        });
  }

  /// Emits the section that installs tear-off getters.
  js.Statement emitInstallTearOffs(Fragment fragment) {
    List<js.Statement> inits = <js.Statement>[];

    for (Library library in fragment.libraries) {
      for (StaticMethod method in library.statics) {
        // TODO(floitsch): can there be anything else than a StaticDartMethod?
        if (method is StaticDartMethod) {
          if (method.needsTearOff) {
            Holder holder = method.holder;
            inits.add(
                emitInstallTearOff(new js.VariableUse(holder.name), method));
          }
        }
      }
      for (Class cls in library.classes) {
        for (InstanceMethod method in cls.methods) {
          if (method.needsTearOff) {
            js.Expression container = js.js("#.prototype", classReference(cls));
            inits.add(emitInstallTearOff(container, method));
          }
        }
      }
    }
    return new js.Block(inits);
  }

  /// Emits the constants section.
  js.Statement emitConstants(Fragment fragment) {
    List<js.Statement> assignments = <js.Statement>[];
    for (Constant constant in fragment.constants) {
      // TODO(floitsch): instead of just updating the constant holder, we should
      // find the constants that don't have any dependency on other constants
      // and create an object-literal with them (and assign it to the
      // constant-holder variable).
      assignments.add(js.js.statement('#.# = #',
          [constant.holder.name,
           constant.name,
           constantEmitter.generate(constant.value)]));
    }
    return new js.Block(assignments);
  }


  /// Emits the static non-final fields section.
  ///
  /// This section initializes all static non-final fields that don't require
  /// an initializer.
  js.Block emitStaticNonFinalFields(Fragment fragment) {
    List<StaticField> fields = fragment.staticNonFinalFields;
    // TODO(floitsch): instead of assigning the fields one-by-one we should
    // create a literal and assign it to the static-state holder.
    // TODO(floitsch): if we don't make a literal we should at least initialize
    // statics that have the same initial value in the same expression:
    //    `$.x = $.y = $.z = null;`.
    Iterable<js.Statement> statements = fields.map((StaticField field) {
      assert(field.holder.isStaticStateHolder);
      return js.js.statement("#.# = #;",
          [field.holder.name, field.name, field.code]);
    });
    return new js.Block(statements.toList());
  }

  /// Emits lazy fields.
  ///
  /// This section initializes all static (final and non-final) fields that
  /// require an initializer.
  js.Block emitLazilyInitializedStatics(Fragment fragment) {
    List<StaticField> fields = fragment.staticLazilyInitializedFields;
    Iterable<js.Statement> statements = fields.map((StaticField field) {
      assert(field.holder.isStaticStateHolder);
      return js.js.statement("lazy(#, #, #, #);",
          [field.holder.name,
           js.quoteName(field.name),
           js.quoteName(namer.deriveLazyInitializerName(field.name)),
           field.code]);
    });

    return new js.Block(statements.toList());
  }

  /// Emits the embedded globals that are needed for deferred loading.
  ///
  /// This function is only invoked for the main fragment.
  ///
  /// The [loadMap] contains a map from load-ids (for each deferred library)
  /// to the list of generated fragments that must be installed when the
  /// deferred library is loaded.
  Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
      Map<String, List<Fragment>> loadMap,
      Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
    if (loadMap.isEmpty) return [];

    List<js.Property> globals = <js.Property>[];

    js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
      return js.stringArray(fragments.map((DeferredFragment fragment) =>
          "${fragment.outputFileName}.${ModelEmitter.deferredExtension}"));
    }
    js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
      return new js.ArrayInitializer(
          fragments
              .map((fragment) => deferredLoadHashes[fragment])
              .toList(growable: false));
    }

    List<js.Property> uris = new List<js.Property>(loadMap.length);
    List<js.Property> hashes = new List<js.Property>(loadMap.length);
    int count = 0;
    loadMap.forEach((String loadId, List<Fragment> fragmentList) {
      uris[count] =
          new js.Property(js.string(loadId), fragmentUris(fragmentList));
      hashes[count] =
          new js.Property(js.string(loadId), fragmentHashes(fragmentList));
      count++;
    });

    globals.add(new js.Property(js.string(DEFERRED_LIBRARY_URIS),
        new js.ObjectInitializer(uris)));
    globals.add(new js.Property(js.string(DEFERRED_LIBRARY_HASHES),
        new js.ObjectInitializer(hashes)));
    globals.add(new js.Property(js.string(DEFERRED_INITIALIZED),
        js.js("Object.create(null)")));

    String deferredGlobal = ModelEmitter.deferredInitializersGlobal;
    js.Expression isHunkLoadedFunction =
        js.js("function(hash) { return !!$deferredGlobal[hash]; }");
    globals.add(new js.Property(js.string(IS_HUNK_LOADED),
        isHunkLoadedFunction));

    js.Expression isHunkInitializedFunction =
        js.js("function(hash) { return !!#deferredInitialized[hash]; }",
            {'deferredInitialized':
                generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)});
    globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED),
        isHunkInitializedFunction));

    /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the
    /// deferred hunk.
    js.Expression initializeLoadedHunkFunction =
    js.js("""
            function(hash) {
              initializeDeferredHunk($deferredGlobal[hash]);
              #deferredInitialized[hash] = true;
            }""", {'deferredInitialized':
                    generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)});

    globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK),
                                initializeLoadedHunkFunction));

    return globals;
  }

  /// Emits the [MANGLED_GLOBAL_NAMES] embedded global.
  ///
  /// This global maps minified names for selected classes (some important
  /// core classes, and some native classes) to their unminified names.
  js.Property emitMangledGlobalNames() {
    List<js.Property> names = <js.Property>[];

    // We want to keep the original names for the most common core classes when
    // calling toString on them.
    List<ClassElement> nativeClassesNeedingUnmangledName =
        [compiler.intClass, compiler.doubleClass, compiler.numClass,
         compiler.stringClass, compiler.boolClass, compiler.nullClass,
         compiler.listClass];
    // TODO(floitsch): this should probably be on a per-fragment basis.
    nativeClassesNeedingUnmangledName.forEach((element) {
      names.add(new js.Property(js.quoteName(namer.className(element)),
                                js.string(element.name)));
    });

    return new js.Property(js.string(MANGLED_GLOBAL_NAMES),
                           new js.ObjectInitializer(names));
  }

  /// Emits the [GET_TYPE_FROM_NAME] embedded global.
  ///
  /// This embedded global provides a way to go from a class name (which is
  /// also the constructor's name) to the constructor itself.
  js.Property emitGetTypeFromName() {
    js.Expression function = js.js("getGlobalFromName");
    return new js.Property(js.string(GET_TYPE_FROM_NAME), function);
  }

  /// Emits the [METADATA] embedded global.
  ///
  /// The metadata itself has already been computed earlier and is stored in
  /// the [program].
  List<js.Property> emitMetadata(Program program) {
    List<js.Property> metadataGlobals = <js.Property>[];

    js.Property createGlobal(js.Expression metadata, String global) {
      return new js.Property(js.string(global), metadata);
    }

    metadataGlobals.add(createGlobal(program.metadata, METADATA));
    js.Expression types =
        program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
    metadataGlobals.add(createGlobal(types, TYPES));

    return metadataGlobals;
  }

  /// Emits all embedded globals.
  js.Statement emitEmbeddedGlobals(
      Program program,
      Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
    List<js.Property> globals = <js.Property>[];

    if (program.loadMap.isNotEmpty) {
      globals.addAll(emitEmbeddedGlobalsForDeferredLoading(
          program.loadMap, deferredLoadHashes));
    }

    if (program.typeToInterceptorMap != null) {
      globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
      program.typeToInterceptorMap));
    }

    if (program.hasIsolateSupport) {
      String staticStateName = namer.staticStateHolder;
      // TODO(floitsch): this doesn't create a new isolate, but just reuses
      // the current static state. Since we don't run multiple isolates in the
      // same JavaScript context (except for testing) this shouldn't have any
      // impact on real-world programs, though.
      globals.add(
          new js.Property(js.string(CREATE_NEW_ISOLATE),
                          js.js('function () { return $staticStateName; }')));

      js.Expression nameToClosureFunction = js.js('''
        // First fetch the static function. From there we can execute its
        // getter function which builds a Dart closure.
        function(name) {
           var staticFunction = getGlobalFromName(name);
           var getterFunction = staticFunction.$tearOffPropertyName;
           return getterFunction();
         }''');
      globals.add(new js.Property(js.string(STATIC_FUNCTION_NAME_TO_CLOSURE),
                                  nameToClosureFunction));

      globals.add(
          new js.Property(js.string(CLASS_ID_EXTRACTOR),
                          js.js('function(o) { return o.constructor.name; }')));

      js.Expression extractFieldsFunction = js.js('''
      function(o) {
        var constructor = o.constructor;
        var fieldNames = constructor.$cachedClassFieldNames;
        if (!fieldNames) {
          // Extract the fields from an empty unmodified object.
          var empty = new constructor();
          // This gives us the keys that the constructor sets.
          fieldNames = constructor.$cachedClassFieldNames = Object.keys(empty);
        }
        var result = new Array(fieldNames.length);
        for (var i = 0; i < fieldNames.length; i++) {
          result[i] = o[fieldNames[i]];
        }
        return result;
      }''');
      globals.add(new js.Property(js.string(CLASS_FIELDS_EXTRACTOR),
                                  extractFieldsFunction));

      js.Expression createInstanceFromClassIdFunction = js.js('''
        function(name) {
          var constructor = getGlobalFromName(name);
          return new constructor();
        }
      ''');
      globals.add(new js.Property(js.string(INSTANCE_FROM_CLASS_ID),
                                  createInstanceFromClassIdFunction));

      js.Expression initializeEmptyInstanceFunction = js.js('''
      function(name, o, fields) {
        var constructor = o.constructor;
        // By construction the object `o` is an empty object with the same
        // keys as the one we used in the extract-fields function.
        var fieldNames = Object.keys(o);
        if (fieldNames.length != fields.length) {
          throw new Error("Mismatch during deserialization.");
        }
        for (var i = 0; i < fields.length; i++) {
          o[fieldNames[i]] = fields[i];
        }
        return o;
      }''');
      globals.add(new js.Property(js.string(INITIALIZE_EMPTY_INSTANCE),
                                  initializeEmptyInstanceFunction));
    }

    globals.add(emitMangledGlobalNames());

    // The [MANGLED_NAMES] table must contain the mapping for const symbols.
    // Without const symbols, the table is only relevant for reflection and
    // therefore unused in this emitter.
    List<js.Property> mangledNamesProperties = <js.Property>[];
    program.symbolsMap.forEach((js.Name mangledName, String unmangledName) {
      mangledNamesProperties.add(
          new js.Property(mangledName, js.string(unmangledName)));
    });
    globals.add(new js.Property(
        js.string(MANGLED_NAMES),
        new js.ObjectInitializer(mangledNamesProperties)));

    globals.add(emitGetTypeFromName());

    globals.addAll(emitMetadata(program));

    if (program.needsNativeSupport) {
      globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG),
          new js.LiteralNull()));
      globals.add(new js.Property(js.string(LEAF_TAGS),
          new js.LiteralNull()));
    }

    js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);

    return js.js.statement('var init = #;', globalsObject);
  }

  /// Emits data needed for native classes.
  ///
  /// We don't try to reduce the size of the native data, but rather build
  /// JavaScript object literals that contain all the information directly.
  /// This means that the output size is bigger, but that the startup is faster.
  ///
  /// This function is the static equivalent of
  /// [NativeGenerator.buildNativeInfoHandler].
  js.Statement emitNativeSupport(Fragment fragment) {
    List<js.Statement> statements = <js.Statement>[];

    // The isolate-affinity tag must only be initialized once per program.
    if (fragment.isMainFragment &&
        NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
      statements.add(NativeGenerator.generateIsolateAffinityTagInitialization(
              backend,
              generateEmbeddedGlobalAccess,
              js.js("""
        // On V8, the 'intern' function converts a string to a symbol, which
        // makes property access much faster.
        function (s) {
          var o = {};
          o[s] = 1;
          return Object.keys(convertToFastObject(o))[0];
        }""", [])));
    }

    Map<String, js.Expression> interceptorsByTag = <String, js.Expression>{};
    Map<String, js.Expression> leafTags = <String, js.Expression>{};
    js.Statement subclassAssignment = new js.EmptyStatement();

    for (Library library in fragment.libraries) {
      for (Class cls in library.classes) {
        if (cls.nativeLeafTags != null) {
          for (String tag in cls.nativeLeafTags) {
            interceptorsByTag[tag] = classReference(cls);
            leafTags[tag] = new js.LiteralBool(true);
          }
        }
        if (cls.nativeNonLeafTags != null) {
          for (String tag in cls.nativeNonLeafTags) {
            interceptorsByTag[tag] = classReference(cls);
            leafTags[tag] = new js.LiteralBool(false);
          }
          if (cls.nativeExtensions != null) {
            List<Class> subclasses = cls.nativeExtensions;
            js.Expression value = js.string(cls.nativeNonLeafTags[0]);
            for (Class subclass in subclasses) {
              value = js.js('#.# = #',
                  [classReference(subclass),
                   NATIVE_SUPERCLASS_TAG_NAME,
                   js.string(cls.nativeNonLeafTags[0])]);
            }
            subclassAssignment = new js.ExpressionStatement(value);
          }
        }
      }
    }
    statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);",
        js.objectLiteral(interceptorsByTag)));
    statements.add(js.js.statement("setOrUpdateLeafTags(#);",
        js.objectLiteral(leafTags)));
    statements.add(subclassAssignment);

    return new js.Block(statements);
  }
}
