Package alt.jiapi.reflect

Source Code of alt.jiapi.reflect.InstructionFactory

package alt.jiapi.reflect;

import java.lang.reflect.Modifier;
import java.util.List;

import alt.jiapi.file.ConstantPool;
import alt.jiapi.file.ConstantPool.ClassInfo;
import alt.jiapi.file.Field;
import alt.jiapi.file.Method;

import alt.jiapi.reflect.instruction.CPInstruction;
import alt.jiapi.reflect.instruction.FieldAccess;
import alt.jiapi.reflect.instruction.Invocation;
import alt.jiapi.reflect.instruction.Opcodes;

/**
* Class InstructionFactory.
*
* @author Mika Riekkinen
*/
public class InstructionFactory {
    private ConstantPool cp;

    public InstructionFactory() {
        this.cp = new ConstantPool();
    }


    /**
     */
    InstructionFactory(ConstantPool cp) {
        this.cp = cp;
    }

    /**
     * Parse bytecode and create a List of Instructions out
     * of it.
     *
     * @return a List of Instructions.
     * @exception
     */
    List createInstructionList(byte[] byteCode) {
        InstructionParser ip = new InstructionParser();
        return ip.createInstructionList(byteCode, cp);
    }


    public Instruction pushConstant(float constant) {
        short index = cp.addFloatInfo((int)constant).getEntryIndex();
        byte[] bytes = createLDC(index);
       
        return new CPInstruction(bytes, cp);//new Constant.StringConstant(bytes, index, clazz);
    }

    public Instruction pushConstant(int constant) {
        switch(constant) {
        case 0:
            return new Instruction(new byte[] {Opcodes.ICONST_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.ICONST_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.ICONST_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.ICONST_3});
        case 4:
            return new Instruction(new byte[] {Opcodes.ICONST_4});
        case 5:
            return new Instruction(new byte[] {Opcodes.ICONST_5});
        }

        short index = cp.addIntegerInfo(constant).getEntryIndex();
        byte[] bytes = createLDC(index);
       
        return new CPInstruction(bytes, cp);
    }

    public Instruction pushConstant(String constant) {
        short index = cp.addStringInfo(constant).getEntryIndex();
        byte[] bytes = createLDC(index);
       
        return new CPInstruction(bytes, cp);//new Constant.StringConstant(bytes, index, clazz);
    }

    public Instruction newClass(String className) {
        short index = cp.addClassInfo(className).getEntryIndex();
        byte[] bytes = new byte[3];
        bytes[0] = Opcodes.NEW;
        bytes[1] = (byte) (index >> 8);
        bytes[2] = (byte) (index & 255);

        //return new Instruction(bytes);
        return new CPInstruction(bytes, cp);
    }


    /**
     * Creates a cast.
     * It will create an InstructionList containing:
     * <blockquote>
     * <i>checkcast</i> #ref
     * </blockquote>
     *
     * @param type type of the cast
     * @return an InstructionList
     */
    public Instruction cast(String type) {
        ClassInfo ci = cp.addClassInfo(type);
        short index = ci.getEntryIndex();

        byte[] bytes = new byte[3];
        bytes[0] = Opcodes.CHECKCAST;
        bytes[1] = (byte) (index >> 8);
        bytes[2] = (byte) (index & 255);

        return new CPInstruction(bytes, cp);
    }


    public Instruction pushNull() {
        return new Instruction(new byte[] { Opcodes.ACONST_NULL });
    }

    public Instruction pushThis() {
        return new Instruction(new byte[] { Opcodes.ALOAD_0 });
    }


    public Instruction returnMethod(JiapiMethod jm) {
        String retType = jm.getSignature().getReturnType();
        Instruction ins = null;
       
        if ("void".equals(retType)) {
            ins = new Instruction(new byte[] { Opcodes.RETURN });
        }
        else if ("boolean".equals(retType) ||
                 "int".equals(retType) ||
                 "short".equals(retType) ||
                 "byte".equals(retType)) {
            ins = new Instruction(new byte[] { Opcodes.IRETURN });
        }
        else if ("long".equals(retType)) {
            ins = new Instruction(new byte[] { Opcodes.LRETURN });
        }
        else if ("float".equals(retType)) {
            ins = new Instruction(new byte[] { Opcodes.FRETURN });
        }
        else if ("double".equals(retType)) {
            ins = new Instruction(new byte[] { Opcodes.DRETURN });
        }
        else {
            ins = new Instruction(new byte[] { Opcodes.ARETURN });
        }

        return ins;
    }



    public Instruction invoke(int mods, String className, String methodName,
                              Signature s) {
        short index = ConstantPoolHelper.addMethodReference(cp, className,
                                                            methodName, s);
       
        byte[] bytes;

        if (Modifier.isStatic(mods)) {
            bytes = new byte[3];
            bytes[0] = Opcodes.INVOKESTATIC;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else if (Modifier.isInterface(mods)) {
            bytes = new byte[5];
            bytes[0] = Opcodes.INVOKEINTERFACE;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
            bytes[3] = (byte) s.getParameters().length;
            bytes[4] = (byte) 0;
        }
        else if ("<init>".equals(methodName)) {
            bytes = new byte[3];
            bytes[0] = Opcodes.INVOKESPECIAL;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else {
            bytes = new byte[3];
            bytes[0] = Opcodes.INVOKEVIRTUAL;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }

        Instruction instruction = new Invocation(bytes, cp);

        return instruction;
    }


    public Instruction invoke(JiapiMethod jm) {
        String[] params = jm.getParameterTypeNames();

        short index = ConstantPoolHelper.addReference(cp, jm);

        byte[] bytes;
        int stackUsage = 1 + params.length; // object ref + params

        if (Modifier.isStatic(jm.getModifiers())) {
            bytes = new byte[3];
            bytes[0] = Opcodes.INVOKESTATIC;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else if (Modifier.isInterface(jm.getModifiers())) {
            bytes = new byte[5];
            bytes[0] = Opcodes.INVOKEINTERFACE;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
            bytes[3] = (byte) params.length;
            bytes[4] = (byte) 0;
        }
        else if ("<init>".equals(jm.getName())) {
            bytes = new byte[3];
            bytes[0] = Opcodes.INVOKESPECIAL;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else {
            bytes = new byte[3];
            bytes[0] = Opcodes.INVOKEVIRTUAL;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }

        Instruction instruction = new Invocation(bytes, cp); // new Instruction(bytes);

        return instruction;
    }


    private byte[] createLDC(short index) {
        byte[] bytes;
        if (index > 255) {
            bytes = new byte[3];
            bytes[0] = Opcodes.LDC_W;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else {
            bytes = new byte[2];
            bytes[0] = Opcodes.LDC;
            bytes[1] = (byte)index;
        }

        return bytes;
    }

    private byte[] createLDC_longDouble(short index) {
        byte[] bytes = new byte[3];

        bytes[0] = Opcodes.LDC2_W;
        bytes[1] = (byte) (index >> 8);
        bytes[2] = (byte) (index & 255);

        return bytes;
    }



    public Instruction getField(int modifiers, String className,
                                String fieldName,
                                String fieldType) {
        ConstantPool.ClassInfo ci =
            cp.addClassInfo(className);
        ConstantPool.FieldRefInfo fri =
            cp.addFieldRefInfo(ci, fieldName, fieldType);

        int index = fri.getEntryIndex();
        byte[] bytes = new byte[3];

        if (Modifier.isStatic(modifiers)) {
            bytes[0] = Opcodes.GETSTATIC;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else {
            bytes[0] = Opcodes.GETFIELD;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }

        Instruction instruction = new FieldAccess(bytes, cp);
        return instruction;
    }

    public Instruction getField(JiapiField field) {
        ConstantPool cp =
            field.getDeclaringClass().getConstantPool();

        ConstantPool.ClassInfo ci =
            cp.addClassInfo(field.getDeclaringClass().getName());
        ConstantPool.FieldRefInfo fri =
            cp.addFieldRefInfo(ci, field.getName(), field.getDescriptor());

        int index = fri.getEntryIndex();

        int modifiers = field.getModifiers();
        byte[] bytes = new byte[3];

        if (Modifier.isStatic(modifiers)) {
            bytes[0] = Opcodes.GETSTATIC;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else {
            bytes[0] = Opcodes.GETFIELD;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }

        Instruction instruction = new FieldAccess(bytes, cp);
        return instruction;
    }

    /**
     * Sets a field reference to stack.
     * It will create an InstructionList containing:
     *
     * <blockquote>
     * <i>putstatic</i> #ref
     * </blockquote>
     *
     * if the field is static field or:
     *
     * <blockquote>
     * <i>putfield</i> #ref
     * </blockquote>
     *
     * if the field is an instance field.
     *
     * @param field a JiapiField which will be set
     * @return an InstructionList
     */
    public Instruction setField(JiapiField field) {
        // NOTE: We could return InstructionList
        //       and do a checkcast before putfield or pustatic
        ConstantPool cp =
            field.getDeclaringClass().getConstantPool();

        ConstantPool.ClassInfo ci =
            cp.addClassInfo(field.getDeclaringClass().getName());
        ConstantPool.FieldRefInfo fri =
            cp.addFieldRefInfo(ci, field.getName(), field.getDescriptor());

        int index = fri.getEntryIndex();


        int modifiers = field.getModifiers();
        byte[] bytes = new byte[3];

        if (Modifier.isStatic(modifiers)) {
            bytes[0] = Opcodes.PUTSTATIC;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }
        else {
            bytes[0] = Opcodes.PUTFIELD;
            bytes[1] = (byte) (index >> 8);
            bytes[2] = (byte) (index & 255);
        }

        Instruction instruction = new FieldAccess(bytes, cp);
        return instruction;
    }

   
    public Instruction aload(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.ALOAD_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.ALOAD_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.ALOAD_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.ALOAD_3});
        default:
            return new Instruction(new byte[] {Opcodes.ALOAD, (byte)idx});
        }
    }
   
    public Instruction iload(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.ILOAD_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.ILOAD_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.ILOAD_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.ILOAD_3});
        default:
            return new Instruction(new byte[] {Opcodes.ILOAD, (byte)idx});
        }
    }

    public Instruction lload(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.LLOAD_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.LLOAD_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.LLOAD_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.LLOAD_3});
        default:
            return new Instruction(new byte[] {Opcodes.LLOAD, (byte)idx});
        }
    }

    public Instruction dload(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.DLOAD_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.DLOAD_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.DLOAD_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.DLOAD_3});
        default:
            return new Instruction(new byte[] {Opcodes.DLOAD, (byte)idx});
        }
    }

    public Instruction fload(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.FLOAD_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.FLOAD_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.FLOAD_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.FLOAD_3});
        default:
            return new Instruction(new byte[] {Opcodes.FLOAD, (byte)idx});
        }
    }

    public Instruction astore(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.ASTORE_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.ASTORE_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.ASTORE_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.ASTORE_3});
        default:
            return new Instruction(new byte[] {Opcodes.ASTORE, (byte)idx});
        }
    }

    public Instruction istore(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.ISTORE_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.ISTORE_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.ISTORE_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.ISTORE_3});
        default:
            return new Instruction(new byte[] {Opcodes.ISTORE, (byte)idx});
        }
    }

    public Instruction lstore(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.LSTORE_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.LSTORE_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.LSTORE_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.LSTORE_3});
        default:
            return new Instruction(new byte[] {Opcodes.LSTORE, (byte)idx});
        }
    }

    public Instruction fstore(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.FSTORE_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.FSTORE_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.FSTORE_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.FSTORE_3});
        default:
            return new Instruction(new byte[] {Opcodes.FSTORE, (byte)idx});
        }
    }
   
    public Instruction dstore(int idx) {
        // NOTE: <wide> support missing
        switch(idx) {
        case 0:
            return new Instruction(new byte[] {Opcodes.DSTORE_0});
        case 1:
            return new Instruction(new byte[] {Opcodes.DSTORE_1});
        case 2:
            return new Instruction(new byte[] {Opcodes.DSTORE_2});
        case 3:
            return new Instruction(new byte[] {Opcodes.DSTORE_3});
        default:
            return new Instruction(new byte[] {Opcodes.DSTORE, (byte)idx});
        }
    }

    public Instruction aastore() {
        return new Instruction(new byte[] {Opcodes.AASTORE});
    }

    public Instruction dup() {
        return new Instruction(new byte[] {Opcodes.DUP});
    }
    public Instruction dup2() {
        return new Instruction(new byte[] {Opcodes.DUP2});
    }

    public InstructionList newArray(String type, int size) {
        InstructionList il = new InstructionList(cp);
        il.add(pushConstant(size));

        if (SignatureUtil.isPrimitive(type)) {
            throw new RuntimeException("NOT implemented: new array for primitive types");
        }
        else {
            ClassInfo ci = cp.addClassInfo("java.lang.Object");
            short idx = ci.getEntryIndex();

            il.add(new CPInstruction(new byte[] {Opcodes.ANEWARRAY,
                                                 (byte)(idx >> 8),
                                                 (byte)(idx& 0xff)},
                                     cp));
        }

        return  il;
    }


//     public Instruction objectArrayStore(int idx) {

//     }

//     /**
//      * Swap the top two values on the operand stack.
//      */
//     public Instruction swap() {
//         return new Instruction(new byte[] {Opcodes.SWAP});
//     }
}
TOP

Related Classes of alt.jiapi.reflect.InstructionFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.