169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode.stackmap;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class TypedBlock extends BasicBlock {
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int stackTop, numLocals;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public TypeData[] stackTypes, localsTypes;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // set by a Liveness object.
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // inputs[i] is true if the i-th variable is used within this block.
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean[] inputs;
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // working area for Liveness class.
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean updating;
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int status;
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public byte[] localsUsage;
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Divides the method body into basic blocks.
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The type information of the first block is initialized.
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param optmize       if it is true and the method does not include
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      branches, this method returns null.
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static TypedBlock[] makeBlocks(MethodInfo minfo, CodeAttribute ca,
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                          boolean optimize)
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypedBlock[] blocks = (TypedBlock[])new Maker().make(minfo);
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (optimize && blocks.length < 2)
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (blocks.length == 0 || blocks[0].incoming == 0)
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return null;
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool pool = minfo.getConstPool();
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean isStatic = (minfo.getAccessFlags() & AccessFlag.STATIC) != 0;
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        blocks[0].initFirstBlock(ca.getMaxStack(), ca.getMaxLocals(),
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                 pool.getClassName(), minfo.getDescriptor(),
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                 isStatic, minfo.isConstructor());
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        new Liveness().compute(ca.iterator(), blocks, ca.getMaxLocals(),
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                               blocks[0].localsTypes);
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return blocks;
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected TypedBlock(int pos) {
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(pos);
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        localsTypes = null;
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        inputs = null;
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        updating = false;
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void toString2(StringBuffer sbuf) {
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super.toString2(sbuf);
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        sbuf.append(",\n stack={");
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        printTypes(sbuf, stackTop, stackTypes);
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        sbuf.append("}, locals={");
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        printTypes(sbuf, numLocals, localsTypes);
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        sbuf.append("}, inputs={");
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (inputs != null)
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < inputs.length; i++)
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(inputs[i] ? "1, " : "0, ");
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        sbuf.append('}');
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void printTypes(StringBuffer sbuf, int size,
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            TypeData[] types) {
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (types == null)
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < size; i++) {
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (i > 0)
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(", ");
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypeData td = types[i];
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(td == null ? "<>" : td.toString());
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean alreadySet() {
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return localsTypes != null;
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setStackMap(int st, TypeData[] stack, int nl, TypeData[] locals)
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        stackTop = st;
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        stackTypes = stack;
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        numLocals = nl;
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        localsTypes = locals;
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Computes the correct value of numLocals.
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void resetNumLocals() {
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (localsTypes != null) {
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int nl = localsTypes.length;
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            while (nl > 0 && localsTypes[nl - 1] == TypeTag.TOP) {
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (nl > 1) {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    TypeData td = localsTypes[nl - 2];
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (td == TypeTag.LONG || td == TypeTag.DOUBLE)
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        break;
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                --nl;
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            numLocals = nl;
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class Maker extends BasicBlock.Maker {
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected BasicBlock makeBlock(int pos) {
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new TypedBlock(pos);
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected BasicBlock[] makeArray(int size) {
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new TypedBlock[size];
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Initializes the first block by the given method descriptor.
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param block             the first basic block that this method initializes.
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param className         a dot-separated fully qualified class name.
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          For example, <code>javassist.bytecode.stackmap.BasicBlock</code>.
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param methodDesc        method descriptor.
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param isStatic          true if the method is a static method.
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param isConstructor     true if the method is a constructor.
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void initFirstBlock(int maxStack, int maxLocals, String className,
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        String methodDesc, boolean isStatic, boolean isConstructor)
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (methodDesc.charAt(0) != '(')
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new BadBytecode("no method descriptor: " + methodDesc);
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        stackTop = 0;
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        stackTypes = new TypeData[maxStack];
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeData[] locals = new TypeData[maxLocals];
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (isConstructor)
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            locals[0] = new TypeData.UninitThis(className);
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (!isStatic)
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            locals[0] = new TypeData.ClassName(className);
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = isStatic ? -1 : 0;
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = 1;
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            while ((i = descToTag(methodDesc, i, ++n, locals)) > 0)
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (locals[n].is2WordType())
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    locals[++n] = TypeTag.TOP;
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (StringIndexOutOfBoundsException e) {
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new BadBytecode("bad method descriptor: "
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  + methodDesc);
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        numLocals = n;
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        localsTypes = locals;
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static int descToTag(String desc, int i,
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                 int n, TypeData[] types)
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i0 = i;
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int arrayDim = 0;
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char c = desc.charAt(i);
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (c == ')')
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 0;
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (c == '[') {
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ++arrayDim;
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c = desc.charAt(++i);
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (c == 'L') {
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int i2 = desc.indexOf(';', ++i);
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (arrayDim > 0)
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                types[n] = new TypeData.ClassName(desc.substring(i0, ++i2));
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                types[n] = new TypeData.ClassName(desc.substring(i0 + 1, ++i2 - 1)
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                      .replace('/', '.'));
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return i2;
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (arrayDim > 0) {
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            types[n] = new TypeData.ClassName(desc.substring(i0, ++i));
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return i;
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypeData t = toPrimitiveTag(c);
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (t == null)
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new BadBytecode("bad method descriptor: " + desc);
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            types[n] = t;
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return i + 1;
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static TypeData toPrimitiveTag(char c) {
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (c) {
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'Z' :
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'C' :
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'B' :
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'S' :
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'I' :
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return TypeTag.INTEGER;
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'J' :
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return TypeTag.LONG;
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'F' :
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return TypeTag.FLOAT;
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'D' :
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return TypeTag.DOUBLE;
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'V' :
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        default :
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static String getRetType(String desc) {
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = desc.indexOf(')');
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (i < 0)
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "java.lang.Object";
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char c = desc.charAt(i + 1);
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (c == '[')
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return desc.substring(i + 1);
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (c == 'L')
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return desc.substring(i + 2, desc.length() - 1).replace('/', '.');
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return "java.lang.Object";
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
250