inliningbytecodevisitor.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 217 行

JAVA
217
字号
/*
 * $Id: InliningBytecodeVisitor.java,v 1.5 2004/02/20 08:21:00 epr Exp $
 */
package org.jnode.vm.compiler;

import java.util.Iterator;

import org.jnode.vm.bytecode.BasicBlock;
import org.jnode.vm.bytecode.ControlFlowGraph;
import org.jnode.vm.classmgr.VmByteCode;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmConstMethodRef;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmPrimitiveClass;
import org.jnode.vm.classmgr.VmType;

/**
 * @author Ewout Prangsma (epr@users.sourceforge.net)
 */
public class InliningBytecodeVisitor extends DelegatingCompilerBytecodeVisitor {

    /** Maximum length of methods that will be inlined */ 
    private static final int SIZE_LIMIT = 32;
    
    /** The classloader */
    private final VmClassLoader loader;
    /** The method that is being visited (not the inlined method!) */
    private VmMethod method;
    /** The original max locals of method */
    private int origMaxLocals;
    /** The current max locals of method (adjusted for inlined methods) */
    private int maxLocals;
    

    /**
     * Initialize this instance.
     * 
     * @param delegate
     * @param loader
     */
    public InliningBytecodeVisitor(InlineBytecodeVisitor delegate,
            VmClassLoader loader) {
        super(delegate);
        this.loader = loader;
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#startMethod(org.jnode.vm.classmgr.VmMethod)
     */
    public void startMethod(VmMethod method) {
        this.method = method;
        this.origMaxLocals = method.getBytecode().getNoLocals();
        this.maxLocals = origMaxLocals;        
        super.startMethod(method);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_invokespecial(org.jnode.vm.classmgr.VmConstMethodRef)
     */
    public void visit_invokespecial(VmConstMethodRef methodRef) {
        methodRef.resolve(loader);
        final VmMethod im = methodRef.getResolvedVmMethod();
        if (!canInline(im)) {
            // Do not inline this call
            super.visit_invokespecial(methodRef);
        } else {
            inline(im);
        }
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_invokestatic(org.jnode.vm.classmgr.VmConstMethodRef)
     */
    public void visit_invokestatic(VmConstMethodRef methodRef) {
        methodRef.resolve(loader);
        final VmMethod im = methodRef.getResolvedVmMethod();
        if (!canInline(im)) {
            // Do not inline this call
            super.visit_invokestatic(methodRef);
        } else {
            inline(im);
        }
    }
    
    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_invokevirtual(org.jnode.vm.classmgr.VmConstMethodRef)
     */
    public void visit_invokevirtual(VmConstMethodRef methodRef) {
        methodRef.resolve(loader);
        final VmMethod im = methodRef.getResolvedVmMethod();
        if (!canInline(im)) {
            // Do not inline this call
            super.visit_invokevirtual(methodRef);
        } else {
            inline(im);
        }
    }

    /**
     * Inline the given method into the current method
     * @param im
     */
    private void inline(VmMethod im) {
        final InlineBytecodeVisitor ibv = (InlineBytecodeVisitor)getDelegate();
        
		// Get the bytecode
		final VmByteCode bc = im.getBytecode();

		// Calculate the new maxLocals
        maxLocals = Math.max(maxLocals, origMaxLocals + bc.getNoLocals());
        
        // Start the inlining
        ibv.startInlinedMethod(im, maxLocals);
        
        // Store the arguments in the locals of the inlined method
        storeArgumentsToLocals(im, ibv, origMaxLocals);
                
        // Create the inlined bytecode visitor
        final InlinedBytecodeVisitor bcv = new InlinedBytecodeVisitor(ibv, origMaxLocals);
        
		// Create the control flow graph
		ControlFlowGraph cfg = (ControlFlowGraph) bc.getCompilerData();
		if (cfg == null) {
			cfg = new ControlFlowGraph(bc);
			bc.setCompilerData(cfg);
		}
		// Compile the code 1 basic block at a time
		final CompilerBytecodeParser parser = new CompilerBytecodeParser(bc, cfg, bcv);
		for (Iterator i = cfg.basicBlockIterator(); i.hasNext();) {
			final BasicBlock bb = (BasicBlock) i.next();
			bcv.startBasicBlock(bb);
			parser.parse(bb.getStartPC(), bb.getEndPC(), false);
			bcv.endBasicBlock();
		}
        
        // End the inlining
        ibv.endInlinedMethod(this.method);
    }

    /**
     * Pop the method arguments of the stack and store them in locals.
     * @param im
     * @param ibv
     * @param localDelta
     */
    private void storeArgumentsToLocals(VmMethod im, InlineBytecodeVisitor ibv, int localDelta) {        
        final int cnt = im.getNoArguments();
        int local = localDelta + im.getArgSlotCount() - 1;
        /*if (im.isStatic()) {
            local--;
        }*/
        
        for (int i = cnt-1; i >= 0; i--) {
            final VmType argType = im.getArgumentType(i);
            //System.out.println("arg" + i + ": " + argType);
            
            if (argType.isPrimitive()) {
                final VmPrimitiveClass pc = (VmPrimitiveClass)argType;
                if (pc.isWide()) {
                    local--;
                    if (pc.isFloatingPoint()) {
                        // double
                        ibv.visit_dstore(local);
                    } else {
                        // long
                        ibv.visit_lstore(local);                        
                    }
                } else {
                    if (pc.isFloatingPoint()) {
                        // float
                        ibv.visit_fstore(local);
                    } else {
                        // int
                        ibv.visit_istore(local);                        
                    }                    
                }
            } else {
                ibv.visit_astore(local);
            }
            local--;
        }
        
        if (!im.isStatic()) {
            // TODO add nullpointer check
            
            // Store this pointer.
            ibv.visit_astore(local);
        }        
    }
    
    /**
     * Can the given method be inlined?
     * @param method
     * @return
     */
    private boolean canInline(VmMethod method) {
        if (method.isNative() || method.isAbstract() || method.isSynchronized()) {
            return false;
        }
        if (!(method.isFinal() || method.isPrivate() || method.isStatic() || method.getDeclaringClass().isFinal())) {
            return false;
        }
        final VmByteCode bc = method.getBytecode();
        if (bc == null) {
            return false;
        }
        if (bc.getLength() > SIZE_LIMIT) {
            return false;
        }
        if (bc.getNoExceptionHandlers() > 0) {
            return false;
        }
        return true;
    }  
    
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?