x86bytecodevisitor.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 2,035 行 · 第 1/5 页

JAVA
2,035
字号
        final int imtIndex = selector % ObjectLayout.IMT_LENGTH;
        final int argSlotCount = count - 1;
        final Label noCollLabel = new Label(this.curInstrLabel + "NoCollision");
        final Label findSelectorLabel = new Label(this.curInstrLabel
                + "FindSelector");
        final Label endLabel = new Label(this.curInstrLabel + "End");

        // Get objectref -> EBX
        os.writeMOV(INTSIZE, Register.EBX, SP, argSlotCount * slotSize);

        /*
         * // methodRef -> EDX os.writeMOV_Const(Register.EDX, methodRef); //
         * methodRef.selector -> ecx os.writeMOV(INTSIZE, Register.ECX,
         * Register.EDX,
         * context.getVmConstIMethodRefSelectorField().getOffset()); //
         * methodRef.selector -> eax os.writeMOV(INTSIZE, Register.EAX,
         * Register.ECX); // Clear edx os.writeXOR(Register.EDX, Register.EDX); //
         * IMT_LENGTH -> ESI os.writeMOV_Const(Register.ESI,
         * ObjectLayout.IMT_LENGTH); // selector % IMT_LENGTH -> edx
         */
        os.writeMOV_Const(ECX, selector);
        os.writeMOV_Const(EDX, imtIndex);
        // Output: EBX=objectref, ECX=selector, EDX=imtIndex

        /* objectref.TIB -> ebx */
        os.writeMOV(INTSIZE, Register.EBX, Register.EBX, ObjectLayout.TIB_SLOT
                * slotSize);
        /* boolean[] imtCollisions -> esi */
        os.writeMOV(INTSIZE, Register.ESI, Register.EBX,
                (VmArray.DATA_OFFSET + TIBLayout.IMTCOLLISIONS_INDEX)
                        * slotSize);
        /* Has collision at imt[index] ? */
        os.writeMOV(INTSIZE, Register.EAX, Register.ESI, Register.EDX, 1,
                VmArray.DATA_OFFSET * slotSize);
        os.writeTEST_AL(0xFF);
        /* Object[] imt -> esi */
        os.writeMOV(INTSIZE, Register.ESI, Register.EBX,
                (VmArray.DATA_OFFSET + TIBLayout.IMT_INDEX) * slotSize);
        /* selector -> ebx */
        os.writeMOV(INTSIZE, Register.EBX, Register.ECX);

        os.writeJCC(noCollLabel, X86Constants.JZ);

        // We have a collision
        /* imt[index] (=collisionList) -> esi */
        os.writeMOV(INTSIZE, Register.ESI, Register.ESI, Register.EDX, 4,
                VmArray.DATA_OFFSET * slotSize);
        /* collisionList.length -> ecx */
        os.writeMOV(INTSIZE, Register.ECX, Register.ESI, VmArray.LENGTH_OFFSET
                * slotSize);
        /* &collisionList[0] -> esi */
        os.writeLEA(Register.ESI, Register.ESI, VmArray.DATA_OFFSET * slotSize);

        os.setObjectRef(findSelectorLabel);

        /* collisionList[index] -> eax */
        os.writeLODSD();
        /* collisionList[index].selector == selector? */
        os.writeMOV(INTSIZE, Register.EDX, Register.EAX, context
                .getVmMethodSelectorField().getOffset());
        os.writeCMP(Register.EBX, Register.EDX);
        os.writeJCC(endLabel, X86Constants.JE);
        try {
            os.writeLOOP(findSelectorLabel);
        } catch (UnresolvedObjectRefException ex) {
            throw new CompileError(ex);
        }
        /* Force a NPE further on */
        os.writeXOR(Register.EAX, Register.EAX);
        os.writeJMP(endLabel);

        os.setObjectRef(noCollLabel);
        /* imt[index] -> eax */
        os.writeMOV(INTSIZE, Register.EAX, Register.ESI, Register.EDX, 4,
                VmArray.DATA_OFFSET * slotSize);

        os.setObjectRef(endLabel);

        /** Now invoke the method */
        helper.invokeJavaMethod(methodRef.getSignature());
    }

    /**
     * @param methodRef
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_invokespecial(org.jnode.vm.classmgr.VmConstMethodRef)
     */
    public final void visit_invokespecial(VmConstMethodRef methodRef) {
        methodRef.resolve(loader);
        try {
            final VmMethod sm = methodRef.getResolvedVmMethod();
            // Get method from statics table
            helper.writeGetStaticsEntry(curInstrLabel, EAX, sm);
            helper.invokeJavaMethod(methodRef.getSignature());
        } catch (ClassCastException ex) {
            System.out.println(methodRef.getResolvedVmMethod().getClass()
                    .getName()
                    + "#" + methodRef.getName());
            throw ex;
        }

        /*
         * methodRef.resolve(loader);
         * writeResolveAndLoadClassToEAX(methodRef.getConstClass(), S0);
         * writeResolveAndLoadMethodToEAX(methodRef, S0);
         */
    }

    /**
     * @param methodRef
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_invokestatic(org.jnode.vm.classmgr.VmConstMethodRef)
     */
    public final void visit_invokestatic(VmConstMethodRef methodRef) {
        methodRef.resolve(loader);
        final VmStaticMethod sm = (VmStaticMethod) methodRef
                .getResolvedVmMethod();
        // Get method from statics table
        helper.writeGetStaticsEntry(curInstrLabel, EAX, sm);
        helper.invokeJavaMethod(methodRef.getSignature());
    }

    /**
     * @param methodRef
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_invokevirtual(org.jnode.vm.classmgr.VmConstMethodRef)
     */
    public final void visit_invokevirtual(VmConstMethodRef methodRef) {
        methodRef.resolve(loader);
        final VmMethod mts = methodRef.getResolvedVmMethod();
        if (mts.isStatic()) { throw new IncompatibleClassChangeError(
                "Static method in invokevirtual"); }
        final VmInstanceMethod method = (VmInstanceMethod) mts;
        final int tibOffset = method.getTibOffset();
        final int argSlotCount = Signature.getArgSlotCount(methodRef
                .getSignature());

        /* Get objectref -> S0 */
        os.writeMOV(INTSIZE, S0, SP, argSlotCount * slotSize);
        /* Get VMT of objectef -> S0 */
        os.writeMOV(INTSIZE, S0, S0, ObjectLayout.TIB_SLOT * slotSize);
        /* Get entry in VMT -> EAX */
        os.writeMOV(INTSIZE, EAX, S0, (VmArray.DATA_OFFSET + tibOffset)
                * slotSize);
        /* Now invoke the method */
        helper.invokeJavaMethod(methodRef.getSignature());
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ior()
     */
    public final void visit_ior() {
        helper.writePOP(T0); // value2
        helper.writePOP(S0); // value 1
        os.writeOR(S0, T0);
        helper.writePUSH(S0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_irem()
     */
    public final void visit_irem() {
        helper.writePOP(S0); // Value2
        helper.writePOP(EAX); // Value1
        os.writeCDQ();
        os.writeIDIV_EAX(S0); // EAX = EDX:EAX / S0
        helper.writePUSH(EDX); // Remainder
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ireturn()
     */
    public final void visit_ireturn() {
        helper.writePOP(T0);
        visit_return();
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ishl()
     */
    public final void visit_ishl() {
        helper.writePOP(ECX);
        helper.writePOP(EAX);
        os.writeSAL_CL(EAX);
        helper.writePUSH(EAX);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ishr()
     */
    public final void visit_ishr() {
        helper.writePOP(ECX);
        helper.writePOP(EAX);
        os.writeSAR_CL(EAX);
        helper.writePUSH(EAX);
    }

    /**
     * @param index
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_istore(int)
     */
    public final void visit_istore(int index) {
        int ebpOfs = stackFrame.getEbpOffset(index);
        helper.writePOP(FP, ebpOfs);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_isub()
     */
    public final void visit_isub() {
        helper.writePOP(T0);
        helper.writePOP(S0);
        os.writeSUB(S0, T0);
        helper.writePUSH(S0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_iushr()
     */
    public final void visit_iushr() {
        helper.writePOP(Register.ECX);
        helper.writePOP(Register.EAX);
        os.writeSHR_CL(Register.EAX);
        helper.writePUSH(Register.EAX);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ixor()
     */
    public final void visit_ixor() {
        helper.writePOP(T0);
        helper.writePOP(S0);
        os.writeXOR(S0, T0);
        helper.writePUSH(S0);
    }

    /**
     * @param address
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_jsr(int)
     */
    public final void visit_jsr(int address) {
        os.writeCALL(helper.getInstrLabel(address));
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_l2d()
     */
    public final void visit_l2d() {
        os.writeFILD64(SP, 0);
        os.writeFSTP64(SP, 0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_l2f()
     */
    public final void visit_l2f() {
        os.writeFILD64(SP, 0);
        os.writeLEA(SP, SP, 4);
        os.writeFSTP32(SP, 0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_l2i()
     */
    public final void visit_l2i() {
        helper.writePOP64(T0, T1);
        helper.writePUSH(T0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ladd()
     */
    public final void visit_ladd() {
        helper.writePOP64(T0, T1); // Value 2
        helper.writePOP64(S0, S1); // Value 1
        os.writeADD(S0, T0);
        os.writeADC(S1, T1);
        helper.writePUSH64(S0, S1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_laload()
     */
    public final void visit_laload() {
        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);
        os.writeMOV(INTSIZE, T1, S0, 4);
        helper.writePUSH64(T0, T1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_land()
     */
    public final void visit_land() {
        helper.writePOP64(T0, T1); // Value 2
        helper.writePOP64(S0, S1); // Value 1
        os.writeAND(S0, T0);
        os.writeAND(S1, T1);
        helper.writePUSH64(S0, S1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lastore()
     */
    public final void visit_lastore() {
        os.writeMOV(INTSIZE, T0, SP, 8); // Index
        os.writeMOV(INTSIZE, S0, SP, 12); // Arrayref
        checkBounds(S0, T0);
        os.writeLEA(S0, S0, T0, 8, VmArray.DATA_OFFSET * 4);
        helper.writePOP64(T0, T1); // Value
        os.writeMOV(INTSIZE, S0, 0, T0);
        os.writeMOV(INTSIZE, S0, 4, T1);
        os.writeLEA(SP, SP, 8); // Remove index, arrayref
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lcmp()
     */
    public final void visit_lcmp() {
        helper.writePOP64(Register.EBX, Register.ECX); // Value 2
        helper.writePOP64(Register.EAX, Register.EDX); // Value 1

        Label ltLabel = new Label(curInstrLabel + "lt");
        Label endLabel = new Label(curInstrLabel + "end");

        os.writeXOR(Register.ESI, Register.ESI);
        os.writeSUB(Register.EAX, Register.EBX);
        os.writeSBB(Register.EDX, Register.ECX);
        os.writeJCC(ltLabel, X86Constants.JL); // JL
        os.writeOR(Register.EAX, Register.EDX);
        os.writeJCC(endLabel, X86Constants.JZ); // value1 == value2
        /** GT */
        os.writeINC(Register.ESI);
        os.writeJMP(endLabel);
        /** LT */
        os.setObjectRef(ltLabel);
        os.writeDEC(Register.ESI);
        os.setObjectRef(endLabel);
        helper.writePUSH(Register.ESI);
    }

    /**
     * @param v
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lconst(long)
     */
    public final void visit_lconst(long v) {
        final int lsb = (int) (v & 0xFFFFFFFFL);
        final int msb = (int) ((v >>> 32) & 0xFFFFFFFFL);
        //log.debug("lconst v=" + NumberUtils.hex(v,16) + ",lsb=" +
        // NumberUtils.hex(lsb, 8) +
        // ",msb=" + NumberUtils.hex(msb, 8));

        os.writeMOV_Const(T0, lsb);
        os.writeMOV_Const(T1, msb);
        helper.writePUSH64(T0, T1);
    }

    /**
     * @param value
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ldc(VmConstString)
     */
    public final void visit_ldc(VmConstString value) {
        // Get string constant
        helper.writeGetStaticsEntry(curInstrLabel, T0, value);
        helper.writePUSH(T0);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ldiv()
     */
    public final void visit_ldiv() {
        helper.invokeJavaMethod(context.getLdivMethod());
    }

    /**
     * @param index
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lload(int)
     */
    public final void visit_lload(int index) {
        int ebpOfs = stackFrame.getWideEbpOffset(index);
        os.writeMOV(INTSIZE, T0, FP, ebpOfs);
        os.writeMOV(INTSIZE, T1, FP, ebpOfs + 4);
        helper.writePUSH64(T0, T1);
    }

    /**
     * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lmul()
     */
    public final void visit_lmul() {
        helper.writePOP64(Register.EBX, Register.ECX); // Value 2
        helper.writePOP64(Register.ESI, Register.EDI); // Value 1

        Label tmp1 = new Label(curInstrLabel + "$tmp1");
        Label tmp2 = new Label(curInstrLabel + "$tmp2");

        os.writeMOV(INTSIZE, Register.EAX, Register.EDI); // hi2
        os.writeOR(Register.EAX, Register.ECX); // hi1 | hi2
        os.writeJCC(tmp1, X86Constants.JNZ);
        os.writeMOV(INTSIZE, Register.EAX, Register.ESI); // lo2
        os.writeMUL_EAX(Register.EBX); // lo1*lo2
        os.writeJMP(tmp2);
        os.setObjectRef(tmp1);
        os.writeMOV(INTSIZE, Register.EAX, Register.ESI); // lo2
        os.writeMUL_EAX(Register.ECX); // hi1*lo2
        os.writeMOV(INTSIZE, Register.ECX, Register.EAX);
        os.writeMOV(INTSIZE, Register.EAX, Register.EDI); // hi2
        os.writeMUL_EAX(Register.EBX); // hi2*lo1

⌨️ 快捷键说明

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