/*
 * Copyright (c) 2010, 2016, 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.lookup.Lookup.MH;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import jdk.internal.dynalink.ChainedCallSite;
import jdk.internal.dynalink.DynamicLinker;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.options.Options;


/**
 * Relinkable form of call site.
 */
public class LinkerCallSite extends ChainedCallSite {
    /** Maximum number of arguments passed directly. */
    public static final int ARGLIMIT = 250;

    private static final String PROFILEFILE = Options.getStringProperty("nashorn.profilefile", "NashornProfile.txt");

    private static final MethodHandle INCREASE_MISS_COUNTER = MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, "increaseMissCount", MH.type(Object.class, String.class, Object.class));
    private static final MethodHandle ON_CATCH_INVALIDATION = MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, "onCatchInvalidation", MH.type(ChainedCallSite.class, LinkerCallSite.class));

    private int catchInvalidations;

    LinkerCallSite(final NashornCallSiteDescriptor descriptor) {
        super(descriptor);
        if (Context.DEBUG) {
            LinkerCallSite.count.increment();
        }
    }

    @Override
    protected MethodHandle getPruneCatches() {
        return MH.filterArguments(super.getPruneCatches(), 0, ON_CATCH_INVALIDATION);
    }

    /**
     * Action to perform when a catch guard around a callsite triggers. Increases
     * catch invalidation counter
     * @param callSite callsite
     * @return the callsite, so this can be used as argument filter
     */
    @SuppressWarnings("unused")
    private static ChainedCallSite onCatchInvalidation(final LinkerCallSite callSite) {
        ++callSite.catchInvalidations;
        return callSite;
    }

    /**
     * Get the number of catch invalidations that have happened at this call site so far
     * @param callSiteToken call site token, unique to the callsite.
     * @return number of catch invalidations, i.e. thrown exceptions caught by the linker
     */
    public static int getCatchInvalidationCount(final Object callSiteToken) {
        if (callSiteToken instanceof LinkerCallSite) {
            return ((LinkerCallSite)callSiteToken).catchInvalidations;
        }
        return 0;
    }
    /**
     * Construct a new linker call site.
     * @param name     Name of method.
     * @param type     Method type.
     * @param flags    Call site specific flags.
     * @return New LinkerCallSite.
     */
    static LinkerCallSite newLinkerCallSite(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int flags) {
        final NashornCallSiteDescriptor desc = NashornCallSiteDescriptor.get(lookup, name, type, flags);

        if (desc.isProfile()) {
            return ProfilingLinkerCallSite.newProfilingLinkerCallSite(desc);
        }

        if (desc.isTrace()) {
            return new TracingLinkerCallSite(desc);
        }

        return new LinkerCallSite(desc);
    }

    @Override
    public String toString() {
        return getDescriptor().toString();
    }

    /**
     * Get the descriptor for this callsite
     * @return a {@link NashornCallSiteDescriptor}
     */
    public NashornCallSiteDescriptor getNashornDescriptor() {
        return (NashornCallSiteDescriptor)getDescriptor();
    }

    @Override
    public void relink(final GuardedInvocation invocation, final MethodHandle relink) {
        super.relink(invocation, getDebuggingRelink(relink));
    }

    @Override
    public void resetAndRelink(final GuardedInvocation invocation, final MethodHandle relink) {
        super.resetAndRelink(invocation, getDebuggingRelink(relink));
    }

    private MethodHandle getDebuggingRelink(final MethodHandle relink) {
        if (Context.DEBUG) {
            return MH.filterArguments(relink, 0, getIncreaseMissCounter(relink.type().parameterType(0)));
        }
        return relink;
    }

    private MethodHandle getIncreaseMissCounter(final Class<?> type) {
        final MethodHandle missCounterWithDesc = MH.bindTo(INCREASE_MISS_COUNTER, getDescriptor().getName() + " @ " + getScriptLocation());
        if (type == Object.class) {
            return missCounterWithDesc;
        }
        return MH.asType(missCounterWithDesc, missCounterWithDesc.type().changeParameterType(0, type).changeReturnType(type));
    }

    private static String getScriptLocation() {
        final StackTraceElement caller = DynamicLinker.getLinkedCallSiteLocation();
        return caller == null ? "unknown location" : (caller.getFileName() + ":" + caller.getLineNumber());
    }

    /**
     * Instrumentation - increase the miss count when a callsite misses. Used as filter
     * @param desc descriptor for table entry
     * @param self self reference
     * @return self reference
     */
    public static Object increaseMissCount(final String desc, final Object self) {
        missCount.increment();
        if (r.nextInt(100) < missSamplingPercentage) {
            final AtomicInteger i = missCounts.get(desc);
            if (i == null) {
                missCounts.put(desc, new AtomicInteger(1));
            } else {
                i.incrementAndGet();
            }
        }
        return self;
    }

    /*
     * Debugging call sites.
     */

    private static class ProfilingLinkerCallSite extends LinkerCallSite {
        /** List of all profiled call sites. */
        private static LinkedList<ProfilingLinkerCallSite> profileCallSites = null;

        /** Start time when entered at zero depth. */
        private long startTime;

        /** Depth of nested calls. */
        private int depth;

        /** Total time spent in this call site. */
        private long totalTime;

        /** Total number of times call site entered. */
        private long hitCount;

        private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

        private static final MethodHandle PROFILEENTRY    = MH.findVirtual(LOOKUP, ProfilingLinkerCallSite.class, "profileEntry",    MH.type(Object.class, Object.class));
        private static final MethodHandle PROFILEEXIT     = MH.findVirtual(LOOKUP, ProfilingLinkerCallSite.class, "profileExit",     MH.type(Object.class, Object.class));
        private static final MethodHandle PROFILEVOIDEXIT = MH.findVirtual(LOOKUP, ProfilingLinkerCallSite.class, "profileVoidExit", MH.type(void.class));

        /*
         * Constructor
         */

        ProfilingLinkerCallSite(final NashornCallSiteDescriptor desc) {
           super(desc);
        }

        public static ProfilingLinkerCallSite newProfilingLinkerCallSite(final NashornCallSiteDescriptor desc) {
            if (profileCallSites == null) {
                profileCallSites = new LinkedList<>();

                final Thread profileDumperThread = new Thread(new ProfileDumper());
                Runtime.getRuntime().addShutdownHook(profileDumperThread);
            }

            final ProfilingLinkerCallSite callSite = new ProfilingLinkerCallSite(desc);
            profileCallSites.add(callSite);

            return callSite;
        }

        @Override
        public void setTarget(final MethodHandle newTarget) {
            final MethodType type   = type();
            final boolean    isVoid = type.returnType() == void.class;
            final Class<?> newSelfType = newTarget.type().parameterType(0);

            MethodHandle selfFilter = MH.bindTo(PROFILEENTRY, this);
            if (newSelfType != Object.class) {
                // new target uses a more precise 'self' type than Object.class. We need to
                // convert the filter type. Note that the profileEntry method returns "self"
                // argument "as is" and so the cast introduced will succeed for any type.
                MethodType selfFilterType = MethodType.methodType(newSelfType, newSelfType);
                selfFilter = selfFilter.asType(selfFilterType);
            }

            MethodHandle methodHandle = MH.filterArguments(newTarget, 0, selfFilter);

            if (isVoid) {
                methodHandle = MH.filterReturnValue(methodHandle, MH.bindTo(PROFILEVOIDEXIT, this));
            } else {
                final MethodType filter = MH.type(type.returnType(), type.returnType());
                methodHandle = MH.filterReturnValue(methodHandle, MH.asType(MH.bindTo(PROFILEEXIT, this), filter));
            }

            super.setTarget(methodHandle);
        }

        /**
         * Start the clock for a profile entry and increase depth
         * @param self argument to filter
         * @return preserved argument
         */
        @SuppressWarnings("unused")
        public Object profileEntry(final Object self) {
            if (depth == 0) {
                startTime = System.nanoTime();
            }

            depth++;
            hitCount++;

            return self;
        }

        /**
         * Decrease depth and stop the clock for a profile entry
         * @param result return value to filter
         * @return preserved argument
         */
        @SuppressWarnings("unused")
        public Object profileExit(final Object result) {
            depth--;

            if (depth == 0) {
                totalTime += System.nanoTime() - startTime;
            }

            return result;
        }

        /**
         * Decrease depth without return value filter
         */
        @SuppressWarnings("unused")
        public void profileVoidExit() {
            depth--;

            if (depth == 0) {
                totalTime += System.nanoTime() - startTime;
            }
        }

        static class ProfileDumper implements Runnable {
            @Override
            public void run() {
                PrintWriter out    = null;
                boolean fileOutput = false;

                try {
                    try {
                        out = new PrintWriter(new FileOutputStream(PROFILEFILE));
                        fileOutput = true;
                    } catch (final FileNotFoundException e) {
                        out = Context.getCurrentErr();
                    }

                    dump(out);
                } finally {
                    if (out != null && fileOutput) {
                        out.close();
                    }
                }
            }

            private static void dump(final PrintWriter out) {
                int index = 0;
                for (final ProfilingLinkerCallSite callSite : profileCallSites) {
                   out.println("" + (index++) + '\t' +
                                  callSite.getDescriptor().getName() + '\t' +
                                  callSite.totalTime + '\t' +
                                  callSite.hitCount);
                }
            }
        }
    }

    /**
     * Debug subclass for LinkerCallSite that allows tracing
     */
    private static class TracingLinkerCallSite extends LinkerCallSite {
        private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

        private static final MethodHandle TRACEOBJECT = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceObject", MH.type(Object.class, MethodHandle.class, Object[].class));
        private static final MethodHandle TRACEVOID   = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceVoid", MH.type(void.class, MethodHandle.class, Object[].class));
        private static final MethodHandle TRACEMISS   = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceMiss", MH.type(void.class, String.class, Object[].class));

        TracingLinkerCallSite(final NashornCallSiteDescriptor desc) {
           super(desc);
        }

        @Override
        public void setTarget(final MethodHandle newTarget) {
            if (!getNashornDescriptor().isTraceEnterExit()) {
                super.setTarget(newTarget);
                return;
            }

            final MethodType type = type();
            final boolean isVoid = type.returnType() == void.class;

            MethodHandle traceMethodHandle = isVoid ? TRACEVOID : TRACEOBJECT;
            traceMethodHandle = MH.bindTo(traceMethodHandle, this);
            traceMethodHandle = MH.bindTo(traceMethodHandle, newTarget);
            traceMethodHandle = MH.asCollector(traceMethodHandle, Object[].class, type.parameterCount());
            traceMethodHandle = MH.asType(traceMethodHandle, type);

            super.setTarget(traceMethodHandle);
        }

        @Override
        public void initialize(final MethodHandle relinkAndInvoke) {
            super.initialize(getFallbackLoggingRelink(relinkAndInvoke));
        }

        @Override
        public void relink(final GuardedInvocation invocation, final MethodHandle relink) {
            super.relink(invocation, getFallbackLoggingRelink(relink));
        }

        @Override
        public void resetAndRelink(final GuardedInvocation invocation, final MethodHandle relink) {
            super.resetAndRelink(invocation, getFallbackLoggingRelink(relink));
        }

        private MethodHandle getFallbackLoggingRelink(final MethodHandle relink) {
            if (!getNashornDescriptor().isTraceMisses()) {
                // If we aren't tracing misses, just return relink as-is
                return relink;
            }
            final MethodType type = relink.type();
            return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.insertArguments(TRACEMISS, 0, this, "MISS " + getScriptLocation() + " "), Object[].class, type.parameterCount()), type.changeReturnType(void.class)));
        }

        private void printObject(final PrintWriter out, final Object arg) {
            if (!getNashornDescriptor().isTraceObjects()) {
                out.print((arg instanceof ScriptObject) ? "ScriptObject" : arg);
                return;
            }

            if (arg instanceof ScriptObject) {
                final ScriptObject object = (ScriptObject)arg;

                boolean isFirst = true;
                final Set<Object> keySet = object.keySet();

                if (keySet.isEmpty()) {
                    out.print(ScriptRuntime.safeToString(arg));
                } else {
                    out.print("{ ");

                    for (final Object key : keySet) {
                        if (!isFirst) {
                            out.print(", ");
                        }

                        out.print(key);
                        out.print(":");

                        final Object value = object.get(key);

                        if (value instanceof ScriptObject) {
                            out.print("...");
                        } else {
                            printObject(out, value);
                        }

                        isFirst = false;
                    }

                    out.print(" }");
                }
             } else {
                out.print(ScriptRuntime.safeToString(arg));
            }
        }

        private void tracePrint(final PrintWriter out, final String tag, final Object[] args, final Object result) {
            //boolean isVoid = type().returnType() == void.class;
            out.print(Debug.id(this) + " TAG " + tag);
            out.print(getDescriptor().getName() + "(");

            if (args.length > 0) {
                printObject(out, args[0]);
                for (int i = 1; i < args.length; i++) {
                    final Object arg = args[i];
                    out.print(", ");

                    if (!(arg instanceof ScriptObject && ((ScriptObject)arg).isScope())) {
                        printObject(out, arg);
                    } else {
                        out.print("SCOPE");
                    }
                }
            }

            out.print(")");

            if (tag.equals("EXIT  ")) {
                out.print(" --> ");
                printObject(out, result);
            }

            out.println();
        }

        /**
         * Trace event. Wrap an invocation with a return value
         *
         * @param mh     invocation handle
         * @param args   arguments to call
         *
         * @return return value from invocation
         *
         * @throws Throwable if invocation fails or throws exception/error
         */
        @SuppressWarnings("unused")
        public Object traceObject(final MethodHandle mh, final Object... args) throws Throwable {
            final PrintWriter out = Context.getCurrentErr();
            tracePrint(out, "ENTER ", args, null);
            final Object result = mh.invokeWithArguments(args);
            tracePrint(out, "EXIT  ", args, result);

            return result;
        }

        /**
         * Trace event. Wrap an invocation that returns void
         *
         * @param mh     invocation handle
         * @param args   arguments to call
         *
         * @throws Throwable if invocation fails or throws exception/error
         */
        @SuppressWarnings("unused")
        public void traceVoid(final MethodHandle mh, final Object... args) throws Throwable {
            final PrintWriter out = Context.getCurrentErr();
            tracePrint(out, "ENTER ", args, null);
            mh.invokeWithArguments(args);
            tracePrint(out, "EXIT  ", args, null);
        }

        /**
         * Tracer function that logs a callsite miss
         *
         * @param desc callsite descriptor string
         * @param args arguments to function
         *
         * @throws Throwable if invocation fails or throws exception/error
         */
        @SuppressWarnings("unused")
        public void traceMiss(final String desc, final Object... args) throws Throwable {
            tracePrint(Context.getCurrentErr(), desc, args, null);
        }
    }

    // counters updated in debug mode
    private static LongAdder count;
    private static final HashMap<String, AtomicInteger> missCounts = new HashMap<>();
    private static LongAdder missCount;
    private static final Random r = new Random();
    private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1);

    static {
        if (Context.DEBUG) {
            count = new LongAdder();
            missCount = new LongAdder();
        }
    }

    @Override
    protected int getMaxChainLength() {
        return 8;
    }

    /**
     * Get the callsite count
     * @return the count
     */
    public static long getCount() {
        return count.longValue();
    }

    /**
     * Get the callsite miss count
     * @return the missCount
     */
    public static long getMissCount() {
        return missCount.longValue();
    }

    /**
     * Get given miss sampling percentage for sampler. Default is 1%. Specified with -Dnashorn.tcs.miss.samplePercent=x
     * @return miss sampling percentage
     */
    public static int getMissSamplingPercentage() {
        return missSamplingPercentage;
    }

    /**
     * Dump the miss counts collected so far to a given output stream
     * @param out print stream
     */
    public static void getMissCounts(final PrintWriter out) {
        final ArrayList<Entry<String, AtomicInteger>> entries = new ArrayList<>(missCounts.entrySet());

        Collections.sort(entries, new Comparator<Map.Entry<String, AtomicInteger>>() {
            @Override
            public int compare(final Entry<String, AtomicInteger> o1, final Entry<String, AtomicInteger> o2) {
                return o2.getValue().get() - o1.getValue().get();
            }
        });

        for (final Entry<String, AtomicInteger> entry : entries) {
            out.println("  " + entry.getKey() + "\t" + entry.getValue().get());
        }
    }

}
