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 + -
显示快捷键?