Package org.cojen.classfile

Source Code of org.cojen.classfile.AbstractCodeAssembler

/*
*  Copyright 2004-2010 Brian S O'Neill
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

package org.cojen.classfile;

import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.MissingResourceException;

/**
*
*
* @author Brian S O'Neill
*/
public abstract class AbstractCodeAssembler implements CodeAssembler {
    protected AbstractCodeAssembler() {
    }

    public LocalVariable createLocalVariable(TypeDesc type) {
        return createLocalVariable(null, type);
    }

    public void ifComparisonBranch(Location location, String choice, TypeDesc type) {
        boolean trueBranch = false;
        int length = choice.length();
        if (choice.charAt(length - 1) == 't') {
            trueBranch = true;
            choice = choice.substring(0, length - 1);
        }

        choice = choice.intern();

        switch (type.getTypeCode()) {
        default:
            if (choice == "==") {
                ifEqualBranch(location, true);
            } else if (choice == "!=") {
                ifEqualBranch(location, false);
            } else {
                throw new IllegalArgumentException
                    ("Comparison not allowed on object types: " + choice);
            }
            return;

        case TypeDesc.BOOLEAN_CODE:
        case TypeDesc.CHAR_CODE:
        case TypeDesc.BYTE_CODE:
        case TypeDesc.SHORT_CODE:
        case TypeDesc.INT_CODE:
            ifComparisonBranch(location, choice);
            return;

        case TypeDesc.LONG_CODE:
            math(Opcode.LCMP);
            break;

        case TypeDesc.FLOAT_CODE:
            math((choice == (trueBranch ? "<=" : ">") || choice == (trueBranch ? "<" : ">="))
                 ? Opcode.FCMPG : Opcode.FCMPL);
            break;

        case TypeDesc.DOUBLE_CODE:
            math((choice == (trueBranch ? "<=" : ">") || choice == (trueBranch ? "<" : ">="))
                 ? Opcode.DCMPG : Opcode.DCMPL);
            break;
        }

        ifZeroComparisonBranch(location, choice);
    }

    public void inline(Object code) {
        // First load the class for the inlined code.

        Class codeClass = code.getClass();
        String className = codeClass.getName().replace('.', '/') + ".class";
        ClassLoader loader = codeClass.getClassLoader();

        InputStream in;
        if (loader == null) {
            in = ClassLoader.getSystemResourceAsStream(className);
        } else {
            in = loader.getResourceAsStream(className);
        }

        if (in == null) {
            throw new MissingResourceException("Unable to find class file", className, null);
        }

        ClassFile cf;
        try {
            cf = ClassFile.readFrom(in);
        } catch (IOException e) {
            MissingResourceException e2 = new MissingResourceException
                ("Error loading class file: " + e.getMessage(), className, null);
            try {
                e2.initCause(e);
            } catch (NoSuchMethodError e3) {
            }
            throw e2;
        }

        // Now find the single "define" method.
        MethodInfo defineMethod = null;

        MethodInfo[] methods = cf.getMethods();
        for (int i=0; i<methods.length; i++) {
            MethodInfo method = methods[i];
            if ("define".equals(method.getName())) {
                if (defineMethod != null) {
                    throw new IllegalArgumentException("Multiple define methods found");
                } else {
                    defineMethod = method;
                }
            }
        }

        if (defineMethod == null) {
            throw new IllegalArgumentException("No define method found");
        }

        // Copy stack arguments to expected local variables.
        TypeDesc[] paramTypes = defineMethod.getMethodDescriptor().getParameterTypes();
        LocalVariable[] paramVars = new LocalVariable[paramTypes.length];
        for (int i=paramVars.length; --i>=0; ) {
            LocalVariable paramVar = createLocalVariable(paramTypes[i]);
            storeLocal(paramVar);
            paramVars[i] = paramVar;
        }

        Label returnLocation = createLabel();
        CodeDisassembler cd = new CodeDisassembler(defineMethod);
        cd.disassemble(this, paramVars, returnLocation);
        returnLocation.setLocation();
    }

    public void invoke(Method method) {
        TypeDesc ret = TypeDesc.forClass(method.getReturnType());

        Class[] paramClasses = method.getParameterTypes();
        TypeDesc[] params = new TypeDesc[paramClasses.length];
        for (int i=0; i<params.length; i++) {
            params[i] = TypeDesc.forClass(paramClasses[i]);
        }

        Class clazz = method.getDeclaringClass();

        if (Modifier.isStatic(method.getModifiers())) {
            invokeStatic(clazz.getName(),
                         method.getName(),
                         ret,
                         params);
        } else if (clazz.isInterface()) {
            invokeInterface(clazz.getName(),
                            method.getName(),
                            ret,
                            params);
        } else {
            invokeVirtual(clazz.getName(),
                          method.getName(),
                          ret,
                          params);
        }
    }

    public void invokeSuper(Method method) {
        TypeDesc ret = TypeDesc.forClass(method.getReturnType());

        Class[] paramClasses = method.getParameterTypes();
        TypeDesc[] params = new TypeDesc[paramClasses.length];
        for (int i=0; i<params.length; i++) {
            params[i] = TypeDesc.forClass(paramClasses[i]);
        }

        invokeSuper(method.getDeclaringClass().getName(),
                    method.getName(),
                    ret,
                    params);
    }

    public void invoke(Constructor constructor) {
        Class[] paramClasses = constructor.getParameterTypes();
        TypeDesc[] params = new TypeDesc[paramClasses.length];
        for (int i=0; i<params.length; i++) {
            params[i] = TypeDesc.forClass(paramClasses[i]);
        }

        invokeConstructor(constructor.getDeclaringClass().getName().toString(), params);
    }
}
TOP

Related Classes of org.cojen.classfile.AbstractCodeAssembler

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.