// Copyright (c) 2014, 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 dart2js.js_emitter.class_stub_generator;

import 'package:js_runtime/shared/embedded_names.dart'
    show TearOffParametersPropertyNames;

import '../common/names.dart' show Identifiers, Selectors;
import '../common_elements.dart' show CommonElements;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_backend/field_analysis.dart';
import '../js_backend/namer.dart' show Namer;
import '../js_backend/interceptor_data.dart' show InterceptorData;
import '../options.dart';
import '../universe/codegen_world_builder.dart';
import '../universe/selector.dart' show Selector;
import '../universe/world_builder.dart' show SelectorConstraints;
import '../world.dart' show JClosedWorld;

import 'code_emitter_task.dart';
import 'model.dart';

class ClassStubGenerator {
  final Namer _namer;
  final CodegenWorld _codegenWorld;
  final JClosedWorld _closedWorld;
  final bool enableMinification;
  final Emitter _emitter;
  final CommonElements _commonElements;

  ClassStubGenerator(this._emitter, this._commonElements, this._namer,
      this._codegenWorld, this._closedWorld,
      {this.enableMinification});

  InterceptorData get _interceptorData => _closedWorld.interceptorData;

  /// Documentation wanted -- johnniwinther
  ///
  /// Invariant: [member] must be a declaration element.
  Map<jsAst.Name, jsAst.Expression> generateCallStubsForGetter(
      MemberEntity member, Map<Selector, SelectorConstraints> selectors) {
    // If the method is intercepted, the stub gets the
    // receiver explicitly and we need to pass it to the getter call.
    bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member);
    bool isInterceptedClass =
        _interceptorData.isInterceptedClass(member.enclosingClass);

    const String receiverArgumentName = r'$receiver';

    jsAst.Expression buildGetter() {
      jsAst.Expression receiver =
          js(isInterceptedClass ? receiverArgumentName : 'this');
      if (member.isGetter) {
        jsAst.Name getterName = _namer.getterForElement(member);
        if (isInterceptedMethod) {
          return js('this.#(#)', [getterName, receiver]);
        }
        return js('#.#()', [receiver, getterName]);
      } else {
        FieldAnalysisData fieldData =
            _closedWorld.fieldAnalysis.getFieldData(member);
        if (fieldData.isEffectivelyConstant) {
          return _emitter.constantReference(fieldData.constantValue);
        } else {
          jsAst.Name fieldName = _namer.instanceFieldPropertyName(member);
          return js('#.#', [receiver, fieldName]);
        }
      }
    }

    Map<jsAst.Name, jsAst.Expression> generatedStubs = {};

    // Two selectors may match but differ only in type.  To avoid generating
    // identical stubs for each we track untyped selectors which already have
    // stubs.
    Set<Selector> generatedSelectors = {};
    for (Selector selector in selectors.keys) {
      if (generatedSelectors.contains(selector)) continue;
      if (!selector.appliesUnnamed(member)) continue;
      if (selectors[selector]
          .canHit(member, selector.memberName, _closedWorld)) {
        generatedSelectors.add(selector);

        jsAst.Name invocationName = _namer.invocationName(selector);
        Selector callSelector = Selector.callClosureFrom(selector);
        jsAst.Name closureCallName = _namer.invocationName(callSelector);

        List<jsAst.Parameter> parameters = [];
        List<jsAst.Expression> arguments = [];
        if (isInterceptedMethod) {
          parameters.add(jsAst.Parameter(receiverArgumentName));
        }

        for (int i = 0; i < selector.argumentCount; i++) {
          String name = 'arg$i';
          parameters.add(jsAst.Parameter(name));
          arguments.add(js('#', name));
        }

        for (int i = 0; i < selector.typeArgumentCount; i++) {
          String name = '\$T${i + 1}';
          parameters.add(jsAst.Parameter(name));
          arguments.add(js('#', name));
        }

        jsAst.Fun function = js('function(#) { return #.#(#); }',
            [parameters, buildGetter(), closureCallName, arguments]);

        generatedStubs[invocationName] = function;
      }
    }

    return generatedStubs;
  }

  Map<jsAst.Name, Selector> computeSelectorsForNsmHandlers() {
    Map<jsAst.Name, Selector> jsNames = {};

    // Do not generate no such method handlers if there is no class.
    if (_codegenWorld.directlyInstantiatedClasses.isEmpty) {
      return jsNames;
    }

    void addNoSuchMethodHandlers(
        String ignore, Map<Selector, SelectorConstraints> selectors) {
      for (Selector selector in selectors.keys) {
        if (selector == Selectors.runtimeType_ ||
            selector == Selectors.equals ||
            selector == Selectors.toString_ ||
            selector == Selectors.hashCode_ ||
            selector == Selectors.noSuchMethod_) {
          // Skip Object methods since these need no noSuchMethod handling
          // regardless of the precision of the selector constraints.
          continue;
        }

        SelectorConstraints maskSet = selectors[selector];
        if (maskSet.needsNoSuchMethodHandling(selector, _closedWorld)) {
          jsAst.Name jsName = _namer.invocationMirrorInternalName(selector);
          jsNames[jsName] = selector;
        }
      }
    }

    _codegenWorld.forEachInvokedName(addNoSuchMethodHandlers);
    _codegenWorld.forEachInvokedGetter(addNoSuchMethodHandlers);
    _codegenWorld.forEachInvokedSetter(addNoSuchMethodHandlers);
    return jsNames;
  }

  StubMethod generateStubForNoSuchMethod(jsAst.Name name, Selector selector) {
    // Values match JSInvocationMirror in js-helper library.
    int type = selector.invocationMirrorKind;
    List<String> parameterNames =
        List.generate(selector.argumentCount, (i) => '\$$i') +
            List.generate(selector.typeArgumentCount, (i) => '\$T${i + 1}');

    List<jsAst.Expression> argNames = selector.callStructure
        .getOrderedNamedArguments()
        .map((String name) => js.string(name))
        .toList();

    jsAst.Name methodName = _namer.asName(selector.invocationMirrorMemberName);
    jsAst.Name internalName = _namer.invocationMirrorInternalName(selector);

    assert(_interceptorData.isInterceptedName(Identifiers.noSuchMethod_));
    bool isIntercepted = _interceptorData.isInterceptedName(selector.name);
    jsAst.Expression expression = js('''this.#noSuchMethodName(#receiver,
                    #createInvocationMirror(#methodName,
                                            #internalName,
                                            #type,
                                            #arguments,
                                            #namedArguments,
                                            #typeArgumentCount))''', {
      'receiver': isIntercepted ? r'$receiver' : 'this',
      'noSuchMethodName': _namer.noSuchMethodName,
      'createInvocationMirror':
          _emitter.staticFunctionAccess(_commonElements.createInvocationMirror),
      'methodName':
          js.quoteName(enableMinification ? internalName : methodName),
      'internalName': js.quoteName(internalName),
      'type': js.number(type),
      'arguments': jsAst.ArrayInitializer(
          parameterNames.map<jsAst.Expression>(js).toList()),
      'namedArguments': jsAst.ArrayInitializer(argNames),
      'typeArgumentCount': js.number(selector.typeArgumentCount)
    });

    jsAst.Expression function;
    if (isIntercepted) {
      function = js(
          r'function($receiver, #) { return # }', [parameterNames, expression]);
    } else {
      function = js(r'function(#) { return # }', [parameterNames, expression]);
    }
    return StubMethod(name, function);
  }

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

    jsAst.Expression code;
    if (field.isElided) {
      ConstantValue constantValue = field.constantValue;
      assert(
          constantValue != null, "No constant value for elided field: $field");
      if (constantValue == null) {
        // This should never occur because codegen member usage is now limited
        // by closed world member usage. In the case we've missed a spot we
        // cautiously generate a null constant.
        constantValue = NullConstantValue();
      }
      code = js("function() { return #; }",
          _emitter.constantReference(constantValue));
    } else {
      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[#]; }";
      }
      jsAst.Expression fieldName = js.quoteName(field.name);
      code = js(template, fieldName);
    }
    jsAst.Name getterName = _namer.deriveGetterName(field.accessorName);
    return StubMethod(getterName, code);
  }

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

    String template;
    jsAst.Expression code;
    if (field.isElided) {
      code = js("function() { }");
    } else {
      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; }";
      }
      jsAst.Expression fieldName = js.quoteName(field.name);
      code = js(template, fieldName);
    }

    jsAst.Name setterName = _namer.deriveSetterName(field.accessorName);
    return StubMethod(setterName, code);
  }
}

/// Creates two JavaScript functions: `tearOffGetter` and `tearOff`.
///
/// `tearOffGetter` is internal and only used by `tearOff`.
///
/// `tearOff` takes the following arguments:
///   * `funcs`: a list of functions. These are the functions representing the
///     member that is torn off. There can be more than one, since a member
///     can have several stubs.
///     Each function must have the `$callName` property set.
///   * `applyTrampolineIndex` is the index of the stub to be used for
///     Function.apply
///   * `reflectionInfo`: contains reflective information, and the function
///     type. TODO(floitsch): point to where this is specified.
///   * `isStatic`.
///   * `name`.
///   * `isIntercepted.
List<jsAst.Statement> buildTearOffCode(
    CompilerOptions options, Emitter emitter, CommonElements commonElements) {
  FunctionEntity closureFromTearOff = commonElements.closureFromTearOff;
  jsAst.Expression closureFromTearOffAccessExpression;
  if (closureFromTearOff != null) {
    closureFromTearOffAccessExpression =
        emitter.staticFunctionAccess(closureFromTearOff);
  } else {
    // Default values for mocked-up test libraries.
    closureFromTearOffAccessExpression =
        js(r'''function() { throw "Helper 'closureFromTearOff' missing." }''');
  }

  jsAst.Statement instanceTearOffGetter;
  if (options.useContentSecurityPolicy) {
    instanceTearOffGetter = js.statement(
      '''
      function instanceTearOffGetter(isIntercepted, parameters) {
        var cache = null;
        return isIntercepted
            ? function(receiver) {
                if (cache === null) cache = #createTearOffClass(parameters);
                return new cache(receiver, this);
              }
            : function() {
                if (cache === null) cache = #createTearOffClass(parameters);
                return new cache(this, null);
              };
      }''',
      {'createTearOffClass': closureFromTearOffAccessExpression},
    );
  } else {
    // In the CSP version above, the allocation `new cache(...)` is polymorphic
    // since the same JavaScript anonymous function is used for all instance
    // tear-offs.
    //
    // The following code uses `new Function` to create a fresh instance method
    // tear-off getter for each method, allowing the allocation to be
    // monomorphic. This translates into a 2x performance improvement when a
    // method is torn-off many times.  The cost is that the getter, created via
    // `new Function`, is more expensive to create, and that cost is at program
    // startup.
    //
    // The a counter in the name ensures that the JavaScript engine does not
    // attempt to fold all of the almost-identical functions back to the same
    // instance of Function.
    //
    // Functions created by `new Function` are at the JavaScript global scope,
    // so cannot close-over any values from an 'intermediate' enclosing scope.
    // We use `new Function` to create a function that is immediately applied to
    // create a context with the closed-over values. The closed-over values
    // include parameters, (Dart) top-level definitions, and the local `cache`
    // variable all in one context (passing `null` to initialize `cache`).
    instanceTearOffGetter = js.statement(
      '''
function instanceTearOffGetter(isIntercepted, parameters) {
  var name = parameters.#tpFunctionsOrNames[0];
  if (isIntercepted)
    return new Function("parameters, createTearOffClass, cache",
        "return function tearOff_" + name + (functionCounter++) + "(receiver) {" +
          "if (cache === null) cache = createTearOffClass(parameters);" +
            "return new cache(receiver, this);" +
        "}")(parameters, #createTearOffClass, null);
  else
    return new Function("parameters, createTearOffClass, cache",
        "return function tearOff_" + name + (functionCounter++)+ "() {" +
          "if (cache === null) cache = createTearOffClass(parameters);" +
            "return new cache(this, null);" +
        "}")(parameters, #createTearOffClass, null);
}''',
      {
        'tpFunctionsOrNames':
            js.string(TearOffParametersPropertyNames.funsOrNames),
        'createTearOffClass': closureFromTearOffAccessExpression
      },
    );
  }

  jsAst.Statement staticTearOffGetter = js.statement(
    '''
function staticTearOffGetter(parameters) {
  var cache = null;
  return function() {
    if (cache === null) cache = #createTearOffClass(parameters).prototype;
    return cache;
  }
}''',
    {'createTearOffClass': closureFromTearOffAccessExpression},
  );

  return [instanceTearOffGetter, staticTearOffGetter];
}
