/*
 * Copyright 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.jjs.impl;

import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JRunAsync;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;

/**
 * Update polymorphic method calls to tighter bindings based on the type of the
 * qualifier. For a given polymorphic method call to a non-final target, see if
 * the static type of the qualifer would let us target an override instead.
 *
 * This is possible because the qualifier might have been tightened by
 * {@link com.google.gwt.dev.jjs.impl.TypeTightener}.
 *
 * For example, given the code:
 *
 * <pre>
 *   List foo = new ArrayList<String>();
 *   foo.add("bar");
 * </pre>
 *
 * The type of foo is tightened by TypeTightener from type List to be of type
 * ArrayList. This means that MethodCallTightener can analyze the polymorphic
 * call List.add() on foo and tighten it to the more specific ArrayList.add().
 */
public class MethodCallTightener {
  /**
   * Updates polymorphic method calls to tighter bindings based on the type of
   * the qualifier.
   */
  public class MethodCallTighteningVisitor extends JChangeTrackingVisitor {

    public MethodCallTighteningVisitor(OptimizerContext optimizerCtx) {
      super(optimizerCtx);
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      // The method call is already known statically
      if (x.isVolatile() || !x.canBePolymorphic()) {
        return;
      }

      JType instanceType = x.getInstance().getType().getUnderlyingType();
      if (!(instanceType instanceof JClassType)) {
        // Cannot tighten.
        return;
      }

      JMethodCall newCall = maybeUpgradeToNonPolymorphicCall(x);

      // If the call is still polymorphic, try tightening the method.
      if (newCall.canBePolymorphic()) {
        newCall = maybeTightenMethodCall(newCall);
      }

      if (newCall != x) {
        ctx.replaceMe(newCall);
      }
    }

    private JMethodCall maybeUpgradeToNonPolymorphicCall(JMethodCall x) {
      JReferenceType instanceType = (JReferenceType) x.getInstance().getType();

      if (!instanceType.canBeSubclass()) {
        // Mark a call as non-polymorphic if the targeted type is guaranteed to be not a subclass.
        x = maybeTightenMethodCall(x);
        x.setCannotBePolymorphic();
        madeChanges();
      } else if (!hasPotentialOverride(instanceType, x.getTarget())) {
        // Mark a call as non-polymorphic if the targeted method is the only possible dispatch.
        x.setCannotBePolymorphic();
        madeChanges();
       }

      return x;
    }

    private boolean hasPotentialOverride(JReferenceType instanceType, JMethod target) {
      if (target.isAbstract()) {
        return true;
      }

      for (JMethod override : target.getOverridingMethods()) {
        JReferenceType overrideType = override.getEnclosingType();
        if (!program.typeOracle.castFailsTrivially(instanceType, overrideType)) {
          // This call is truly polymorphic.
          return true;
        }
      }

      return false;
    }

    private JMethodCall maybeTightenMethodCall(final JMethodCall methodCall) {
      JMethod original = methodCall.getTarget();
      JClassType underlyingType =
          (JClassType) methodCall.getInstance().getType().getUnderlyingType();

      JMethod mostSpecificOverride =
          program.typeOracle.findMostSpecificOverride(underlyingType, original);

      if (mostSpecificOverride == original
          // Never tighten object methods to native implementations. This decision forces
          // the use of the Object trampoline for hashcCode, equals and toString.
          || (original.getEnclosingType().isJavaLangObject()
              && mostSpecificOverride.isJsNative())) {
        return methodCall;
      }
      JMethodCall newCall = new JMethodCall(
          methodCall.getSourceInfo(), methodCall.getInstance(), mostSpecificOverride);
      newCall.addArgs(methodCall.getArgs());
      return newCall;
    }

    @Override
    public void endVisit(JNewInstance x, Context ctx) {
      // Do not tighten new operations.
    }

    @Override
    public boolean visit(JRunAsync x, Context ctx) {
      x.traverseOnSuccess(this);
      return super.visit(x, ctx);
    }
  }

  public static final String NAME = MethodCallTightener.class.getSimpleName();

  @VisibleForTesting
  static OptimizerStats exec(JProgram program) {
    return exec(program, OptimizerContext.NULL_OPTIMIZATION_CONTEXT);
  }

  public static OptimizerStats exec(JProgram program, OptimizerContext optimizerCtx) {
    Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME);
    OptimizerStats stats = new MethodCallTightener(program).execImpl(optimizerCtx);
    optimizerCtx.incOptimizationStep();
    optimizeEvent.end("didChange", "" + stats.didChange());
    JavaAstVerifier.assertProgramIsConsistent(program);
    return stats;
  }

  private final JProgram program;

  private MethodCallTightener(JProgram program) {
    this.program = program;
  }

  private OptimizerStats execImpl(OptimizerContext optimizerCtx) {
    MethodCallTighteningVisitor tightener = new MethodCallTighteningVisitor(optimizerCtx);
    tightener.accept(program);
    return new OptimizerStats(NAME).recordModified(tightener.getNumMods());
  }
}
