108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver/*
208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * Copyright 2013, Google Inc.
308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * All rights reserved.
408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver *
508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * Redistribution and use in source and binary forms, with or without
608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * modification, are permitted provided that the following conditions are
708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * met:
808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver *
908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver *     * Redistributions of source code must retain the above copyright
1008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * notice, this list of conditions and the following disclaimer.
1108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver *     * Redistributions in binary form must reproduce the above
1208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * copyright notice, this list of conditions and the following disclaimer
1308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * in the documentation and/or other materials provided with the
1408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * distribution.
1508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver *     * Neither the name of Google Inc. nor the names of its
1608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * contributors may be used to endorse or promote products derived from
1708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * this software without specific prior written permission.
1808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver *
1908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver */
3108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
3208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverpackage org.jf.dexlib2.analysis;
3308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
3408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport com.google.common.collect.ImmutableList;
3508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport org.jf.dexlib2.iface.Method;
3608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport org.jf.dexlib2.iface.instruction.InlineIndexInstruction;
3708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport org.jf.dexlib2.iface.instruction.VariableRegisterInstruction;
3808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport org.jf.dexlib2.immutable.ImmutableMethod;
3908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport org.jf.dexlib2.immutable.ImmutableMethodParameter;
4008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruverimport org.jf.dexlib2.immutable.util.ParamUtil;
4108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
429531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruverimport javax.annotation.Nonnull;
4308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
449531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruverpublic abstract class InlineMethodResolver {
459531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    // These are the possible values for the accessFlag field on a resolved inline method
469531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    // We can't use, e.g. AccessFlags.STATIC.value, because we need them to be a constant in order to use them as cases
479531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    // in switch statements
489531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    public static final int STATIC = 0x8; // AccessFlags.STATIC.value;
495fa302678ce3a8e08fa8d2e8dbc5424781e751a6Ben Gruver    public static final int VIRTUAL = 0x1; // AccessFlags.PUBLIC.value;
509531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    public static final int DIRECT = 0x2; // AccessFlags.PRIVATE.value;
519531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver
529531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    @Nonnull
5308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    public static InlineMethodResolver createInlineMethodResolver(int odexVersion) {
5408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        if (odexVersion == 35) {
5508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            return new InlineMethodResolver_version35();
5608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        } else if (odexVersion == 36) {
5708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            return new InlineMethodResolver_version36();
5808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        } else {
5908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            throw new RuntimeException(String.format("odex version %d is not supported yet", odexVersion));
6008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        }
6108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    }
6208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
6308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    protected InlineMethodResolver() {
6408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    }
6508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
669531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    @Nonnull
679531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    private static Method inlineMethod(int accessFlags, @Nonnull String cls, @Nonnull String name,
689531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver                                       @Nonnull String params, @Nonnull String returnType) {
6908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        ImmutableList<ImmutableMethodParameter> paramList = ImmutableList.copyOf(ParamUtil.parseParamString(params));
7008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        return new ImmutableMethod(cls, name, paramList, returnType, accessFlags, null, null);
7108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    }
7208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
739531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver    @Nonnull public abstract Method resolveExecuteInline(@Nonnull AnalyzedInstruction instruction);
7408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
7508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    private static class InlineMethodResolver_version35 extends InlineMethodResolver
7608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    {
7708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        private final Method[] inlineMethods;
7808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
7908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        public InlineMethodResolver_version35() {
8008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            inlineMethods = new Method[] {
8108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"),
8208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "charAt", "I", "C"),
8308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"),
8408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"),
8508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "length", "", "I"),
8608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "I", "I"),
8708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "J", "J"),
8808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "F", "F"),
8908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "D", "D"),
9008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "min", "II", "I"),
9108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "max", "II", "I"),
9208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "sqrt", "D", "D"),
9308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "cos", "D", "D"),
9408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "sin", "D", "D")
9508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            };
9608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        }
9708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
9808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        @Override
999531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver        @Nonnull
1009531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver        public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) {
10108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            InlineIndexInstruction instruction = (InlineIndexInstruction)analyzedInstruction.instruction;
10208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            int inlineIndex = instruction.getInlineIndex();
10308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
10408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            if (inlineIndex < 0 || inlineIndex >= inlineMethods.length) {
10508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                throw new RuntimeException("Invalid inline index: " + inlineIndex);
10608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            }
10708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            return inlineMethods[inlineIndex];
10808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        }
10908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    }
11008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
11108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    private static class InlineMethodResolver_version36 extends InlineMethodResolver
11208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    {
11308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        private final Method[] inlineMethods;
11408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        private final Method indexOfIMethod;
11508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        private final Method indexOfIIMethod;
11608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        private final Method fastIndexOfMethod;
11708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        private final Method isEmptyMethod;
11808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
11908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        public InlineMethodResolver_version36() {
12008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            //The 5th and 6th entries differ between froyo and gingerbread. We have to look at the parameters being
12108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            //passed to distinguish between them.
12208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
12308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            //froyo
12408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            indexOfIMethod = inlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "I", "I");
12508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            indexOfIIMethod = inlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "II", "I");
12608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
12708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            //gingerbread
1289531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver            fastIndexOfMethod = inlineMethod(DIRECT, "Ljava/lang/String;", "fastIndexOf", "II", "I");
12908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            isEmptyMethod = inlineMethod(VIRTUAL, "Ljava/lang/String;", "isEmpty", "", "Z");
13008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
13108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            inlineMethods = new Method[] {
13208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"),
13308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "charAt", "I", "C"),
13408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"),
13508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"),
13608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                //froyo: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "I", "I"),
13708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                //gingerbread: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "fastIndexOf", "II", "I"),
13808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                null,
13908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                //froyo: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "II", "I"),
14008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                //gingerbread: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "isEmpty", "", "Z"),
14108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                null,
14208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(VIRTUAL, "Ljava/lang/String;", "length", "", "I"),
14308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "I", "I"),
14408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "J", "J"),
14508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "F", "F"),
14608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "D", "D"),
14708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "min", "II", "I"),
14808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "max", "II", "I"),
14908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "sqrt", "D", "D"),
15008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "cos", "D", "D"),
15108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Math;", "sin", "D", "D"),
15208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Float;", "floatToIntBits", "F", "I"),
15308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Float;", "floatToRawIntBits", "F", "I"),
15408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Float;", "intBitsToFloat", "I", "F"),
15508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Double;", "doubleToLongBits", "D", "J"),
15608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Double;", "doubleToRawLongBits", "D", "J"),
15708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/Double;", "longBitsToDouble", "J", "D"),
15808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "I", "I"),
15908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "J", "J"),
16008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "F", "F"),
16108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "D", "D"),
16208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "min", "II", "I"),
16308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "max", "II", "I"),
16408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                inlineMethod(STATIC, "Ljava/lang/StrictMath;", "sqrt", "D", "D"),
16508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            };
16608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        }
16708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
16808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        @Override
1699531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver        @Nonnull
1709531284b1b6a29371ae8d8e6cfe3e1f1bfe23296Ben Gruver        public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) {
17108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            InlineIndexInstruction instruction = (InlineIndexInstruction)analyzedInstruction.instruction;
17208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            int inlineIndex = instruction.getInlineIndex();
17308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
17408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            if (inlineIndex < 0 || inlineIndex >= inlineMethods.length) {
17508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                throw new RuntimeException("Invalid method index: " + inlineIndex);
17608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            }
17708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
17808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            if (inlineIndex == 4) {
17908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                int parameterCount = ((VariableRegisterInstruction)instruction).getRegisterCount();
18008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                if (parameterCount == 2) {
18108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                    return indexOfIMethod;
18208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                } else if (parameterCount == 3) {
18308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                    return fastIndexOfMethod;
18408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                } else {
18508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                    throw new RuntimeException("Could not determine the correct inline method to use");
18608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                }
18708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            } else if (inlineIndex == 5) {
18808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                int parameterCount = ((VariableRegisterInstruction)instruction).getRegisterCount();
18908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                if (parameterCount == 3) {
19008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                    return indexOfIIMethod;
19108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                } else if (parameterCount == 1) {
19208637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                    return isEmptyMethod;
19308637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                } else {
19408637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                    throw new RuntimeException("Could not determine the correct inline method to use");
19508637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver                }
19608637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            }
19708637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver
19808637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver            return inlineMethods[inlineIndex];
19908637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver        }
20008637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver    }
20108637a8e1f1dff5a36dbed68e7f4d40e900533cfBen Gruver}
202