nativecodecompiler.java

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

JAVA
289
字号
/**
 * $Id: NativeCodeCompiler.java,v 1.6 2004/02/26 10:33:38 epr Exp $
 */
package org.jnode.vm.compiler;

import java.util.Iterator;

import org.jnode.assembler.Label;
import org.jnode.assembler.NativeStream;
import org.jnode.assembler.ObjectResolver;
import org.jnode.assembler.UnresolvedObjectRefException;
import org.jnode.vm.Address;
import org.jnode.vm.VmSystemObject;
import org.jnode.vm.bytecode.BasicBlock;
import org.jnode.vm.bytecode.ControlFlowGraph;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmAddressMap;
import org.jnode.vm.classmgr.VmByteCode;
import org.jnode.vm.classmgr.VmCompiledCode;
import org.jnode.vm.classmgr.VmCompiledExceptionHandler;
import org.jnode.vm.classmgr.VmConstClass;
import org.jnode.vm.classmgr.VmMethod;

/**
 * Abstract native code compiler.
 * 
 * @author Ewout Prangsma (epr@users.sourceforge.net)
 */
public abstract class NativeCodeCompiler extends VmSystemObject {

    /**
     * Compile the given method during bootstrapping
     * 
     * @param method
     * @param os
     * @param level
     *            Optimization level
     */
    public final void compileBootstrap(VmMethod method, NativeStream os,
            int level) {
        int start = os.getLength();
        final CompiledMethod cm;
        final boolean abstractM = method.isAbstract();
        if (abstractM) {
            if (method.isStatic()) { throw new Error("Abstract & static"); }
            if (method.isNative()) { throw new Error("Abstract & native"); }
            cm = doCompileAbstract(method, os, level, true);
            if (cm == null) { return; }
        } else {
            cm = doCompile(method, os, level, true);
        }
        int end = os.getLength();

        final Address nativeCode = (Address) cm.getCodeStart().getObject();
        final VmCompiledExceptionHandler[] eTable;
        final Address defExHandler;
        final VmByteCode bc;
        final VmAddressMap aTable = cm.getAddressTable();

        if (!(method.isNative() || abstractM)) {
            final NativeStream.ObjectRef defExHRef = cm
                    .getDefExceptionHandler();
            if (defExHRef != null) {
                defExHandler = (Address) defExHRef.getObject();
            } else {
                defExHandler = null;
            }
            bc = method.getBytecode();
            final CompiledExceptionHandler[] ceh = cm.getExceptionHandlers();
            if (ceh != null) {
                eTable = new VmCompiledExceptionHandler[ ceh.length];
                for (int i = 0; i < ceh.length; i++) {

                    final VmConstClass catchType = bc.getExceptionHandler(i)
                            .getCatchType();
                    final Address startPtr = (Address) ceh[ i].getStartPc()
                            .getObject();
                    final Address endPtr = (Address) ceh[ i].getEndPc()
                            .getObject();
                    final Address handler = (Address) ceh[ i].getHandler()
                            .getObject();
                    eTable[ i] = new VmCompiledExceptionHandler(catchType,
                            startPtr, endPtr, handler);
                }
            } else {
                eTable = null;
            }
        } else {
            eTable = null;
            defExHandler = null;
            bc = null;
        }

        method.addCompiledCode(new VmCompiledCode(this, bc, nativeCode, null,
                end - start, eTable, defExHandler, aTable), level);
    }

    /**
     * Compile the given method during runtime.
     * 
     * @param method
     * @param resolver
     * @param level
     *            Optimization level
     * @param os
     *            The native stream, can be null
     */
    public void compileRuntime(VmMethod method, ObjectResolver resolver,
            int level, NativeStream os) {

        if (method.isNative()) { throw new IllegalArgumentException(
                "Cannot compile native methods"); }

        //long start = System.currentTimeMillis();

        //System.out.println("Compiling " + method);

        if (os == null) {
            os = createNativeStream(resolver);
        }
        final CompiledMethod cm;
        if (method.isAbstract()) {
            cm = doCompileAbstract(method, os, level, false);
            if (cm == null) { return; }
        } else {
            cm = doCompile(method, os, level, false);
        }

        try {
            final int startOffset = cm.getCodeStart().getOffset();
            final int size = cm.getCodeEnd().getOffset() - startOffset;
            final byte[] code = new byte[ size];
            System.arraycopy(os.getBytes(), startOffset, code, 0, size);
            final Address codePtr = resolver.addressOfArrayData(code);

            final NativeStream.ObjectRef defExHRef = cm
                    .getDefExceptionHandler();
            final Address defExHandler;
            if (defExHRef != null) {
                defExHandler = resolver.add(codePtr, cm
                        .getDefExceptionHandler().getOffset()
                        - startOffset);
            } else {
                defExHandler = null;
            }
            final VmCompiledExceptionHandler[] eTable;
            final VmAddressMap aTable = cm.getAddressTable();

            final VmByteCode bc = method.getBytecode();
            final CompiledExceptionHandler[] ceh = cm.getExceptionHandlers();
            if (ceh != null) {
                eTable = new VmCompiledExceptionHandler[ ceh.length];
                for (int i = 0; i < ceh.length; i++) {

                    final VmConstClass catchType = bc.getExceptionHandler(i)
                            .getCatchType();
                    final Address startPtr = Address.add(codePtr, ceh[ i]
                            .getStartPc().getOffset()
                            - startOffset);
                    final Address endPtr = Address.add(codePtr, ceh[ i]
                            .getEndPc().getOffset()
                            - startOffset);
                    final Address handler = Address.add(codePtr, ceh[ i]
                            .getHandler().getOffset()
                            - startOffset);

                    eTable[ i] = new VmCompiledExceptionHandler(catchType,
                            startPtr, endPtr, handler);
                }
            } else {
                eTable = null;
            }

            method.addCompiledCode(new VmCompiledCode(this, bc, codePtr, code,
                    size, eTable, defExHandler, aTable), level);

            // For debugging only
            //System.out.println("Code: " + NumberUtils.hex(code));
            //System.out.println();
            //End of debugging only
        } catch (UnresolvedObjectRefException ex) {
            throw new CompileError(ex);
        }

        if (os.hasUnresolvedObjectRefs()) { throw new CompileError(
                "Unresolved labels after compile!"); }
    }

    /**
     * Create a native stream for the current architecture.
     * 
     * @param resolver
     * @return NativeStream
     */
    public abstract NativeStream createNativeStream(ObjectResolver resolver);

    /**
     * Compile the given method into the given stream.
     * 
     * @param method
     * @param os
     * @param level
     *            Optimization level
     * @param isBootstrap
     * @return The compiled method
     */
    protected CompiledMethod doCompile(VmMethod method, NativeStream os,
            int level, boolean isBootstrap) {
        final CompiledMethod cm = new CompiledMethod(level);
        if (method.isNative()) {
            Object label = new Label(method.getMangledName());
            cm.setCodeStart(os.getObjectRef(label));
        } else {
            // Create the visitor
            final CompilerBytecodeVisitor bcv = createBytecodeVisitor(method,
                    cm, os, level, isBootstrap);
            // Get the bytecode
            final VmByteCode bc = method.getBytecode();
            // 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);
            bcv.startMethod(method);
            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();
            }
            bcv.endMethod();
        }

        return cm;
    }

    /**
     * Compile the given abstract method into the given stream.
     * 
     * @param method
     * @param os
     * @param level
     *            Optimization level
     * @param isBootstrap
     * @return The compiled method
     */
    protected abstract CompiledMethod doCompileAbstract(VmMethod method,
            NativeStream os, int level, boolean isBootstrap);

    /**
     * Create the visitor that converts bytecodes into native code.
     * 
     * @param method
     * @param cm
     * @param os
     * @param level
     * @param isBootstrap
     * @return The new bytecode visitor.
     */
    protected abstract CompilerBytecodeVisitor createBytecodeVisitor(
            VmMethod method, CompiledMethod cm, NativeStream os, int level,
            boolean isBootstrap);

    /**
     * Initialize this compiler
     * 
     * @param loader
     */
    public abstract void initialize(VmClassLoader loader);

    /**
     * Dump compiler statistics to System.out
     */
    public abstract void dumpStatistics();
    
    /**
     * Gets the magic value of this compiler.
     * @see org.jnode.vm.VmStackFrame#MAGIC_COMPILED
     * @see org.jnode.vm.VmStackFrame#MAGIC_INTERPRETED
     * @see org.jnode.vm.VmStackFrame#MAGIC_MASK
     * @return
     */
    public abstract int getMagic();
}

⌨️ 快捷键说明

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