x86bytecodevisitor.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 2,035 行 · 第 1/5 页
JAVA
2,035 行
/*
* $Id: X86BytecodeVisitor.java,v 1.29 2004/02/24 08:05:27 epr Exp $
*/
package org.jnode.vm.x86.compiler.l1;
import org.jnode.assembler.Label;
import org.jnode.assembler.NativeStream;
import org.jnode.assembler.UnresolvedObjectRefException;
import org.jnode.assembler.x86.AbstractX86Stream;
import org.jnode.assembler.x86.Register;
import org.jnode.assembler.x86.X86Constants;
import org.jnode.vm.SoftByteCodes;
import org.jnode.vm.bytecode.BasicBlock;
import org.jnode.vm.bytecode.BytecodeParser;
import org.jnode.vm.classmgr.ObjectLayout;
import org.jnode.vm.classmgr.Signature;
import org.jnode.vm.classmgr.TIBLayout;
import org.jnode.vm.classmgr.VmArray;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmConstClass;
import org.jnode.vm.classmgr.VmConstFieldRef;
import org.jnode.vm.classmgr.VmConstIMethodRef;
import org.jnode.vm.classmgr.VmConstMethodRef;
import org.jnode.vm.classmgr.VmConstString;
import org.jnode.vm.classmgr.VmField;
import org.jnode.vm.classmgr.VmInstanceField;
import org.jnode.vm.classmgr.VmInstanceMethod;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmStaticField;
import org.jnode.vm.classmgr.VmStaticMethod;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.classmgr.VmTypeState;
import org.jnode.vm.compiler.CompileError;
import org.jnode.vm.compiler.CompiledMethod;
import org.jnode.vm.compiler.InlineBytecodeVisitor;
import org.jnode.vm.x86.VmX86Architecture;
import org.jnode.vm.x86.compiler.X86CompilerConstants;
import org.jnode.vm.x86.compiler.X86CompilerContext;
import org.jnode.vm.x86.compiler.X86CompilerHelper;
import org.jnode.vm.x86.compiler.X86JumpTable;
/**
* Actual converter from bytecodes to X86 native code.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
class X86BytecodeVisitor extends InlineBytecodeVisitor implements
X86CompilerConstants {
/** The output stream */
private final AbstractX86Stream os;
/** Helper class */
private final X86CompilerHelper helper;
/** The destination compiled method */
private final CompiledMethod cm;
/** Label of current instruction */
private Label curInstrLabel;
/** Length of os at start of method */
private int startOffset;
/** Stackframe utility */
private X86StackFrame stackFrame;
/** Size of an object reference */
private final int slotSize;
/** Current context */
private final X86CompilerContext context;
/** Emit logging info */
private final boolean log;
/** Class loader */
private VmClassLoader loader;
private boolean startOfBB;
private Label endOfInlineLabel;
private int maxLocals;
/**
* Create a new instance
*
* @param outputStream
* @param cm
* @param isBootstrap
* @param context
*/
public X86BytecodeVisitor(NativeStream outputStream, CompiledMethod cm,
boolean isBootstrap, X86CompilerContext context) {
this.os = (AbstractX86Stream) outputStream;
this.context = context;
this.helper = new X86CompilerHelper(os, context, isBootstrap);
this.cm = cm;
this.slotSize = VmX86Architecture.SLOT_SIZE;
this.log = os.isLogEnabled();
}
/**
* @param method
* @see org.jnode.vm.bytecode.BytecodeVisitor#startMethod(org.jnode.vm.classmgr.VmMethod)
*/
public void startMethod(VmMethod method) {
this.maxLocals = method.getBytecode().getNoLocals();
this.loader = method.getDeclaringClass().getLoader();
helper.setMethod(method);
this.startOffset = os.getLength();
this.stackFrame = new X86StackFrame(os, helper, method, context, cm);
stackFrame.emitHeader();
}
/**
* The given basic block is about to start.
*/
public void startBasicBlock(BasicBlock bb) {
if (log) {
os.log("Start of basic block " + bb);
}
helper.reset();
startOfBB = true;
}
/**
* @param address
* @see org.jnode.vm.bytecode.BytecodeVisitor#startInstruction(int)
*/
public void startInstruction(int address) {
this.curInstrLabel = helper.getInstrLabel(address);
if (startOfBB) {
os.setObjectRef(curInstrLabel);
startOfBB = false;
}
final int offset = os.getLength() - startOffset;
cm.add(address, offset);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#endInstruction()
*/
public void endInstruction() {
// Nothing to do here
}
/**
* The started basic block has finished.
*/
public void endBasicBlock() {
if (log) {
os.log("End of basic block");
}
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#endMethod()
*/
public void endMethod() {
stackFrame.emitTrailer(maxLocals);
}
/**
* @param parser
* @see org.jnode.vm.bytecode.BytecodeVisitor#setParser(org.jnode.vm.bytecode.BytecodeParser)
*/
public void setParser(BytecodeParser parser) {
// Nothing to do here
}
/**
* @see org.jnode.vm.compiler.InlineBytecodeVisitor#endInlinedMethod(org.jnode.vm.classmgr.VmMethod)
*/
public void endInlinedMethod(VmMethod previousMethod) {
helper.setMethod(previousMethod);
os.setObjectRef(endOfInlineLabel);
}
/**
* @see org.jnode.vm.compiler.InlineBytecodeVisitor#startInlinedMethod(org.jnode.vm.classmgr.VmMethod,
* int)
*/
public void startInlinedMethod(VmMethod inlinedMethod, int newMaxLocals) {
maxLocals = newMaxLocals;
endOfInlineLabel = new Label(curInstrLabel + "_end_of_inline");
helper.startInlinedMethod(inlinedMethod, curInstrLabel);
}
/**
* @see org.jnode.vm.compiler.InlineBytecodeVisitor#visit_inlinedReturn()
*/
public void visit_inlinedReturn() {
os.writeJMP(endOfInlineLabel);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aaload()
*/
public final void visit_aaload() {
helper.writePOP(T0); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T0);
os.writePUSH(S0, T0, 4, VmArray.DATA_OFFSET * 4);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aastore()
*/
public final void visit_aastore() {
helper.writePOP(T1); // Value
helper.writePOP(T0); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T0);
os.writeMOV(INTSIZE, S0, T0, 4, VmArray.DATA_OFFSET * 4, T1);
helper.writeArrayStoreWriteBarrier(S0, T0, T1, S1);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aconst_null()
*/
public final void visit_aconst_null() {
os.writeMOV_Const(T0, 0);
helper.writePUSH(T0);
}
/**
* @param index
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aload(int)
*/
public final void visit_aload(int index) {
final int ebpOfs = stackFrame.getEbpOffset(index);
os.writeMOV(INTSIZE, T0, FP, ebpOfs);
helper.writePUSH(T0);
}
/**
* @param classRef
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_anewarray(org.jnode.vm.classmgr.VmConstClass)
*/
public final void visit_anewarray(VmConstClass classRef) {
writeResolveAndLoadClassToEAX(classRef, S0);
helper.writePOP(S0); /* Count */
stackFrame.writePushMethodRef();
helper.writePUSH(EAX); /* Class */
helper.writePUSH(S0); /* Count */
helper.invokeJavaMethod(context.getAnewarrayMethod());
/* Result is already push on the stack */
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_areturn()
*/
public final void visit_areturn() {
helper.writePOP(T0);
visit_return();
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_arraylength()
*/
public final void visit_arraylength() {
helper.writePOP(T0); // Arrayref
os.writeMOV(INTSIZE, T1, T0, VmArray.LENGTH_OFFSET * slotSize);
helper.writePUSH(T1);
}
/**
* @param index
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_astore(int)
*/
public final void visit_astore(int index) {
final int ebpOfs = stackFrame.getEbpOffset(index);
helper.writePOP(FP, ebpOfs);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_athrow()
*/
public final void visit_athrow() {
helper.writePOP(T0); // Exception
helper.writeJumpTableCALL(X86JumpTable.VM_ATHROW_OFS);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_baload()
*/
public final void visit_baload() {
helper.writePOP(T1); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T1);
os.writeMOV(BYTESIZE, T0, S0, T1, 1, VmArray.DATA_OFFSET * 4);
os.writeMOVSX(T0, T0, BYTESIZE);
helper.writePUSH(T0);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_bastore()
*/
public final void visit_bastore() {
helper.writePOP(T1); // Value
helper.writePOP(T0); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T0);
os.writeMOV(BYTESIZE, S0, T0, 1, VmArray.DATA_OFFSET * 4, T1);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_caload()
*/
public final void visit_caload() {
helper.writePOP(T1); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T1);
os.writeMOV(WORDSIZE, T0, S0, T1, 2, VmArray.DATA_OFFSET * 4);
os.writeMOVZX(T0, T0, WORDSIZE);
helper.writePUSH(T0);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_castore()
*/
public final void visit_castore() {
helper.writePOP(T1); // Value
helper.writePOP(T0); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T0);
os.writeMOV(WORDSIZE, S0, T0, 2, VmArray.DATA_OFFSET * 4, T1);
}
/**
* @param classRef
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_checkcast(org.jnode.vm.classmgr.VmConstClass)
*/
public final void visit_checkcast(VmConstClass classRef) {
writeResolveAndLoadClassToEAX(classRef, S0);
final Label okLabel = new Label(this.curInstrLabel + "cc-ok");
/* objectref -> ECX (also leave in on the stack */
os.writeMOV(INTSIZE, ECX, SP, 0);
/* Is objectref null? */
os.writeTEST(ECX, ECX);
os.writeJCC(okLabel, X86Constants.JZ);
/* Is instanceof? */
instanceOf(okLabel);
/* Not instanceof */
// Call SoftByteCodes.systemException
helper.writePUSH(SoftByteCodes.EX_CLASSCAST);
helper.writePUSH(0);
helper.invokeJavaMethod(context.getSystemExceptionMethod());
/* Exception in EAX, throw it */
helper.writeJumpTableCALL(X86JumpTable.VM_ATHROW_OFS);
/* Normal exit */
os.setObjectRef(okLabel);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_d2f()
*/
public final void visit_d2f() {
os.writeFLD64(SP, 0);
os.writeLEA(SP, SP, 4);
os.writeFSTP32(SP, 0);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_d2i()
*/
public final void visit_d2i() {
os.writeFLD64(SP, 0);
os.writeLEA(SP, SP, 4);
os.writeFISTP32(SP, 0);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_d2l()
*/
public final void visit_d2l() {
os.writeFLD64(SP, 0);
os.writeFISTP64(SP, 0);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dadd()
*/
public final void visit_dadd() {
os.writeFLD64(SP, 8);
os.writeFADD64(SP, 0);
os.writeLEA(SP, SP, 8);
os.writeFSTP64(SP, 0);
}
/**
* @see org.jnode.vm.bytecode.BytecodeVisitor#visit_daload()
*/
public final void visit_daload() {
helper.writePOP(T0); // Index
helper.writePOP(S0); // Arrayref
checkBounds(S0, T0);
os.writeLEA(S0, S0, T0, 8, VmArray.DATA_OFFSET * 4);
os.writeMOV(INTSIZE, T0, S0, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?