/*
 * Copyright (c) 2008, 2009, 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 sun.dyn;

import sun.dyn.util.VerifyType;
import sun.dyn.util.Wrapper;
import java.dyn.*;
import java.util.List;
import sun.dyn.MethodHandleNatives.Constants;
import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP;
import static sun.dyn.MemberName.newIllegalArgumentException;

/**
 * The flavor of method handle which emulates an invoke instruction
 * on a predetermined argument.  The JVM dispatches to the correct method
 * when the handle is created, not when it is invoked.
 * @author jrose
 */
public class BoundMethodHandle extends MethodHandle {
    //MethodHandle vmtarget;           // next BMH or final DMH or methodOop
    private final Object argument;     // argument to insert
    private final int    vmargslot;    // position at which it is inserted

    private static final Access IMPL_TOKEN = Access.getToken();
    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);

    // Constructors in this class *must* be package scoped or private.
    // Exception:  JavaMethodHandle constructors are protected.
    // (The link between JMH and BMH is temporary.)

    /** Bind a direct MH to its receiver (or first ref. argument).
     *  The JVM will pre-dispatch the MH if it is not already static.
     */
    BoundMethodHandle(DirectMethodHandle mh, Object argument) {
        super(Access.TOKEN, mh.type().dropParameterTypes(0, 1));
        // check the type now, once for all:
        this.argument = checkReferenceArgument(argument, mh, 0);
        this.vmargslot = this.type().parameterSlotCount();
        if (MethodHandleNatives.JVM_SUPPORT) {
            this.vmtarget = null;  // maybe updated by JVM
            MethodHandleNatives.init(this, mh, 0);
        } else {
            this.vmtarget = mh;
        }
    }

    /** Insert an argument into an arbitrary method handle.
     *  If argnum is zero, inserts the first argument, etc.
     *  The argument type must be a reference.
     */
    BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
        this(mh.type().dropParameterTypes(argnum, argnum+1),
             mh, argument, argnum);
    }

    /** Insert an argument into an arbitrary method handle.
     *  If argnum is zero, inserts the first argument, etc.
     */
    BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
        super(Access.TOKEN, type);
        if (mh.type().parameterType(argnum).isPrimitive())
            this.argument = bindPrimitiveArgument(argument, mh, argnum);
        else {
            this.argument = checkReferenceArgument(argument, mh, argnum);
        }
        this.vmargslot = type.parameterSlotDepth(argnum);
        initTarget(mh, argnum);
    }

    private void initTarget(MethodHandle mh, int argnum) {
        if (MethodHandleNatives.JVM_SUPPORT) {
            this.vmtarget = null; // maybe updated by JVM
            MethodHandleNatives.init(this, mh, argnum);
        } else {
            this.vmtarget = mh;
        }
    }

    /** For the AdapterMethodHandle subclass.
     */
    BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
        super(Access.TOKEN, type);
        this.argument = argument;
        this.vmargslot = vmargslot;
        assert(this.getClass() == AdapterMethodHandle.class);
    }

    /** Initialize the current object as a Java method handle, binding it
     *  as the first argument of the method handle {@code entryPoint}.
     *  The invocation type of the resulting method handle will be the
     *  same as {@code entryPoint},  except that the first argument
     *  type will be dropped.
     */
    protected BoundMethodHandle(MethodHandle entryPoint) {
        super(Access.TOKEN, entryPoint.type().dropParameterTypes(0, 1));
        this.argument = this; // kludge; get rid of
        this.vmargslot = this.type().parameterSlotDepth(0);
        initTarget(entryPoint, 0);
        assert(this instanceof JavaMethodHandle);
    }

    /** Initialize the current object as a Java method handle.
     */
    protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) {
        super(Access.TOKEN, null);
        MethodHandle entryPoint
                = findJavaMethodHandleEntryPoint(this.getClass(),
                                        entryPointName, type, matchArity);
        MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1));
        this.argument = this; // kludge; get rid of
        this.vmargslot = this.type().parameterSlotDepth(0);
        initTarget(entryPoint, 0);
        assert(this instanceof JavaMethodHandle);
    }

    private static
    MethodHandle findJavaMethodHandleEntryPoint(Class<?> caller,
                                                String name,
                                                MethodType type,
                                                boolean matchArity) {
        if (matchArity)  type.getClass();  // elicit NPE
        List<MemberName> methods = IMPL_NAMES.getMethods(caller, true, name, null, caller);
        MethodType foundType = null;
        MemberName foundMethod = null;
        for (MemberName method : methods) {
            MethodType mtype = method.getMethodType();
            if (type != null && type.parameterCount() != mtype.parameterCount())
                continue;
            else if (foundType == null)
                foundType = mtype;
            else if (foundType != mtype)
                throw newIllegalArgumentException("more than one method named "+name+" in "+caller.getName());
            // discard overrides
            if (foundMethod == null)
                foundMethod = method;
            else if (foundMethod.getDeclaringClass().isAssignableFrom(method.getDeclaringClass()))
                foundMethod = method;
        }
        if (foundMethod == null)
            throw newIllegalArgumentException("no method named "+name+" in "+caller.getName());
        MethodHandle entryPoint = MethodHandleImpl.findMethod(IMPL_TOKEN, foundMethod, true, caller);
        if (type != null) {
            MethodType epType = type.insertParameterTypes(0, entryPoint.type().parameterType(0));
            entryPoint = MethodHandles.convertArguments(entryPoint, epType);
        }
        return entryPoint;
    }

    /** Make sure the given {@code argument} can be used as {@code argnum}-th
     *  parameter of the given method handle {@code mh}, which must be a reference.
     *  <p>
     *  If this fails, throw a suitable {@code WrongMethodTypeException},
     *  which will prevent the creation of an illegally typed bound
     *  method handle.
     */
    final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
        Class<?> ptype = mh.type().parameterType(argnum);
        if (ptype.isPrimitive()) {
            // fail
        } else if (argument == null) {
            return null;
        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
            return argument;
        }
        throw badBoundArgumentException(argument, mh, argnum);
    }

    /** Make sure the given {@code argument} can be used as {@code argnum}-th
     *  parameter of the given method handle {@code mh}, which must be a primitive.
     *  <p>
     *  If this fails, throw a suitable {@code WrongMethodTypeException},
     *  which will prevent the creation of an illegally typed bound
     *  method handle.
     */
    final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
        Class<?> ptype = mh.type().parameterType(argnum);
        Wrapper  wrap = Wrapper.forPrimitiveType(ptype);
        Object   zero  = wrap.zero();
        if (zero == null) {
            // fail
        } else if (argument == null) {
            if (ptype != int.class && wrap.isSubwordOrInt())
                return Integer.valueOf(0);
            else
                return zero;
        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
            if (ptype != int.class && wrap.isSubwordOrInt())
                return Wrapper.INT.wrap(argument);
            else
                return argument;
        }
        throw badBoundArgumentException(argument, mh, argnum);
    }

    final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
        String atype = (argument == null) ? "null" : argument.getClass().toString();
        return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
    }

    @Override
    public String toString() {
        MethodHandle mh = this;
        while (mh instanceof BoundMethodHandle) {
            Object info = MethodHandleNatives.getTargetInfo(mh);
            if (info instanceof MethodHandle) {
                mh = (MethodHandle) info;
            } else {
                String name = null;
                if (info instanceof MemberName)
                    name = ((MemberName)info).getName();
                if (name != null)
                    return name;
                else
                    return super.toString(); // <unknown>, probably
            }
            assert(mh != this);
            if (mh instanceof JavaMethodHandle)
                break;  // access JMH.toString(), not BMH.toString()
        }
        return mh.toString();
    }
}
