/*
 * Copyright 2016 Google Inc.
 *
 * 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.  Google designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Google 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.
 */

package java.lang.invoke;

import dalvik.system.EmulatedStackFrame;
import dalvik.system.EmulatedStackFrame.Range;
import dalvik.system.EmulatedStackFrame.StackFrameReader;
import dalvik.system.EmulatedStackFrame.StackFrameWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import sun.invoke.util.Wrapper;
import sun.misc.Unsafe;
import static dalvik.system.EmulatedStackFrame.StackFrameAccessor.copyNext;

/**
 * @hide Public for testing only.
 */
public class Transformers {
    private Transformers() {}

    static {
        try {
            TRANSFORM_INTERNAL = MethodHandle.class.getDeclaredMethod("transformInternal",
                    EmulatedStackFrame.class);
        } catch (NoSuchMethodException nsme) {
            throw new AssertionError();
        }
    }

    /**
     * Method reference to the private {@code MethodHandle.transformInternal} method. This is
     * cached here because it's the point of entry for all transformers.
     */
    private static final Method TRANSFORM_INTERNAL;

    /** @hide */
    public static abstract class Transformer extends MethodHandle implements Cloneable {
        protected Transformer(MethodType type) {
            super(TRANSFORM_INTERNAL.getArtMethod(), MethodHandle.INVOKE_TRANSFORM, type);
        }

        protected Transformer(MethodType type, int invokeKind) {
            super(TRANSFORM_INTERNAL.getArtMethod(), invokeKind, type);
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    /**
     * A method handle that always throws an exception of a specified type.
     *
     * The handle declares a nominal return type, which is immaterial to the execution
     * of the handle because it never returns.
     *
     * @hide
     */
    public static class AlwaysThrow extends Transformer {
        private final Class<? extends Throwable> exceptionType;

        public AlwaysThrow(Class<?> nominalReturnType, Class<? extends  Throwable> exType) {
            super(MethodType.methodType(nominalReturnType, exType));
            this.exceptionType = exType;
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            throw emulatedStackFrame.getReference(0, exceptionType);
        }
    }

    /**
     * Implements {@code MethodHandles.dropArguments}.
     */
    public static class DropArguments extends Transformer {
        private final MethodHandle delegate;

        private final EmulatedStackFrame.Range range1;

        /**
         * Note that {@code range2} will be null if the arguments that are being dropped
         * are the last {@code n}.
         */
        /* @Nullable */ private final EmulatedStackFrame.Range range2;

        public DropArguments(MethodType type, MethodHandle delegate,
                             int startPos, int numDropped) {
            super(type);

            this.delegate = delegate;

            // We pre-calculate the ranges of values we have to copy through to the delegate
            // handle at the time of instantiation so that the actual invoke is performant.
            this.range1 = EmulatedStackFrame.Range.of(type, 0, startPos);
            final int numArgs = type.ptypes().length;
            if (startPos + numDropped < numArgs) {
                this.range2 = EmulatedStackFrame.Range.of(type, startPos + numDropped, numArgs);
            } else {
                this.range2 = null;
            }
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(delegate.type());

            emulatedStackFrame.copyRangeTo(calleeFrame, range1,
                    0 /* referencesStart */, 0 /* stackFrameStart */);

            if (range2 != null) {
                final int referencesStart = range1.numReferences;
                final int stackFrameStart = range1.numBytes;

                emulatedStackFrame.copyRangeTo(calleeFrame, range2,
                        referencesStart, stackFrameStart);
            }

            delegate.invoke(calleeFrame);
            calleeFrame.copyReturnValueTo(emulatedStackFrame);
        }
    }

    /**
     * Implements {@code MethodHandles.catchException}.
     */
    public static class CatchException extends Transformer {
        private final MethodHandle target;
        private final MethodHandle handler;
        private final Class<?> exType;

        private final EmulatedStackFrame.Range handlerArgsRange;

        public CatchException(MethodHandle target, MethodHandle handler, Class<?> exType) {
            super(target.type());

            this.target = target;
            this.handler = handler;
            this.exType = exType;

            // We only copy the first "count" args, dropping others if required. Note that
            // we subtract one because the first handler arg is the exception thrown by the
            // target.
            handlerArgsRange = EmulatedStackFrame.Range.of(target.type(), 0,
                    (handler.type().parameterCount() - 1));
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            try {
                target.invoke(emulatedStackFrame);
            } catch (Throwable th) {
                if (th.getClass() == exType) {
                    // We've gotten an exception of the appropriate type, so we need to call
                    // the handler. Create a new frame of the appropriate size.
                    EmulatedStackFrame fallback = EmulatedStackFrame.create(handler.type());

                    // The first argument to the handler is the actual exception.
                    fallback.setReference(0, th);

                    // We then copy other arguments that need to be passed through to the handler.
                    // Note that we might drop arguments at the end, if needed. Note that
                    // referencesStart == 1 because the first argument is the exception type.
                    emulatedStackFrame.copyRangeTo(fallback, handlerArgsRange,
                            1 /* referencesStart */, 0 /* stackFrameStart */);

                    // Perform the invoke and return the appropriate value.
                    handler.invoke(fallback);
                    fallback.copyReturnValueTo(emulatedStackFrame);
                } else {
                    // The exception is not of the expected type, we throw it.
                    throw th;
                }
            }
        }
    }

    /**
     * Implements {@code MethodHandles.GuardWithTest}.
     */
    public static class GuardWithTest extends Transformer {
        private final MethodHandle test;
        private final MethodHandle target;
        private final MethodHandle fallback;

        private final EmulatedStackFrame.Range testArgsRange;

        public GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) {
            super(target.type());

            this.test = test;
            this.target = target;
            this.fallback = fallback;

            // The test method might have a subset of the arguments of the handle / target.
            testArgsRange = EmulatedStackFrame.Range.of(target.type(), 0, test.type().parameterCount());
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            EmulatedStackFrame testFrame = EmulatedStackFrame.create(test.type());
            emulatedStackFrame.copyRangeTo(testFrame, testArgsRange, 0, 0);

            // We know that the return value for test is going to be boolean.class, so we don't have
            // to do the copyReturnValue dance.
            final boolean value = (boolean) test.invoke(testFrame);
            if (value) {
                target.invoke(emulatedStackFrame);
            } else {
                fallback.invoke(emulatedStackFrame);
            }
        }
    }

    /**
     * Implementation of MethodHandles.arrayElementGetter for reference types.
     */
    public static class ReferenceArrayElementGetter extends Transformer {
        private final Class<?> arrayClass;

        public ReferenceArrayElementGetter(Class<?> arrayClass) {
            super(MethodType.methodType(arrayClass.getComponentType(),
                    new Class<?>[]{arrayClass, int.class}));
            this.arrayClass = arrayClass;
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            final StackFrameReader reader = new StackFrameReader();
            reader.attach(emulatedStackFrame);

            // Read the array object and the index from the stack frame.
            final Object[] array = (Object[]) reader.nextReference(arrayClass);
            final int index = reader.nextInt();

            // Write the array element back to the stack frame.
            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(emulatedStackFrame);
            writer.makeReturnValueAccessor();
            writer.putNextReference(array[index], arrayClass.getComponentType());
        }
    }

    /**
     * Implementation of MethodHandles.arrayElementSetter for reference types.
     */
    public static class ReferenceArrayElementSetter extends Transformer {
        private final Class<?> arrayClass;

        public ReferenceArrayElementSetter(Class<?> arrayClass) {
            super(MethodType.methodType(void.class,
                    new Class<?>[] { arrayClass, int.class, arrayClass.getComponentType() }));
            this.arrayClass = arrayClass;
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            final StackFrameReader reader = new StackFrameReader();
            reader.attach(emulatedStackFrame);

            // Read the array object, index and the value to write from the stack frame.
            final Object[] array = (Object[]) reader.nextReference(arrayClass);
            final int index = reader.nextInt();
            final Object value = reader.nextReference(arrayClass.getComponentType());

            array[index] = value;
        }
    }

    /**
     * Implementation of MethodHandles.identity() for reference types.
     */
    public static class ReferenceIdentity extends Transformer {
        private final Class<?> type;

        public ReferenceIdentity(Class<?> type) {
            super(MethodType.methodType(type, type));
            this.type = type;
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            final StackFrameReader reader = new StackFrameReader();
            reader.attach(emulatedStackFrame);

            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(emulatedStackFrame);
            writer.makeReturnValueAccessor();
            writer.putNextReference(reader.nextReference(type), type);
        }
    }

    /**
     * Implementation of MethodHandles.constant.
     */
    public static class Constant extends Transformer {
        private final Class<?> type;

        // NOTE: This implementation turned out to be more awkward than expected becuase
        // of the type system. We could simplify this considerably at the cost of making
        // the emulated stack frame API uglier or by transitioning into JNI.
        //
        // We could consider implementing this in terms of bind() once that's implemented.
        // This would then just become : MethodHandles.identity(type).bind(value).
        private int asInt;
        private long asLong;
        private float asFloat;
        private double asDouble;
        private Object asReference;

        private char typeChar;

        public Constant(Class<?> type, Object value) {
            super(MethodType.methodType(type));
            this.type = type;

            if (!type.isPrimitive()) {
                asReference = value;
                typeChar = 'L';
            } else if (type == int.class) {
                asInt = (int) value;
                typeChar = 'I';
            } else if (type == char.class) {
                asInt = (int) (char) value;
                typeChar = 'C';
            } else if (type == short.class) {
                asInt = (int) (short) value;
                typeChar = 'S';
            } else if (type == byte.class) {
                asInt = (int) (byte) value;
                typeChar = 'B';
            } else if (type == boolean.class) {
                asInt = ((boolean) value) ? 1 : 0;
                typeChar = 'Z';
            } else if (type == long.class) {
                asLong = (long) value;
                typeChar = 'J';
            } else if (type == float.class) {
                asFloat = (float) value;
                typeChar = 'F';
            } else if (type == double.class) {
                asDouble = (double) value;
                typeChar = 'D';
            } else {
                throw new AssertionError("unknown type: " + typeChar);
            }
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(emulatedStackFrame);
            writer.makeReturnValueAccessor();

            switch (typeChar) {
                case 'L' : { writer.putNextReference(asReference, type); break; }
                case 'I' : { writer.putNextInt(asInt); break; }
                case 'C' : { writer.putNextChar((char) asInt); break; }
                case 'S' : { writer.putNextShort((short) asInt); break; }
                case 'B' : { writer.putNextByte((byte) asInt); break; }
                case 'Z' : { writer.putNextBoolean(asInt == 1); break; }
                case 'J' : { writer.putNextLong(asLong); break; }
                case 'F' : { writer.putNextFloat(asFloat); break; }
                case 'D' : { writer.putNextDouble(asDouble); break; }
                default:
                    throw new AssertionError("Unexpected typeChar: " + typeChar);
            }
        }
    }

    /*package*/ static class Construct extends Transformer {
        private final MethodHandle constructorHandle;
        private final EmulatedStackFrame.Range callerRange;

        /*package*/ Construct(MethodHandle constructorHandle, MethodType returnedType) {
            super(returnedType);
            this.constructorHandle = constructorHandle;
            this.callerRange = EmulatedStackFrame.Range.all(type());
        }

        MethodHandle getConstructorHandle() {
            return constructorHandle;
        }

        private static boolean isAbstract(Class<?> klass) {
            return (klass.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT;
        }

        private static void checkInstantiable(Class<?> klass) throws InstantiationException {
            if (isAbstract(klass)) {
                String s = klass.isInterface() ? "interface " : "abstract class ";
                throw new InstantiationException("Can't instantiate " + s + klass);
            }
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            final Class<?> receiverType = type().rtype();
            checkInstantiable(receiverType);

            // Allocate memory for receiver.
            Object receiver = Unsafe.getUnsafe().allocateInstance(receiverType);

            // The MethodHandle type for the caller has the form of
            // {rtype=T,ptypes=A1..An}. The constructor MethodHandle is of
            // the form {rtype=void,ptypes=T,A1...An}. So the frame for
            // the constructor needs to have a slot with the receiver
            // in position 0.
            EmulatedStackFrame constructorFrame =
                    EmulatedStackFrame.create(constructorHandle.type());
            constructorFrame.setReference(0, receiver);
            emulatedStackFrame.copyRangeTo(constructorFrame, callerRange, 1, 0);
            constructorHandle.invoke(constructorFrame);

            // Set return result for caller.
            emulatedStackFrame.setReturnValueTo(receiver);
        }
    }

    /**
     * Implements MethodHandle.bindTo.
     *
     * @hide
     */
    public static class BindTo extends Transformer {
        private final MethodHandle delegate;
        private final Object receiver;

        private final EmulatedStackFrame.Range range;

        public BindTo(MethodHandle delegate, Object receiver) {
            super(delegate.type().dropParameterTypes(0, 1));

            this.delegate = delegate;
            this.receiver = receiver;

            this.range = EmulatedStackFrame.Range.all(this.type());
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            // Create a new emulated stack frame with the full type (including the leading
            // receiver reference).
            EmulatedStackFrame stackFrame = EmulatedStackFrame.create(delegate.type());

            // The first reference argument must be the receiver.
            stackFrame.setReference(0, receiver);
            // Copy all other arguments.
            emulatedStackFrame.copyRangeTo(stackFrame, range,
                    1 /* referencesStart */, 0 /* stackFrameStart */);

            // Perform the invoke.
            delegate.invoke(stackFrame);
            stackFrame.copyReturnValueTo(emulatedStackFrame);
        }
    }

    /**
     * Implements MethodHandle.filterReturnValue.
     */
    public static class FilterReturnValue extends Transformer {
        private final MethodHandle target;
        private final MethodHandle filter;

        private final EmulatedStackFrame.Range allArgs;

        public FilterReturnValue(MethodHandle target, MethodHandle filter) {
            super(MethodType.methodType(filter.type().rtype(), target.type().ptypes()));

            this.target = target;
            this.filter = filter;

            allArgs = EmulatedStackFrame.Range.all(type());
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            // Create a new frame with the target's type and copy all arguments over.
            // This frame differs in return type with |emulatedStackFrame| but will have
            // the same parameter shapes.
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
            emulatedStackFrame.copyRangeTo(targetFrame, allArgs, 0, 0);
            target.invoke(targetFrame);

            // Perform the invoke.
            final StackFrameReader returnValueReader = new StackFrameReader();
            returnValueReader.attach(targetFrame);
            returnValueReader.makeReturnValueAccessor();

            // Create an emulated frame for the filter and copy all its arguments across.
            EmulatedStackFrame filterFrame = EmulatedStackFrame.create(filter.type());
            final StackFrameWriter filterWriter = new StackFrameWriter();
            filterWriter.attach(filterFrame);

            final Class<?> returnType = target.type().rtype();
            if (!returnType.isPrimitive()) {
                filterWriter.putNextReference(returnValueReader.nextReference(returnType),
                        returnType);
            } else if (returnType == boolean.class) {
                filterWriter.putNextBoolean(returnValueReader.nextBoolean());
            } else if (returnType == byte.class) {
                filterWriter.putNextByte(returnValueReader.nextByte());
            } else if (returnType == char.class) {
                filterWriter.putNextChar(returnValueReader.nextChar());
            } else if (returnType == short.class) {
                filterWriter.putNextShort(returnValueReader.nextShort());
            } else if (returnType == int.class) {
                filterWriter.putNextInt(returnValueReader.nextInt());
            } else if (returnType == long.class) {
                filterWriter.putNextLong(returnValueReader.nextLong());
            } else if (returnType == float.class) {
                filterWriter.putNextFloat(returnValueReader.nextFloat());
            } else if (returnType == double.class) {
                filterWriter.putNextDouble(returnValueReader.nextDouble());
            }

            // Invoke the filter and copy its return value back to the original frame.
            filter.invoke(filterFrame);
            filterFrame.copyReturnValueTo(emulatedStackFrame);
        }
    }

    /*
     * Implements MethodHandles.permuteArguments.
     *
     * @hide
     */
    public static class PermuteArguments extends Transformer {
        private final MethodHandle target;
        private final int[] reorder;

        public PermuteArguments(MethodType type, MethodHandle target, int[] reorder) {
            super(type);

            this.target = target;
            this.reorder = reorder;
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            final StackFrameReader reader = new StackFrameReader();
            reader.attach(emulatedStackFrame);

            // In the interests of simplicity, we box / unbox arguments while performing
            // the permutation. We first iterate through the incoming stack frame and box
            // each argument. We then unbox and write out the argument to the target frame
            // according to the specified reordering.
            Object[] arguments = new Object[reorder.length];
            final Class<?>[] ptypes = type().ptypes();
            for (int i = 0; i < ptypes.length; ++i) {
                final Class<?> ptype = ptypes[i];
                if (!ptype.isPrimitive()) {
                    arguments[i] = reader.nextReference(ptype);
                } else if (ptype == boolean.class) {
                    arguments[i] = reader.nextBoolean();
                } else if (ptype == byte.class) {
                    arguments[i] = reader.nextByte();
                } else if (ptype == char.class) {
                    arguments[i] = reader.nextChar();
                } else if (ptype == short.class) {
                    arguments[i] = reader.nextShort();
                } else if (ptype == int.class) {
                    arguments[i] = reader.nextInt();
                } else if (ptype == long.class) {
                    arguments[i] = reader.nextLong();
                } else if (ptype == float.class) {
                    arguments[i] = reader.nextFloat();
                } else if (ptype == double.class) {
                    arguments[i] = reader.nextDouble();
                } else {
                    throw new AssertionError("Unexpected type: " + ptype);
                }
            }

            EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(target.type());
            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(calleeFrame);

            for (int i = 0; i < ptypes.length; ++i) {
                int idx = reorder[i];
                final Class<?> ptype = ptypes[idx];
                final Object argument = arguments[idx];

                if (!ptype.isPrimitive()) {
                    writer.putNextReference(argument, ptype);
                } else if (ptype == boolean.class) {
                    writer.putNextBoolean((boolean) argument);
                } else if (ptype == byte.class) {
                    writer.putNextByte((byte) argument);
                } else if (ptype == char.class) {
                    writer.putNextChar((char) argument);
                } else if (ptype == short.class) {
                    writer.putNextShort((short) argument);
                } else if (ptype == int.class) {
                    writer.putNextInt((int) argument);
                } else if (ptype == long.class) {
                    writer.putNextLong((long) argument);
                } else if (ptype == float.class) {
                    writer.putNextFloat((float) argument);
                } else if (ptype == double.class) {
                    writer.putNextDouble((double) argument);
                } else {
                    throw new AssertionError("Unexpected type: " + ptype);
                }
            }

            target.invoke(calleeFrame);
            calleeFrame.copyReturnValueTo(emulatedStackFrame);
        }
    }

    /**
     * Converts methods with a trailing array argument to variable arity
     * methods. So (A,B,C[])R can be invoked with any number of convertible
     * arguments after B, e.g. (A,B)R or (A, B, C0)R or (A, B, C0...Cn)R.
     *
     * @hide
     */
    /*package*/ static class VarargsCollector extends Transformer {
        final MethodHandle target;

        /*package*/ VarargsCollector(MethodHandle target) {
            super(target.type(), MethodHandle.INVOKE_CALLSITE_TRANSFORM);
            if (!lastParameterTypeIsAnArray(target.type().ptypes())) {
                throw new IllegalArgumentException("target does not have array as last parameter");
            }
            this.target = target;
        }

        private static boolean lastParameterTypeIsAnArray(Class<?>[] parameterTypes) {
            if (parameterTypes.length == 0) return false;
            return parameterTypes[parameterTypes.length - 1].isArray();
        }

        @Override
        public boolean isVarargsCollector() { return true; }

        @Override
        public MethodHandle asFixedArity() { return target; }

        @Override
        public void transform(EmulatedStackFrame callerFrame) throws Throwable {
            MethodType callerFrameType = callerFrame.getMethodType();
            Class<?>[] callerPTypes = callerFrameType.ptypes();
            Class<?>[] targetPTypes = type().ptypes();

            int lastTargetIndex = targetPTypes.length - 1;
            if (callerPTypes.length == targetPTypes.length &&
                targetPTypes[lastTargetIndex].isAssignableFrom(callerPTypes[lastTargetIndex])) {
                // Caller frame matches target frame in the arity array parameter. Invoke
                // immediately, and let the invoke() dispatch perform any necessary conversions
                // on the other parameters present.
                target.invoke(callerFrame);
                return;
            }

            if (callerPTypes.length < targetPTypes.length - 1) {
                // Too few arguments to be compatible with variable arity invocation.
                throwWrongMethodTypeException(callerFrameType, type());
            }

            if (!MethodType.canConvert(type().rtype(), callerFrameType.rtype())) {
                // Incompatible return type.
                throwWrongMethodTypeException(callerFrameType, type());
            }

            Class<?> elementType = targetPTypes[lastTargetIndex].getComponentType();
            if (!arityArgumentsConvertible(callerPTypes, lastTargetIndex, elementType)) {
                // Wrong types to be compatible with variable arity invocation.
                throwWrongMethodTypeException(callerFrameType, type());
            }

            // Allocate targetFrame.
            MethodType targetFrameType = makeTargetFrameType(callerFrameType, type());
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(targetFrameType);
            prepareFrame(callerFrame, targetFrame);

            // Invoke target.
            target.invoke(targetFrame);

            // Copy return value to the caller's frame.
            targetFrame.copyReturnValueTo(callerFrame);
        }

        private static void throwWrongMethodTypeException(MethodType from, MethodType to) {
            throw new WrongMethodTypeException("Cannot convert " + from + " to " + to);
        }

        private static boolean arityArgumentsConvertible(Class<?>[] ptypes, int arityStart,
                                                         Class<?> elementType) {
            if (ptypes.length - 1 == arityStart) {
                if (ptypes[arityStart].isArray() &&
                    ptypes[arityStart].getComponentType() == elementType) {
                    // The last ptype is in the same position as the arity
                    // array and has the same type.
                    return true;
                }
            }

            for (int i = arityStart; i < ptypes.length; ++i) {
                if (!MethodType.canConvert(ptypes[i], elementType)) {
                    return false;
                }
            }
            return true;
        }

        private static Object referenceArray(StackFrameReader reader, Class<?>[] ptypes,
                                             Class<?> elementType, int offset, int length) {
            Object arityArray = Array.newInstance(elementType, length);
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                Object o = null;
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { o = reader.nextReference(argumentType); break; }
                    case 'I': { o = reader.nextInt(); break; }
                    case 'J': { o = reader.nextLong(); break; }
                    case 'B': { o = reader.nextByte(); break; }
                    case 'S': { o = reader.nextShort(); break; }
                    case 'C': { o = reader.nextChar(); break; }
                    case 'Z': { o = reader.nextBoolean(); break; }
                    case 'F': { o = reader.nextFloat(); break; }
                    case 'D': { o = reader.nextDouble(); break; }
                }
                if (o != null && !elementType.isAssignableFrom(o.getClass())) {
                    throw new ClassCastException(
                        o.getClass() + " not assignable to " + elementType);
                }
                Array.set(arityArray, i, o);
            }
            return arityArray;
        }

        private static Object intArray(StackFrameReader reader, Class<?> ptypes[],
                                       int offset, int length) {
            int[] arityArray = new int[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'I': { arityArray[i] = reader.nextInt(); break; }
                    case 'S': { arityArray[i] = reader.nextShort(); break; }
                    case 'B': { arityArray[i] = reader.nextByte(); break; }
                    default: {
                        arityArray[i] = (Integer) reader.nextReference(argumentType);
                        break;
                    }
                }
            }
            return arityArray;
        }

        private static Object longArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            long[] arityArray = new long[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'J': { arityArray[i] = reader.nextLong(); break; }
                    case 'I': { arityArray[i] = reader.nextInt(); break; }
                    case 'S': { arityArray[i] = reader.nextShort(); break; }
                    case 'B': { arityArray[i] = reader.nextByte(); break; }
                    default: { arityArray[i] = (Long) reader.nextReference(argumentType); break; }
                }
            }
            return arityArray;
        }

        private static Object byteArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            byte[] arityArray = new byte[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'B': { arityArray[i] = reader.nextByte(); break; }
                    default: { arityArray[i] = (Byte) reader.nextReference(argumentType); break; }
                }
            }
            return arityArray;
        }

        private static Object shortArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            short[] arityArray = new short[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'S': { arityArray[i] = reader.nextShort(); break; }
                    case 'B': { arityArray[i] = reader.nextByte(); break; }
                    default: { arityArray[i] = (Short) reader.nextReference(argumentType); break; }
                }
            }
            return arityArray;
        }

        private static Object charArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            char[] arityArray = new char[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'C': { arityArray[i] = reader.nextChar(); break; }
                    default: {
                        arityArray[i] = (Character) reader.nextReference(argumentType);
                        break;
                    }
                }
            }
            return arityArray;
        }

        private static Object booleanArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            boolean[] arityArray = new boolean[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'Z': { arityArray[i] = reader.nextBoolean(); break; }
                    default:
                        arityArray[i] = (Boolean) reader.nextReference(argumentType);
                        break;
                }
            }
            return arityArray;
        }

        private static Object floatArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            float[] arityArray = new float[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'F': { arityArray[i] = reader.nextFloat(); break; }
                    case 'J': { arityArray[i] = reader.nextLong(); break; }
                    case 'I': { arityArray[i] = reader.nextInt(); break; }
                    case 'S': { arityArray[i] = reader.nextShort(); break; }
                    case 'B': { arityArray[i] = reader.nextByte(); break; }
                    default: {
                        arityArray[i] = (Float) reader.nextReference(argumentType);
                        break;
                    }
                }
            }
            return arityArray;
        }

        private static Object doubleArray(StackFrameReader reader, Class<?> ptypes[],
                                        int offset, int length) {
            double[] arityArray = new double[length];
            for (int i = 0; i < length; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'D': { arityArray[i] = reader.nextDouble(); break; }
                    case 'F': { arityArray[i] = reader.nextFloat(); break; }
                    case 'J': { arityArray[i] = reader.nextLong(); break; }
                    case 'I': { arityArray[i] = reader.nextInt(); break; }
                    case 'S': { arityArray[i] = reader.nextShort(); break; }
                    case 'B': { arityArray[i] = reader.nextByte(); break; }
                    default: {
                        arityArray[i] = (Double) reader.nextReference(argumentType);
                        break;
                    }
                }
            }
            return arityArray;
        }

        private static Object makeArityArray(MethodType callerFrameType,
                                             StackFrameReader callerFrameReader,
                                             int indexOfArityArray,
                                             Class<?> arityArrayType) {
            int arityArrayLength = callerFrameType.ptypes().length - indexOfArityArray;
            Class<?> elementType = arityArrayType.getComponentType();
            Class<?>[] callerPTypes = callerFrameType.ptypes();

            char elementBasicType = Wrapper.basicTypeChar(elementType);
            switch (elementBasicType) {
                case 'L': return referenceArray(callerFrameReader, callerPTypes, elementType,
                                                indexOfArityArray, arityArrayLength);
                case 'I': return intArray(callerFrameReader, callerPTypes,
                                          indexOfArityArray, arityArrayLength);
                case 'J': return longArray(callerFrameReader, callerPTypes,
                                           indexOfArityArray, arityArrayLength);
                case 'B': return byteArray(callerFrameReader, callerPTypes,
                                           indexOfArityArray, arityArrayLength);
                case 'S': return shortArray(callerFrameReader, callerPTypes,
                                            indexOfArityArray, arityArrayLength);
                case 'C': return charArray(callerFrameReader, callerPTypes,
                                           indexOfArityArray, arityArrayLength);
                case 'Z': return booleanArray(callerFrameReader, callerPTypes,
                                              indexOfArityArray, arityArrayLength);
                case 'F': return floatArray(callerFrameReader, callerPTypes,
                                            indexOfArityArray, arityArrayLength);
                case 'D': return doubleArray(callerFrameReader, callerPTypes,
                                             indexOfArityArray, arityArrayLength);
            }
            throw new InternalError("Unexpected type: " + elementType);
        }

        public static Object collectArguments(char basicComponentType, Class<?> componentType,
                                              StackFrameReader reader, Class<?>[] types,
                                              int startIdx, int length) {
            switch (basicComponentType) {
                case 'L': return referenceArray(reader, types, componentType, startIdx, length);
                case 'I': return intArray(reader, types, startIdx, length);
                case 'J': return longArray(reader, types, startIdx, length);
                case 'B': return byteArray(reader, types, startIdx, length);
                case 'S': return shortArray(reader, types, startIdx, length);
                case 'C': return charArray(reader, types, startIdx, length);
                case 'Z': return booleanArray(reader, types, startIdx, length);
                case 'F': return floatArray(reader, types, startIdx, length);
                case 'D': return doubleArray(reader, types, startIdx, length);
            }
            throw new InternalError("Unexpected type: " + basicComponentType);
        }

        private static void copyParameter(StackFrameReader reader, StackFrameWriter writer,
                                          Class<?> ptype) {
            switch (Wrapper.basicTypeChar(ptype)) {
                case 'L': { writer.putNextReference(reader.nextReference(ptype), ptype); break; }
                case 'I': { writer.putNextInt(reader.nextInt()); break; }
                case 'J': { writer.putNextLong(reader.nextLong()); break; }
                case 'B': { writer.putNextByte(reader.nextByte()); break; }
                case 'S': { writer.putNextShort(reader.nextShort()); break; }
                case 'C': { writer.putNextChar(reader.nextChar()); break; }
                case 'Z': { writer.putNextBoolean(reader.nextBoolean()); break; }
                case 'F': { writer.putNextFloat(reader.nextFloat()); break; }
                case 'D': { writer.putNextDouble(reader.nextDouble()); break; }
                default: throw new InternalError("Unexpected type: " + ptype);
            }
        }

        private static void prepareFrame(EmulatedStackFrame callerFrame,
                                         EmulatedStackFrame targetFrame) {
            StackFrameWriter targetWriter = new StackFrameWriter();
            targetWriter.attach(targetFrame);
            StackFrameReader callerReader = new StackFrameReader();
            callerReader.attach(callerFrame);

            // Copy parameters from |callerFrame| to |targetFrame| leaving room for arity array.
            MethodType targetMethodType = targetFrame.getMethodType();
            int indexOfArityArray = targetMethodType.ptypes().length - 1;
            for (int i = 0; i < indexOfArityArray; ++i) {
                Class<?> ptype = targetMethodType.ptypes()[i];
                copyParameter(callerReader, targetWriter, ptype);
            }

            // Add arity array as last parameter in |targetFrame|.
            Class<?> arityArrayType = targetMethodType.ptypes()[indexOfArityArray];
            Object arityArray = makeArityArray(callerFrame.getMethodType(), callerReader,
                                               indexOfArityArray, arityArrayType);
            targetWriter.putNextReference(arityArray, arityArrayType);
        }

        /**
         * Computes the frame type to invoke the target method handle with. This
         * is the same as the caller frame type, but with the trailing argument
         * being the array type that is the trailing argument in the target method
         * handle.
         *
         * Suppose the targetType is (T0, T1, T2[])RT and the callerType is (C0, C1, C2, C3)RC
         * then the constructed type is (C0, C1, T2[])RC.
         */
        private static MethodType makeTargetFrameType(MethodType callerType,
                                                      MethodType targetType) {
            final int ptypesLength = targetType.ptypes().length;
            final Class<?>[] ptypes = new Class<?>[ptypesLength];
            // Copy types from caller types to new methodType.
            System.arraycopy(callerType.ptypes(), 0, ptypes, 0, ptypesLength - 1);
            // Set the last element in the type array to be the
            // varargs array of the target.
            ptypes[ptypesLength - 1] = targetType.ptypes()[ptypesLength - 1];
            return MethodType.methodType(callerType.rtype(), ptypes);
        }
    }

    /**
     * Implements MethodHandles.invoker & MethodHandles.exactInvoker.
     */
    static class Invoker extends Transformer {
        private final MethodType targetType;
        private final boolean isExactInvoker;
        private final EmulatedStackFrame.Range copyRange;

        Invoker(MethodType targetType, boolean isExactInvoker) {
            super(targetType.insertParameterTypes(0, MethodHandle.class));
            this.targetType = targetType;
            this.isExactInvoker = isExactInvoker;
            copyRange = EmulatedStackFrame.Range.of(type(), 1, type().parameterCount());
        }

        @Override
        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
            // We need to artifically throw a WrongMethodTypeException here because we
            // can't call invokeExact on the target inside the transformer.
            if (isExactInvoker) {
                // TODO: We should do the comparison by hand if this new type creation
                // on every invoke proves too expensive.
                MethodType callType = emulatedStackFrame.getCallsiteType().dropParameterTypes(0, 1);
                if (!targetType.equals(callType)) {
                    throw new WrongMethodTypeException("Wrong type, Expected: " + targetType
                            + " was: " + callType);
                }
            }

            // The first argument to the stack frame is the handle that needs to be invoked.
            MethodHandle target = emulatedStackFrame.getReference(0, MethodHandle.class);

            // All other arguments must be copied to the target frame.
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(targetType);
            emulatedStackFrame.copyRangeTo(targetFrame, copyRange, 0, 0);

            // Finally, invoke the handle and copy the return value.
            target.invoke(targetFrame);
            targetFrame.copyReturnValueTo(emulatedStackFrame);
        }
    }

    /**
     * Implements MethodHandle.asSpreader / MethodHandles.spreadInvoker.
     */
    static class Spreader extends Transformer {
        /** The method handle we're delegating to. */
        private final MethodHandle target;

        /**
         * The offset of the trailing array argument in the list of arguments to
         * this transformer. The array argument is always the last argument.
         */
        private final int arrayOffset;

        /**
         * The type char of the component type of the array.
         */
        private final char arrayTypeChar;

        /**
         * The number of input arguments that will be present in the array. In other words,
         * this is the expected array length.
         */
        private final int numArrayArgs;

        /**
         * Range of arguments to copy verbatim from the input frame, This will cover all
         * arguments that aren't a part of the trailing array.
         */
        private final Range copyRange;

        Spreader(MethodHandle target, MethodType spreaderType, int numArrayArgs) {
            super(spreaderType);
            this.target = target;
            // Copy all arguments except the last argument (which is the trailing array argument
            // that needs to be spread).
            arrayOffset = spreaderType.parameterCount() - 1;

            // Get and cache the component type of the input array.
            final Class<?> componentType = spreaderType.ptypes()[arrayOffset].getComponentType();
            if (componentType == null) {
                throw new AssertionError("Trailing argument must be an array.");
            }
            arrayTypeChar = Wrapper.basicTypeChar(componentType);

            this.numArrayArgs = numArrayArgs;
            // Copy all args except for the last argument.
            this.copyRange = EmulatedStackFrame.Range.of(spreaderType, 0, arrayOffset);
        }

        @Override
        public void transform(EmulatedStackFrame callerFrame) throws Throwable {
            // Create a new stack frame for the callee.
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());

            // Copy all arguments except for the trailing array argument.
            callerFrame.copyRangeTo(targetFrame, copyRange, 0, 0);

            // Attach the writer, prepare to spread the trailing array arguments into
            // the callee frame.
            StackFrameWriter writer = new StackFrameWriter();
            writer.attach(targetFrame,
                    arrayOffset,
                    copyRange.numReferences,
                    copyRange.numBytes);

            // Get the array reference and check that its length is as expected.
            Object arrayObj = callerFrame.getReference(
                    copyRange.numReferences, this.type().ptypes()[arrayOffset]);
            final int arrayLength = Array.getLength(arrayObj);
            if (arrayLength != numArrayArgs) {
                throw new IllegalArgumentException("Invalid array length: " + arrayLength);
            }

            final MethodType type = target.type();
            switch (arrayTypeChar) {
                case 'L':
                    spreadArray((Object[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'I':
                    spreadArray((int[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'J':
                    spreadArray((long[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'B':
                    spreadArray((byte[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'S':
                    spreadArray((short[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'C':
                    spreadArray((char[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'Z':
                    spreadArray((boolean[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'F':
                    spreadArray((float[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;
                case 'D':
                    spreadArray((double[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
                    break;

            }

            target.invoke(targetFrame);
            targetFrame.copyReturnValueTo(callerFrame);
        }

        public static void spreadArray(Object[] array, StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                Object o = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(o, argumentType); break; }
                    case 'I': { writer.putNextInt((int) o); break; }
                    case 'J': { writer.putNextLong((long) o); break; }
                    case 'B': { writer.putNextByte((byte) o); break; }
                    case 'S': { writer.putNextShort((short) o); break; }
                    case 'C': { writer.putNextChar((char) o); break; }
                    case 'Z': { writer.putNextBoolean((boolean) o); break; }
                    case 'F': { writer.putNextFloat((float) o); break; }
                    case 'D': { writer.putNextDouble((double) o); break; }
                }
            }
        }

        public static void spreadArray(int[] array, StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                int j = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(j, argumentType); break; }
                    case 'I': { writer.putNextInt(j); break; }
                    case 'J': { writer.putNextLong(j); break; }
                    case 'F': { writer.putNextFloat(j); break; }
                    case 'D': { writer.putNextDouble(j); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(long[] array, StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                long l = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(l, argumentType); break; }
                    case 'J': { writer.putNextLong(l); break; }
                    case 'F': { writer.putNextFloat((float) l); break; }
                    case 'D': { writer.putNextDouble((double) l); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(byte[] array,
                                       StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                byte b = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(b, argumentType); break; }
                    case 'I': { writer.putNextInt(b); break; }
                    case 'J': { writer.putNextLong(b); break; }
                    case 'B': { writer.putNextByte(b); break; }
                    case 'S': { writer.putNextShort(b); break; }
                    case 'F': { writer.putNextFloat(b); break; }
                    case 'D': { writer.putNextDouble(b); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(short[] array,
                                       StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                short s = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(s, argumentType); break; }
                    case 'I': { writer.putNextInt(s); break; }
                    case 'J': { writer.putNextLong(s); break; }
                    case 'S': { writer.putNextShort(s); break; }
                    case 'F': { writer.putNextFloat(s); break; }
                    case 'D': { writer.putNextDouble(s); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(char[] array,
                                       StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                char c = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(c, argumentType); break; }
                    case 'I': { writer.putNextInt(c); break; }
                    case 'J': { writer.putNextLong(c); break; }
                    case 'C': { writer.putNextChar(c); break; }
                    case 'F': { writer.putNextFloat(c); break; }
                    case 'D': { writer.putNextDouble(c); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(boolean[] array,
                                       StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                boolean z = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(z, argumentType); break; }
                    case 'Z': { writer.putNextBoolean(z); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(double[] array,
                                       StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                double d = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(d, argumentType); break; }
                    case 'D': { writer.putNextDouble(d); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }

        public static void spreadArray(float[] array, StackFrameWriter writer, MethodType type,
                                       int numArgs, int offset) {
            final Class<?>[] ptypes = type.ptypes();
            for (int i = 0; i < numArgs; ++i) {
                Class<?> argumentType = ptypes[i + offset];
                float f = array[i];
                switch (Wrapper.basicTypeChar(argumentType)) {
                    case 'L': { writer.putNextReference(f, argumentType); break; }
                    case 'D': { writer.putNextDouble((double) f); break; }
                    case 'F': { writer.putNextFloat(f); break; }
                    default : { throw new AssertionError(); }
                }
            }
        }
    }

    /**
     * Implements MethodHandle.asCollector.
     */
    static class Collector extends Transformer {
        private final MethodHandle target;

        /**
         * The offset of the trailing array argument in the list of arguments to
         * this transformer. The array argument is always the last argument.
         */
        private final int arrayOffset;

        /**
         * The number of input arguments that will be present in the array. In other words,
         * this is the expected array length.
         */
        private final int numArrayArgs;

        /**
         * The type char of the component type of the array.
         */
        private final char arrayTypeChar;

        /**
         * Range of arguments to copy verbatim from the input frame, This will cover all
         * arguments that aren't a part of the trailing array.
         */
        private final Range copyRange;

        Collector(MethodHandle delegate, Class<?> arrayType, int length) {
            super(delegate.type().asCollectorType(arrayType, length));

            target = delegate;
            // Copy all arguments except the last argument (which is the trailing array argument
            // that needs to be spread).
            arrayOffset = delegate.type().parameterCount() - 1;
            arrayTypeChar = Wrapper.basicTypeChar(arrayType.getComponentType());
            numArrayArgs = length;

            // Copy all args except for the last argument.
            copyRange = EmulatedStackFrame.Range.of(delegate.type(), 0, arrayOffset);
        }

        @Override
        public void transform(EmulatedStackFrame callerFrame) throws Throwable {
            // Create a new stack frame for the callee.
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());

            // Copy all arguments except for the trailing array argument.
            callerFrame.copyRangeTo(targetFrame, copyRange, 0, 0);

            // Attach the writer, prepare to spread the trailing array arguments into
            // the callee frame.
            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(targetFrame, arrayOffset, copyRange.numReferences, copyRange.numBytes);
            final StackFrameReader reader = new StackFrameReader();
            reader.attach(callerFrame, arrayOffset, copyRange.numReferences, copyRange.numBytes);

            switch (arrayTypeChar) {
                case 'L': {
                    // Reference arrays are the only case where the component type of the
                    // array we construct might differ from the type of the reference we read
                    // from the stack frame.
                    final Class<?> targetType = target.type().ptypes()[arrayOffset];
                    final Class<?> targetComponentType = targetType.getComponentType();
                    final Class<?> adapterComponentType = type().lastParameterType();

                    Object[] arr = (Object[]) Array.newInstance(targetComponentType, numArrayArgs);
                    for (int i = 0; i < numArrayArgs; ++i) {
                        arr[i] = reader.nextReference(adapterComponentType);
                    }

                    writer.putNextReference(arr, targetType);
                    break;
                }
                case 'I': {
                    int[] array = new int[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextInt();
                    }
                    writer.putNextReference(array, int[].class);
                    break;
                }
                case 'J': {
                    long[] array = new long[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextLong();
                    }
                    writer.putNextReference(array, long[].class);
                    break;
                }
                case 'B': {
                    byte[] array = new byte[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextByte();
                    }
                    writer.putNextReference(array, byte[].class);
                    break;
                }
                case 'S': {
                    short[] array = new short[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextShort();
                    }
                    writer.putNextReference(array, short[].class);
                    break;
                }
                case 'C': {
                    char[] array = new char[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextChar();
                    }
                    writer.putNextReference(array, char[].class);
                    break;
                }
                case 'Z': {
                    boolean[] array = new boolean[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextBoolean();
                    }
                    writer.putNextReference(array, boolean[].class);
                    break;
                }
                case 'F': {
                    float[] array = new float[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextFloat();
                    }
                    writer.putNextReference(array, float[].class);
                    break;
                }
                case 'D': {
                    double[] array = new double[numArrayArgs];
                    for (int i = 0; i < numArrayArgs; ++i) {
                        array[i] = reader.nextDouble();
                    }
                    writer.putNextReference(array, double[].class);
                    break;
                }
            }

            target.invoke(targetFrame);
            targetFrame.copyReturnValueTo(callerFrame);
        }
    }

    /*
     * Implements MethodHandles.filterArguments.
     */
    static class FilterArguments extends Transformer {
        /** The target handle. */
        private final MethodHandle target;
        /** Index of the first argument to filter */
        private final int pos;
        /** The list of filters to apply */
        private final MethodHandle[] filters;

        FilterArguments(MethodHandle target, int pos, MethodHandle[] filters) {
            super(deriveType(target, pos, filters));

            this.target = target;
            this.pos = pos;
            this.filters = filters;

        }

        private static MethodType deriveType(MethodHandle target, int pos, MethodHandle[] filters) {
            final Class<?>[] filterArgs = new Class<?>[filters.length];
            for (int i = 0; i < filters.length; ++i) {
                filterArgs[i] = filters[i].type().parameterType(0);
            }

            return target.type().replaceParameterTypes(pos, pos + filters.length, filterArgs);
        }

        @Override
        public void transform(EmulatedStackFrame stackFrame) throws Throwable {
            final StackFrameReader reader = new StackFrameReader();
            reader.attach(stackFrame);

            EmulatedStackFrame transformedFrame = EmulatedStackFrame.create(target.type());
            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(transformedFrame);

            final Class<?>[] ptypes = target.type().ptypes();
            for (int i = 0; i < ptypes.length; ++i) {
                // Check whether the current argument has a filter associated with it.
                // If it has no filter, no further action need be taken.
                final Class<?> ptype = ptypes[i];
                final MethodHandle filter;
                if (i < pos) {
                    filter = null;
                } else if (i >= pos + filters.length) {
                    filter = null;
                } else {
                    filter = filters[i - pos];
                }

                if (filter != null) {
                    // Note that filter.type() must be (ptype)ptype - this is checked before
                    // this transformer is created.
                    EmulatedStackFrame filterFrame = EmulatedStackFrame.create(filter.type());

                    //  Copy the next argument from the stack frame to the filter frame.
                    final StackFrameWriter filterWriter = new StackFrameWriter();
                    filterWriter.attach(filterFrame);
                    copyNext(reader, filterWriter, filter.type().ptypes()[0]);

                    filter.invoke(filterFrame);

                    // Copy the argument back from the filter frame to the stack frame.
                    final StackFrameReader filterReader = new StackFrameReader();
                    filterReader.attach(filterFrame);
                    filterReader.makeReturnValueAccessor();
                    copyNext(filterReader, writer, ptype);
                } else {
                    // There's no filter associated with this frame, just copy the next argument
                    // over.
                    copyNext(reader, writer, ptype);
                }
            }

            target.invoke(transformedFrame);
            transformedFrame.copyReturnValueTo(stackFrame);
        }
    }

    /**
     * Implements MethodHandles.collectArguments.
     */
    static class CollectArguments extends Transformer {
        private final MethodHandle target;
        private final MethodHandle collector;
        private final int pos;

        /** The range of input arguments we copy to the collector. */
        private final Range collectorRange;

        /**
         * The first range of arguments we copy to the target. These are arguments
         * in the range [0, pos). Note that arg[pos] is the return value of the filter.
         */
        private final Range range1;

        /**
         * The second range of arguments we copy to the target. These are arguments in the range
         * (pos, N], where N is the number of target arguments.
         */
        private final Range range2;

        private final int referencesOffset;
        private final int stackFrameOffset;

        CollectArguments(MethodHandle target, MethodHandle collector, int pos,
                         MethodType adapterType) {
            super(adapterType);

            this.target = target;
            this.collector = collector;
            this.pos = pos;

            final int numFilterArgs = collector.type().parameterCount();
            final int numAdapterArgs = type().parameterCount();
            collectorRange = Range.of(type(), pos, pos + numFilterArgs);

            range1 = Range.of(type(), 0, pos);
            if (pos + numFilterArgs < numAdapterArgs) {
                this.range2 = Range.of(type(), pos + numFilterArgs, numAdapterArgs);
            } else {
                this.range2 = null;
            }

            // Calculate the number of primitive bytes (or references) we copy to the
            // target frame based on the return value of the combiner.
            final Class<?> collectorRType = collector.type().rtype();
            if (collectorRType == void.class) {
                stackFrameOffset = 0;
                referencesOffset = 0;
            } else if (collectorRType.isPrimitive()) {
                stackFrameOffset = EmulatedStackFrame.getSize(collectorRType);
                referencesOffset = 0;
            } else {
                stackFrameOffset = 0;
                referencesOffset = 1;
            }
        }

        @Override
        public void transform(EmulatedStackFrame stackFrame) throws Throwable {
            // First invoke the collector.
            EmulatedStackFrame filterFrame = EmulatedStackFrame.create(collector.type());
            stackFrame.copyRangeTo(filterFrame, collectorRange, 0, 0);
            collector.invoke(filterFrame);

            // Start constructing the target frame.
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
            stackFrame.copyRangeTo(targetFrame, range1, 0, 0);

            // If one of these offsets is not zero, we have a return value to copy.
            if (referencesOffset != 0 || stackFrameOffset != 0) {
                final StackFrameReader reader = new StackFrameReader();
                reader.attach(filterFrame).makeReturnValueAccessor();
                final StackFrameWriter writer = new StackFrameWriter();
                writer.attach(targetFrame, pos, range1.numReferences, range1.numBytes);
                copyNext(reader, writer, target.type().ptypes()[0]);
            }

            if (range2 != null) {
                stackFrame.copyRangeTo(targetFrame, range2,
                        range1.numReferences + referencesOffset,
                        range2.numBytes + stackFrameOffset);
            }

            target.invoke(targetFrame);
            targetFrame.copyReturnValueTo(stackFrame);
        }
    }

    /**
     * Implements MethodHandles.foldArguments.
     */
    static class FoldArguments extends Transformer {
        private final MethodHandle target;
        private final MethodHandle combiner;

        private final Range combinerArgs;
        private final Range targetArgs;

        private final int referencesOffset;
        private final int stackFrameOffset;

        FoldArguments(MethodHandle target, MethodHandle combiner) {
            super(deriveType(target, combiner));

            this.target = target;
            this.combiner = combiner;

            combinerArgs = Range.all(combiner.type());
            targetArgs = Range.all(type());

            final Class<?> combinerRType = combiner.type().rtype();
            if (combinerRType == void.class) {
                stackFrameOffset = 0;
                referencesOffset = 0;
            } else if (combinerRType.isPrimitive()) {
                stackFrameOffset = EmulatedStackFrame.getSize(combinerRType);
                referencesOffset = 0;
            } else {
                stackFrameOffset = 0;
                referencesOffset = 1;
            }
        }

        @Override
        public void transform(EmulatedStackFrame stackFrame) throws Throwable {
            // First construct the combiner frame and invoke it.
            EmulatedStackFrame combinerFrame = EmulatedStackFrame.create(combiner.type());
            stackFrame.copyRangeTo(combinerFrame, combinerArgs, 0, 0);
            combiner.invoke(combinerFrame);

            // Create the stack frame for the target.
            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());

            // If one of these offsets is not zero, we have a return value to copy.
            if (referencesOffset != 0 || stackFrameOffset != 0) {
                final StackFrameReader reader = new StackFrameReader();
                reader.attach(combinerFrame).makeReturnValueAccessor();
                final StackFrameWriter writer = new StackFrameWriter();
                writer.attach(targetFrame);
                copyNext(reader, writer, target.type().ptypes()[0]);
            }

            stackFrame.copyRangeTo(targetFrame, targetArgs, referencesOffset, stackFrameOffset);
            target.invoke(targetFrame);

            targetFrame.copyReturnValueTo(stackFrame);
        }

        private static MethodType deriveType(MethodHandle target, MethodHandle combiner) {
            if (combiner.type().rtype() == void.class) {
                return target.type();
            }

            return target.type().dropParameterTypes(0, 1);
        }
    }

    /**
     * Implements MethodHandles.insertArguments.
     */
    static class InsertArguments extends Transformer {
        private final MethodHandle target;
        private final int pos;
        private final Object[] values;

        private final Range range1;
        private final Range range2;

        InsertArguments(MethodHandle target, int pos, Object[] values) {
            super(target.type().dropParameterTypes(pos, pos + values.length));
            this.target = target;
            this.pos = pos;
            this.values = values;

            final MethodType type = type();
            range1 = EmulatedStackFrame.Range.of(type, 0, pos);
            range2 = Range.of(type, pos, type.parameterCount());
        }

        @Override
        public void transform(EmulatedStackFrame stackFrame) throws Throwable {
            EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(target.type());

            // Copy all arguments before |pos|.
            stackFrame.copyRangeTo(calleeFrame, range1, 0, 0);

            // Attach a stack frame writer so that we can copy the next |values.length|
            // arguments.
            final StackFrameWriter writer = new StackFrameWriter();
            writer.attach(calleeFrame, pos, range1.numReferences, range1.numBytes);

            // Copy all the arguments supplied in |values|.
            int referencesCopied = 0;
            int bytesCopied = 0;
            final Class<?>[] ptypes = target.type().ptypes();
            for (int i = 0; i < values.length; ++i) {
                final Class<?> ptype = ptypes[i + pos];
                if (ptype.isPrimitive()) {
                    if (ptype == boolean.class) {
                        writer.putNextBoolean((boolean) values[i]);
                    } else if (ptype == byte.class) {
                        writer.putNextByte((byte) values[i]);
                    } else if (ptype == char.class) {
                        writer.putNextChar((char) values[i]);
                    } else if (ptype == short.class) {
                        writer.putNextShort((short) values[i]);
                    } else if (ptype == int.class) {
                        writer.putNextInt((int) values[i]);
                    } else if (ptype == long.class) {
                        writer.putNextLong((long) values[i]);
                    } else if (ptype == float.class) {
                        writer.putNextFloat((float) values[i]);
                    } else if (ptype == double.class) {
                        writer.putNextDouble((double) values[i]);
                    }

                    bytesCopied += EmulatedStackFrame.getSize(ptype);
                } else {
                    writer.putNextReference(values[i], ptype);
                    referencesCopied++;
                }
            }

            // Copy all remaining arguments.
            if (range2 != null) {
                stackFrame.copyRangeTo(calleeFrame, range2,
                        range1.numReferences + referencesCopied,
                        range1.numBytes + bytesCopied);
            }

            target.invoke(calleeFrame);
            calleeFrame.copyReturnValueTo(stackFrame);
        }
    }
}
