12e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath/*
22e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
32e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
42e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath *
52e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * This code is free software; you can redistribute it and/or modify it
62e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * under the terms of the GNU General Public License version 2 only, as
72e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * published by the Free Software Foundation.  Oracle designates this
82e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * particular file as subject to the "Classpath" exception as provided
92e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * by Oracle in the LICENSE file that accompanied this code.
102e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath *
112e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * This code is distributed in the hope that it will be useful, but WITHOUT
122e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
132e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
142e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * version 2 for more details (a copy is included in the LICENSE file that
152e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * accompanied this code).
162e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath *
172e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * You should have received a copy of the GNU General Public License version
182e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * 2 along with this work; if not, write to the Free Software Foundation,
192e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
202e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath *
212e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
222e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * or visit www.oracle.com if you need additional information or have any
232e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * questions.
242e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath */
252e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
262e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamathpackage java.lang.invoke;
272e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
282e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamathimport sun.invoke.util.Wrapper;
292e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamathimport java.lang.ref.SoftReference;
302e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamathimport static java.lang.invoke.MethodHandleStatics.*;
312e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
322e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath/**
332e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * Shared information for a group of method types, which differ
342e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * only by reference types, and therefore share a common erasure
352e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * and wrapping.
362e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * <p>
372e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * For an empirical discussion of the structure of method types,
382e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
392e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * the thread "Avoiding Boxing" on jvm-languages</a>.
402e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * There are approximately 2000 distinct erased method types in the JDK.
412e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * There are a little over 10 times that number of unerased types.
422e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * No more than half of these are likely to be loaded at once.
432e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath * @author John Rose
442e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath */
452e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamathfinal class MethodTypeForm {
462e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    final int[] argToSlotTable, slotToArgTable;
472e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    final long argCounts;               // packed slot & value counts
482e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    final long primCounts;              // packed prim & double counts
492e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    final MethodType erasedType;        // the canonical erasure
502e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    final MethodType basicType;         // the canonical erasure, with primitives simplified
512e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
522e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // Cached adapter information:
532e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    //
542e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // @Stable final SoftReference<MethodHandle>[] methodHandles;
552e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // static final int  MH_BASIC_INV, MH_NF_INV, MH_UNINIT_CS, MH_LIMIT;
562e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    //
572e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // Cached lambda form information, for basic types only:
582e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // final @Stable SoftReference<LambdaForm>[] lambdaForms;
592e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    //
602e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // Indexes into lambdaForms:
612e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    //
622e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // static final int LF_INVVIRTUAL, LF_INVSTATIC, LF_INVSPECIAL, LF_NEWINVSPECIAL,
632e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // LF_INVINTERFACE, LF_INVSTATIC_INIT, LF_INTERPRET, LF_REBIND, LF_DELEGATE,
642e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // LF_DELEGATE_BLOCK_INLINING, LF_EX_LINKER, LF_EX_INVOKER, LF_GEN_LINKER, LF_GEN_INVOKER,
652e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // LF_CS_LINKER, LF_MH_LINKER, LF_GWC, LF_GWT, LF_LIMIT;
662e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
672e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /** Return the type corresponding uniquely (1-1) to this MT-form.
682e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     *  It might have any primitive returns or arguments, but will have no references except Object.
692e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
702e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public MethodType erasedType() {
712e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return erasedType;
722e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
732e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
742e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /** Return the basic type derived from the erased type of this MT-form.
752e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     *  A basic type is erased (all references Object) and also has all primitive
762e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     *  types (except int, long, float, double, void) normalized to int.
772e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     *  Such basic types correspond to low-level JVM calling sequences.
782e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
792e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public MethodType basicType() {
802e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return basicType;
812e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
822e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
832e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    private boolean assertIsBasicType() {
842e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // primitives must be flattened also
852e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        assert(erasedType == basicType)
862e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                : "erasedType: " + erasedType + " != basicType: " + basicType;
872e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return true;
882e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
892e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
902e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // Android-changed: Removed caches for MethodHandle adaptors / LambdaForms.
912e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    //
922e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // public MethodHandle cachedMethodHandle(int which);
932e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh);
942e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // public LambdaForm cachedLambdaForm(int which);
952e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    // synchronized public LambdaForm setCachedLambdaForm(int which, LambdaForm form);
962e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
972e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /**
982e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * Build an MTF for a given type, which must have all references erased to Object.
992e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * This MTF will stand for that type and all un-erased variations.
1002e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * Eagerly compute some basic properties of the type, common to all variations.
1012e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
1022e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    @SuppressWarnings({"rawtypes", "unchecked"})
1032e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    protected MethodTypeForm(MethodType erasedType) {
1042e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        this.erasedType = erasedType;
1052e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
1062e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?>[] ptypes = erasedType.ptypes();
1072e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        int ptypeCount = ptypes.length;
1082e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        int pslotCount = ptypeCount;            // temp. estimate
1092e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        int rtypeCount = 1;                     // temp. estimate
1102e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        int rslotCount = 1;                     // temp. estimate
1112e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
1122e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        int[] argToSlotTab = null, slotToArgTab = null;
1132e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
1142e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // Walk the argument types, looking for primitives.
1152e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        int pac = 0, lac = 0, prc = 0, lrc = 0;
1162e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?>[] epts = ptypes;
1172e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?>[] bpts = epts;
1182e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        for (int i = 0; i < epts.length; i++) {
1192e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            Class<?> pt = epts[i];
1202e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            if (pt != Object.class) {
1212e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                ++pac;
1222e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                Wrapper w = Wrapper.forPrimitiveType(pt);
1232e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                if (w.isDoubleWord())  ++lac;
1242e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                if (w.isSubwordOrInt() && pt != int.class) {
1252e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    if (bpts == epts)
1262e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                        bpts = bpts.clone();
1272e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    bpts[i] = int.class;
1282e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                }
1292e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
1302e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
1312e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        pslotCount += lac;                  // #slots = #args + #longs
1322e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?> rt = erasedType.returnType();
1332e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?> bt = rt;
1342e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (rt != Object.class) {
1352e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            ++prc;          // even void.class counts as a prim here
1362e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            Wrapper w = Wrapper.forPrimitiveType(rt);
1372e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            if (w.isDoubleWord())  ++lrc;
1382e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            if (w.isSubwordOrInt() && rt != int.class)
1392e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                bt = int.class;
1402e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // adjust #slots, #args
1412e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            if (rt == void.class)
1422e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                rtypeCount = rslotCount = 0;
1432e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            else
1442e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                rslotCount += lrc;
1452e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
1462e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (epts == bpts && bt == rt) {
1472e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            this.basicType = erasedType;
1482e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else {
1492e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            this.basicType = MethodType.makeImpl(bt, bpts, true);
1502e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // fill in rest of data from the basic type:
1512e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            MethodTypeForm that = this.basicType.form();
1522e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            assert(this != that);
1532e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            this.primCounts = that.primCounts;
1542e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            this.argCounts = that.argCounts;
1552e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            this.argToSlotTable = that.argToSlotTable;
1562e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            this.slotToArgTable = that.slotToArgTable;
1572e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // Android-changed: Removed cached adaptors / lambda forms.
1582e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            //
1592e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // this.methodHandles = null;
1602e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // this.lambdaForms = null;
1612e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            return;
1622e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
1632e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (lac != 0) {
1642e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            int slot = ptypeCount + lac;
1652e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            slotToArgTab = new int[slot+1];
1662e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            argToSlotTab = new int[1+ptypeCount];
1672e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
1682e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            for (int i = 0; i < epts.length; i++) {
1692e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                Class<?> pt = epts[i];
1702e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                Wrapper w = Wrapper.forBasicType(pt);
1712e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                if (w.isDoubleWord())  --slot;
1722e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                --slot;
1732e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
1742e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                argToSlotTab[1+i]  = slot;
1752e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
1762e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            assert(slot == 0);  // filled the table
1772e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else if (pac != 0) {
1782e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // have primitives but no long primitives; share slot counts with generic
1792e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            assert(ptypeCount == pslotCount);
1802e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
1812e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            assert(this != that);
1822e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            slotToArgTab = that.slotToArgTable;
1832e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            argToSlotTab = that.argToSlotTable;
1842e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else {
1852e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            int slot = ptypeCount; // first arg is deepest in stack
1862e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            slotToArgTab = new int[slot+1];
1872e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            argToSlotTab = new int[1+ptypeCount];
1882e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
1892e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            for (int i = 0; i < ptypeCount; i++) {
1902e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                --slot;
1912e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
1922e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                argToSlotTab[1+i]  = slot;
1932e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
1942e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
1952e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        this.primCounts = pack(lrc, prc, lac, pac);
1962e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
1972e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        this.argToSlotTable = argToSlotTab;
1982e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        this.slotToArgTable = slotToArgTab;
1992e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2002e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
2012e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2022e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // Initialize caches, but only for basic types
2032e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        assert(basicType == erasedType);
2042e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // Android-changed: Removed cached adaptors / lambda forms.
2052e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        //
2062e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // this.lambdaForms   = new SoftReference[LF_LIMIT];
2072e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // this.methodHandles = new SoftReference[MH_LIMIT];
2082e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2092e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2102e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    private static long pack(int a, int b, int c, int d) {
2112e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        assert(((a|b|c|d) & ~0xFFFF) == 0);
2122e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        long hw = ((a << 16) | b), lw = ((c << 16) | d);
2132e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return (hw << 32) | lw;
2142e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2152e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
2162e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        assert(word <= 3);
2172e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return (char)(packed >> ((3-word) * 16));
2182e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2192e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2202e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int parameterCount() {                      // # outgoing values
2212e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(argCounts, 3);
2222e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2232e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int parameterSlotCount() {                  // # outgoing interpreter slots
2242e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(argCounts, 2);
2252e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2262e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int returnCount() {                         // = 0 (V), or 1
2272e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(argCounts, 1);
2282e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2292e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
2302e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(argCounts, 0);
2312e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2322e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int primitiveParameterCount() {
2332e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(primCounts, 3);
2342e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2352e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int longPrimitiveParameterCount() {
2362e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(primCounts, 2);
2372e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2382e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int primitiveReturnCount() {                // = 0 (obj), or 1
2392e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(primCounts, 1);
2402e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2412e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
2422e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return unpack(primCounts, 0);
2432e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2442e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public boolean hasPrimitives() {
2452e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return primCounts != 0;
2462e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2472e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public boolean hasNonVoidPrimitives() {
2482e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (primCounts == 0)  return false;
2492e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (primitiveParameterCount() != 0)  return true;
2502e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return (primitiveReturnCount() != 0 && returnCount() != 0);
2512e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2522e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public boolean hasLongPrimitives() {
2532e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
2542e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2552e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int parameterToArgSlot(int i) {
2562e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return argToSlotTable[1+i];
2572e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2582e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public int argSlotToParameter(int argSlot) {
2592e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // Note:  Empty slots are represented by zero in this table.
2602e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // Valid arguments slots contain incremented entries, so as to be non-zero.
2612e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // We return -1 the caller to mean an empty slot.
2622e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return slotToArgTable[argSlot] - 1;
2632e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2642e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2652e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    static MethodTypeForm findForm(MethodType mt) {
2662e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        MethodType erased = canonicalize(mt, ERASE, ERASE);
2672e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (erased == null) {
2682e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // It is already erased.  Make a new MethodTypeForm.
2692e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            return new MethodTypeForm(mt);
2702e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else {
2712e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // Share the MethodTypeForm with the erased version.
2722e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            return erased.form();
2732e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
2742e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
2752e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2762e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /** Codes for {@link #canonicalize(java.lang.Class, int)}.
2772e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * ERASE means change every reference to {@code Object}.
2782e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * WRAP means convert primitives (including {@code void} to their
2792e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * corresponding wrapper types.  UNWRAP means the reverse of WRAP.
2802e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * INTS means convert all non-void primitive types to int or long,
2812e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * according to size.  LONGS means convert all non-void primitives
2822e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * to long, regardless of size.  RAW_RETURN means convert a type
2832e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * (assumed to be a return type) to int if it is smaller than an int,
2842e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * or if it is void.
2852e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
2862e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
2872e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
2882e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /** Canonicalize the types in the given method type.
2892e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * If any types change, intern the new type, and return it.
2902e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     * Otherwise return null.
2912e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
2922e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
2932e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?>[] ptypes = mt.ptypes();
2942e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?>[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs);
2952e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?> rtype = mt.returnType();
2962e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
2972e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (ptc == null && rtc == null) {
2982e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // It is already canonical.
2992e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            return null;
3002e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
3012e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // Find the erased version of the method type:
3022e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (rtc == null)  rtc = rtype;
3032e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (ptc == null)  ptc = ptypes;
3042e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return MethodType.makeImpl(rtc, ptc, true);
3052e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
3062e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
3072e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /** Canonicalize the given return or param type.
3082e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     *  Return null if the type is already canonicalized.
3092e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
3102e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    static Class<?> canonicalize(Class<?> t, int how) {
3112e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?> ct;
3122e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        if (t == Object.class) {
3132e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // no change, ever
3142e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else if (!t.isPrimitive()) {
3152e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            switch (how) {
3162e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case UNWRAP:
3172e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    ct = Wrapper.asPrimitiveType(t);
3182e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    if (ct != t)  return ct;
3192e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    break;
3202e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case RAW_RETURN:
3212e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case ERASE:
3222e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return Object.class;
3232e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
3242e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else if (t == void.class) {
3252e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // no change, usually
3262e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            switch (how) {
3272e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case RAW_RETURN:
3282e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return int.class;
3292e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case WRAP:
3302e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return Void.class;
3312e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
3322e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        } else {
3332e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            // non-void primitive
3342e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            switch (how) {
3352e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case WRAP:
3362e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return Wrapper.asWrapperType(t);
3372e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case INTS:
3382e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    if (t == int.class || t == long.class)
3392e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                        return null;  // no change
3402e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    if (t == double.class)
3412e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                        return long.class;
3422e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return int.class;
3432e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case LONGS:
3442e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    if (t == long.class)
3452e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                        return null;  // no change
3462e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return long.class;
3472e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                case RAW_RETURN:
3482e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    if (t == int.class || t == long.class ||
3492e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                        t == float.class || t == double.class)
3502e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                        return null;  // no change
3512e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    // everything else returns as an int
3522e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    return int.class;
3532e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
3542e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
3552e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        // no change; return null to signify
3562e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return null;
3572e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
3582e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
3592e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    /** Canonicalize each param type in the given array.
3602e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     *  Return null if all types are already canonicalized.
3612e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath     */
3622e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    static Class<?>[] canonicalizeAll(Class<?>[] ts, int how) {
3632e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        Class<?>[] cs = null;
3642e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        for (int imax = ts.length, i = 0; i < imax; i++) {
3652e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            Class<?> c = canonicalize(ts[i], how);
3662e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            if (c == void.class)
3672e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                c = null;  // a Void parameter was unwrapped to void; ignore
3682e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            if (c != null) {
3692e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                if (cs == null)
3702e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                    cs = ts.clone();
3712e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath                cs[i] = c;
3722e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath            }
3732e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        }
3742e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return cs;
3752e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
3762e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath
3772e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    @Override
3782e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    public String toString() {
3792e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath        return "Form"+erasedType;
3802e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath    }
3812e439dc50d112c37a4def2d60e3d937a89bfe6caNarayan Kamath}
382