/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.runtime.linker;

import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.DynamicLinker;
import jdk.internal.dynalink.DynamicLinkerFactory;
import jdk.internal.dynalink.GuardedInvocationFilter;
import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.options.Options;

/**
 * This class houses bootstrap method for invokedynamic instructions generated by compiler.
 */
public final class Bootstrap {
    /** Reference to the seed boostrap function */
    public static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "bootstrap", CallSite.class, Lookup.class, String.class, MethodType.class, int.class);

    private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();

    private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED);

    /**
     * The default dynalink relink threshold for megamorphism is 8. In the case
     * of object fields only, it is fine. However, with dual fields, in order to get
     * performance on benchmarks with a lot of object instantiation and then field
     * reassignment, it can take slightly more relinks to become stable with type
     * changes swapping out an entire property map and making a map guard fail.
     * Since we need to set this value statically it must work with possibly changing
     * optimistic types and dual fields settings. A higher value does not seem to have
     * any other negative performance implication when running with object-only fields,
     * so we choose a higher value here.
     *
     * See for example octane.gbemu, run with --log=fields:warning to study
     * megamorphic behavior
     */
    private static final int NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD = 16;

    // do not create me!!
    private Bootstrap() {
    }

    private static final DynamicLinker dynamicLinker;
    static {
        final DynamicLinkerFactory factory = new DynamicLinkerFactory();
        final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker();
        factory.setPrioritizedLinkers(
            new NashornLinker(),
            new NashornPrimitiveLinker(),
            new NashornStaticClassLinker(),
            new BoundCallableLinker(),
            new JavaSuperAdapterLinker(),
            new JSObjectLinker(nashornBeansLinker),
            new BrowserJSObjectLinker(nashornBeansLinker),
            new ReflectionCheckLinker());
        factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker());
        factory.setSyncOnRelink(true);
        factory.setPrelinkFilter(new GuardedInvocationFilter() {
            @Override
            public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) {
                final CallSiteDescriptor desc = request.getCallSiteDescriptor();
                return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType());
            }
        });
        factory.setAutoConversionStrategy(new MethodTypeConversionStrategy() {
            @Override
            public MethodHandle asType(final MethodHandle target, final MethodType newType) {
                return unboxReturnType(target, newType);
            }
        });
        factory.setInternalObjectsFilter(NashornBeansLinker.createHiddenObjectFilter());
        final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD);
        if (relinkThreshold > -1) {
            factory.setUnstableRelinkThreshold(relinkThreshold);
        }

        // Linkers for any additional language runtimes deployed alongside Nashorn will be picked up by the factory.
        factory.setClassLoader(Bootstrap.class.getClassLoader());

        dynamicLinker = factory.createLinker();
    }

    /**
     * Returns if the given object is a "callable"
     * @param obj object to be checked for callability
     * @return true if the obj is callable
     */
    public static boolean isCallable(final Object obj) {
        if (obj == ScriptRuntime.UNDEFINED || obj == null) {
            return false;
        }

        return obj instanceof ScriptFunction ||
            isJSObjectFunction(obj) ||
            BeansLinker.isDynamicMethod(obj) ||
            obj instanceof BoundCallable ||
            isFunctionalInterfaceObject(obj) ||
            obj instanceof StaticClass;
    }

    /**
     * Returns true if the given object is a strict callable
     * @param callable the callable object to be checked for strictness
     * @return true if the obj is a strict callable, false if it is a non-strict callable.
     * @throws ECMAException with {@code TypeError} if the object is not a callable.
     */
    public static boolean isStrictCallable(final Object callable) {
        if (callable instanceof ScriptFunction) {
            return ((ScriptFunction)callable).isStrict();
        } else if (isJSObjectFunction(callable)) {
            return ((JSObject)callable).isStrictFunction();
        } else if (callable instanceof BoundCallable) {
            return isStrictCallable(((BoundCallable)callable).getCallable());
        } else if (BeansLinker.isDynamicMethod(callable) ||
                callable instanceof StaticClass ||
                isFunctionalInterfaceObject(callable)) {
            return false;
        }
        throw notFunction(callable);
    }

    private static ECMAException notFunction(final Object obj) {
        return typeError("not.a.function", ScriptRuntime.safeToString(obj));
    }

    private static boolean isJSObjectFunction(final Object obj) {
        return obj instanceof JSObject && ((JSObject)obj).isFunction();
    }

    /**
     * Returns if the given object is a dynalink Dynamic method
     * @param obj object to be checked
     * @return true if the obj is a dynamic method
     */
    public static boolean isDynamicMethod(final Object obj) {
        return BeansLinker.isDynamicMethod(obj instanceof BoundCallable ? ((BoundCallable)obj).getCallable() : obj);
    }

    /**
     * Returns if the given object is an instance of an interface annotated with
     * java.lang.FunctionalInterface
     * @param obj object to be checked
     * @return true if the obj is an instance of @FunctionalInterface interface
     */
    public static boolean isFunctionalInterfaceObject(final Object obj) {
        return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null);
    }

    /**
     * Create a call site and link it for Nashorn. This version of the method conforms to the invokedynamic bootstrap
     * method expected signature and is referenced from Nashorn generated bytecode as the bootstrap method for all
     * invokedynamic instructions.
     * @param lookup MethodHandle lookup. Ignored as Nashorn only uses public lookup.
     * @param opDesc Dynalink dynamic operation descriptor.
     * @param type   Method type.
     * @param flags  flags for call type, trace/profile etc.
     * @return CallSite with MethodHandle to appropriate method or null if not found.
     */
    public static CallSite bootstrap(final Lookup lookup, final String opDesc, final MethodType type, final int flags) {
        return dynamicLinker.link(LinkerCallSite.newLinkerCallSite(lookup, opDesc, type, flags));
    }

    /**
     * Boostrapper for math calls that may overflow
     * @param lookup         lookup
     * @param name           name of operation
     * @param type           method type
     * @param programPoint   program point to bind to callsite
     *
     * @return callsite for a math intrinsic node
     */
    public static CallSite mathBootstrap(final Lookup lookup, final String name, final MethodType type, final int programPoint) {
        final MethodHandle mh;
        switch (name) {
        case "iadd":
            mh = JSType.ADD_EXACT.methodHandle();
            break;
        case "isub":
            mh = JSType.SUB_EXACT.methodHandle();
            break;
        case "imul":
            mh = JSType.MUL_EXACT.methodHandle();
            break;
        case "idiv":
            mh = JSType.DIV_EXACT.methodHandle();
            break;
        case "irem":
            mh = JSType.REM_EXACT.methodHandle();
            break;
        case "ineg":
            mh = JSType.NEGATE_EXACT.methodHandle();
            break;
        default:
            throw new AssertionError("unsupported math intrinsic");
        }
        return new ConstantCallSite(MH.insertArguments(mh, mh.type().parameterCount() - 1, programPoint));
    }

    /**
     * Returns a dynamic invoker for a specified dynamic operation using the public lookup. You can use this method to
     * create a method handle that when invoked acts completely as if it were a Nashorn-linked call site. An overview of
     * available dynamic operations can be found in the
     * <a href="https://github.com/szegedi/dynalink/wiki/User-Guide-0.6">Dynalink User Guide</a>, but we'll show few
     * examples here:
     * <ul>
     *   <li>Get a named property with fixed name:
     *     <pre>
     * MethodHandle getColor = Boostrap.createDynamicInvoker("dyn:getProp:color", Object.class, Object.class);
     * Object obj = ...; // somehow obtain the object
     * Object color = getColor.invokeExact(obj);
     *     </pre>
     *   </li>
     *   <li>Get a named property with variable name:
     *     <pre>
     * MethodHandle getProperty = Boostrap.createDynamicInvoker("dyn:getElem", Object.class, Object.class, String.class);
     * Object obj = ...; // somehow obtain the object
     * Object color = getProperty.invokeExact(obj, "color");
     * Object shape = getProperty.invokeExact(obj, "shape");
     * MethodHandle getNumProperty = Boostrap.createDynamicInvoker("dyn:getElem", Object.class, Object.class, int.class);
     * Object elem42 = getNumProperty.invokeExact(obj, 42);
     *     </pre>
     *   </li>
     *   <li>Set a named property with fixed name:
     *     <pre>
     * MethodHandle setColor = Boostrap.createDynamicInvoker("dyn:setProp:color", void.class, Object.class, Object.class);
     * Object obj = ...; // somehow obtain the object
     * setColor.invokeExact(obj, Color.BLUE);
     *     </pre>
     *   </li>
     *   <li>Set a property with variable name:
     *     <pre>
     * MethodHandle setProperty = Boostrap.createDynamicInvoker("dyn:setElem", void.class, Object.class, String.class, Object.class);
     * Object obj = ...; // somehow obtain the object
     * setProperty.invokeExact(obj, "color", Color.BLUE);
     * setProperty.invokeExact(obj, "shape", Shape.CIRCLE);
     *     </pre>
     *   </li>
     *   <li>Call a function on an object; two-step variant. This is the actual variant used by Nashorn-generated code:
     *     <pre>
     * MethodHandle findFooFunction = Boostrap.createDynamicInvoker("dyn:getMethod:foo", Object.class, Object.class);
     * Object obj = ...; // somehow obtain the object
     * Object foo_fn = findFooFunction.invokeExact(obj);
     * MethodHandle callFunctionWithTwoArgs = Boostrap.createDynamicInvoker("dyn:call", Object.class, Object.class, Object.class, Object.class, Object.class);
     * // Note: "call" operation takes a function, then a "this" value, then the arguments:
     * Object foo_retval = callFunctionWithTwoArgs.invokeExact(foo_fn, obj, arg1, arg2);
     *     </pre>
     *   </li>
     *   <li>Call a function on an object; single-step variant. Although Nashorn doesn't use this variant and never
     *   emits any INVOKEDYNAMIC instructions with {@code dyn:getMethod}, it still supports this standard Dynalink
     *   operation:
     *     <pre>
     * MethodHandle callFunctionFooWithTwoArgs = Boostrap.createDynamicInvoker("dyn:callMethod:foo", Object.class, Object.class, Object.class, Object.class);
     * Object obj = ...; // somehow obtain the object
     * Object foo_retval = callFunctionFooWithTwoArgs.invokeExact(obj, arg1, arg2);
     *     </pre>
     *   </li>
     * </ul>
     * Few additional remarks:
     * <ul>
     * <li>Just as Nashorn works with any Java object, the invokers returned from this method can also be applied to
     * arbitrary Java objects in addition to Nashorn JavaScript objects.</li>
     * <li>For invoking a named function on an object, you can also use the {@link InvokeByName} convenience class.</li>
     * <li>For Nashorn objects {@code getElem}, {@code getProp}, and {@code getMethod} are handled almost identically,
     * since JavaScript doesn't distinguish between different kinds of properties on an object. Either can be used with
     * fixed property name or a variable property name. The only significant difference is handling of missing
     * properties: {@code getMethod} for a missing member will link to a potential invocation of
     * {@code __noSuchMethod__} on the object, {@code getProp} for a missing member will link to a potential invocation
     * of {@code __noSuchProperty__}, while {@code getElem} for a missing member will link to an empty getter.</li>
     * <li>In similar vein, {@code setElem} and {@code setProp} are handled identically on Nashorn objects.</li>
     * <li>There's no rule that the variable property identifier has to be a {@code String} for {@code getProp/setProp}
     * and {@code int} for {@code getElem/setElem}. You can declare their type to be {@code int}, {@code double},
     * {@code Object}, and so on regardless of the kind of the operation.</li>
     * <li>You can be as specific in parameter types as you want. E.g. if you know that the receiver of the operation
     * will always be {@code ScriptObject}, you can pass {@code ScriptObject.class} as its parameter type. If you happen
     * to link to a method that expects different types, (you can use these invokers on POJOs too, after all, and end up
     * linking with their methods that have strongly-typed signatures), all necessary conversions allowed by either Java
     * or JavaScript will be applied: if invoked methods specify either primitive or wrapped Java numeric types, or
     * {@code String} or {@code boolean/Boolean}, then the parameters might be subjected to standard ECMAScript
     * {@code ToNumber}, {@code ToString}, and {@code ToBoolean} conversion, respectively. Less obviously, if the
     * expected parameter type is a SAM type, and you pass a JavaScript function, a proxy object implementing the SAM
     * type and delegating to the function will be passed. Linkage can often be optimized when linkers have more
     * specific type information than "everything can be an object".</li>
     * <li>You can also be as specific in return types as you want. For return types any necessary type conversion
     * available in either Java or JavaScript will be automatically applied, similar to the process described for
     * parameters, only in reverse direction:  if you specify any either primitive or wrapped Java numeric type, or
     * {@code String} or {@code boolean/Boolean}, then the return values will be subjected to standard ECMAScript
     * {@code ToNumber}, {@code ToString}, and {@code ToBoolean} conversion, respectively. Less obviously, if the return
     * type is a SAM type, and the return value is a JavaScript function, a proxy object implementing the SAM type and
     * delegating to the function will be returned.</li>
     * </ul>
     * @param opDesc Dynalink dynamic operation descriptor.
     * @param rtype the return type for the operation
     * @param ptypes the parameter types for the operation
     * @return MethodHandle for invoking the operation.
     */
    public static MethodHandle createDynamicInvoker(final String opDesc, final Class<?> rtype, final Class<?>... ptypes) {
        return createDynamicInvoker(opDesc, MethodType.methodType(rtype, ptypes));
    }

    /**
     * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
     * {@link #createDynamicInvoker(String, Class, Class...)} but with an additional parameter to
     * set the call site flags of the dynamic invoker.
     * @param opDesc Dynalink dynamic operation descriptor.
     * @param flags the call site flags for the operation
     * @param rtype the return type for the operation
     * @param ptypes the parameter types for the operation
     * @return MethodHandle for invoking the operation.
     */
    public static MethodHandle createDynamicInvoker(final String opDesc, final int flags, final Class<?> rtype, final Class<?>... ptypes) {
        return bootstrap(MethodHandles.publicLookup(), opDesc, MethodType.methodType(rtype, ptypes), flags).dynamicInvoker();
    }

    /**
     * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
     * {@link #createDynamicInvoker(String, Class, Class...)} but with return and parameter types composed into a
     * method type in the signature. See the discussion of that method for details.
     * @param opDesc Dynalink dynamic operation descriptor.
     * @param type the method type for the operation
     * @return MethodHandle for invoking the operation.
     */
    public static MethodHandle createDynamicInvoker(final String opDesc, final MethodType type) {
        return bootstrap(MethodHandles.publicLookup(), opDesc, type, 0).dynamicInvoker();
    }

    /**
     * Binds any object Nashorn can use as a [[Callable]] to a receiver and optionally arguments.
     * @param callable the callable to bind
     * @param boundThis the bound "this" value.
     * @param boundArgs the bound arguments. Can be either null or empty array to signify no arguments are bound.
     * @return a bound callable.
     * @throws ECMAException with {@code TypeError} if the object is not a callable.
     */
    public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
        if (callable instanceof ScriptFunction) {
            return ((ScriptFunction)callable).createBound(boundThis, boundArgs);
        } else if (callable instanceof BoundCallable) {
            return ((BoundCallable)callable).bind(boundArgs);
        } else if (isCallable(callable)) {
            return new BoundCallable(callable, boundThis, boundArgs);
        }
        throw notFunction(callable);
    }

    /**
     * Creates a super-adapter for an adapter, that is, an adapter to the adapter that allows invocation of superclass
     * methods on it.
     * @param adapter the original adapter
     * @return a new adapter that can be used to invoke super methods on the original adapter.
     */
    public static Object createSuperAdapter(final Object adapter) {
        return new JavaSuperAdapter(adapter);
    }

    /**
     * If the given class is a reflection-specific class (anything in {@code java.lang.reflect} and
     * {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is
     * a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}.
     * @param clazz the class being tested
     * @param isStatic is access checked for static members (or instance members)
     */
    public static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
        ReflectionCheckLinker.checkReflectionAccess(clazz, isStatic);
    }

    /**
     * Returns the Nashorn's internally used dynamic linker's services object. Note that in code that is processing a
     * linking request, you will normally use the {@code LinkerServices} object passed by whatever top-level linker
     * invoked the linking (if the call site is in Nashorn-generated code, you'll get this object anyway). You should
     * only resort to retrieving a linker services object using this method when you need some linker services (e.g.
     * type converter method handles) outside of a code path that is linking a call site.
     * @return Nashorn's internal dynamic linker's services object.
     */
    public static LinkerServices getLinkerServices() {
        return dynamicLinker.getLinkerServices();
    }

    /**
     * Takes a guarded invocation, and ensures its method and guard conform to the type of the call descriptor, using
     * all type conversions allowed by the linker's services. This method is used by Nashorn's linkers as a last step
     * before returning guarded invocations. Most of the code used to produce the guarded invocations does not make an
     * effort to coordinate types of the methods, and so a final type adjustment before a guarded invocation is returned
     * to the aggregating linker is the responsibility of the linkers themselves.
     * @param inv the guarded invocation that needs to be type-converted. Can be null.
     * @param linkerServices the linker services object providing the type conversions.
     * @param desc the call site descriptor to whose method type the invocation needs to conform.
     * @return the type-converted guarded invocation. If input is null, null is returned. If the input invocation
     * already conforms to the requested type, it is returned unchanged.
     */
    static GuardedInvocation asTypeSafeReturn(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
        return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType());
    }

    /**
     * Adapts the return type of the method handle with {@code explicitCastArguments} when it is an unboxing
     * conversion. This will ensure that nulls are unwrapped to false or 0.
     * @param target the target method handle
     * @param newType the desired new type. Note that this method does not adapt the method handle completely to the
     * new type, it only adapts the return type; this is allowed as per
     * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is what this method
     * is used for.
     * @return the method handle with adapted return type, if it required an unboxing conversion.
     */
    private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) {
        final MethodType targetType = target.type();
        final Class<?> oldReturnType = targetType.returnType();
        final Class<?> newReturnType = newType.returnType();
        if (TypeUtilities.isWrapperType(oldReturnType)) {
            if (newReturnType.isPrimitive()) {
                // The contract of setAutoConversionStrategy is such that the difference between newType and targetType
                // can only be JLS method invocation conversions.
                assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType);
                return MethodHandles.explicitCastArguments(target, targetType.changeReturnType(newReturnType));
            }
        } else if (oldReturnType == void.class && newReturnType == Object.class) {
            return MethodHandles.filterReturnValue(target, VOID_TO_OBJECT);
        }
        return target;
    }
}
