Skip to content

Commit

Permalink
Introduce and use x86 JECXZ instruction to reduce cases of testing fo…
Browse files Browse the repository at this point in the history
…r null and then branching (generate a single instruction instead). Rewrite checkcast and instanceof to use for their null tests. This saves 2bytes per instruction and improves throughput by 50% (at the cost of extra latency).
  • Loading branch information
Ian Rogers committed May 26, 2009
1 parent dc32152 commit 887b09c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 41 deletions.
19 changes: 19 additions & 0 deletions rvm/src-generated/ia32-assembler/Assembler.in
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,25 @@ public abstract class Assembler extends AbstractAssembler implements RegisterCon
return r;
}

/**
* Generate a forward JECXZ instruction into the generated code.
* This form is used when the compiler wants to hang onto the
* forward reference object and call resolve on it directly. These
* forward references are not handled by the mechanism in the
* assembler; the client is responsible for calling resolve on the
* reference when generating the target instruction. The baseline
* compiler uses this form for jumps within the machine code for a
* single bytecode.
*/
public final ForwardReference forwardJECXZ () {
int miStart = mi;
ForwardReference r = new ForwardReference.ShortBranch(mi);
setMachineCodes(mi++, (byte)0xE3);
mi += 1; // leave space for displacement
if (lister != null) lister.I(miStart, "JECXZ", 0);
return r;
}

/**
* The set of outstanding forward references. This list is used by
* the assembler to keep track of all outstanding forward
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3331,15 +3331,13 @@ protected final void emit_checkcast_resolvedInterface(RVMClass type) {
int interfaceMask = type.getDoesImplementBitMask();

if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegInd(S0, SP); // load object from stack into S0
asm.emitTEST_Reg_Reg(S0, S0); // test for null
asm.emitMOV_Reg_RegInd(ECX, SP); // load object from stack into ECX
} else {
asm.emitMOV_Reg_RegInd_Quad(S0, SP); // load object from stack into S0
asm.emitTEST_Reg_Reg_Quad(S0, S0); // test for null
asm.emitMOV_Reg_RegInd_Quad(ECX, SP); // load object from stack into RCX
}
ForwardReference isNull = asm.forwardJcc(Assembler.EQ);
ForwardReference isNull = asm.forwardJECXZ(); // forward branch if ECX == 0

baselineEmitLoadTIB(asm, S0, S0); // S0 = TIB of object
baselineEmitLoadTIB(asm, S0, ECX); // S0 = TIB of object
// S0 = implements bit vector
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, S0, Offset.fromIntZeroExtend(TIB_DOES_IMPLEMENT_INDEX << LG_WORDSIZE));
Expand Down Expand Up @@ -3379,15 +3377,13 @@ protected final void emit_checkcast_resolvedClass(RVMClass type) {
int LHSId = type.getId();

if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegInd(S0, SP); // load object from stack
asm.emitTEST_Reg_Reg(S0, S0); // test for null
asm.emitMOV_Reg_RegInd(ECX, SP); // load object from stack
} else {
asm.emitMOV_Reg_RegInd_Quad(S0, SP); // load object from stack
asm.emitTEST_Reg_Reg_Quad(S0, S0); // test for null
asm.emitMOV_Reg_RegInd_Quad(ECX, SP); // load object from stack
}
ForwardReference isNull = asm.forwardJcc(Assembler.EQ);
ForwardReference isNull = asm.forwardJECXZ(); // jump forward if ECX == 0

baselineEmitLoadTIB(asm, S0, S0); // S0 = TIB of object
baselineEmitLoadTIB(asm, S0, ECX); // S0 = TIB of object
// S0 = superclass IDs
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, S0, Offset.fromIntZeroExtend(TIB_SUPERCLASS_IDS_INDEX << LG_WORDSIZE));
Expand Down Expand Up @@ -3424,15 +3420,13 @@ protected final void emit_checkcast_resolvedClass(RVMClass type) {
@Override
protected final void emit_checkcast_final(RVMType type) {
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegInd(S0, SP); // load object from stack
asm.emitTEST_Reg_Reg(S0, S0); // test for null
asm.emitMOV_Reg_RegInd(ECX, SP); // load object from stack
} else {
asm.emitMOV_Reg_RegInd_Quad(S0, SP); // load object from stack
asm.emitTEST_Reg_Reg_Quad(S0, S0); // test for null
asm.emitMOV_Reg_RegInd_Quad(ECX, SP); // load object from stack
}
ForwardReference isNull = asm.forwardJcc(Assembler.EQ);
ForwardReference isNull = asm.forwardJECXZ(); // jump forward if ECX == 0

baselineEmitLoadTIB(asm, S0, S0); // TIB of object
baselineEmitLoadTIB(asm, S0, ECX); // TIB of object
if (VM.BuildFor32Addr) {
asm.emitCMP_Reg_Abs(S0, Magic.getTocPointer().plus(type.getTibOffset()));
} else {
Expand Down Expand Up @@ -3466,15 +3460,10 @@ protected final void emit_instanceof_resolvedInterface(RVMClass type) {
int interfaceIndex = type.getDoesImplementIndex();
int interfaceMask = type.getDoesImplementBitMask();

asm.emitPOP_Reg(S0); // load object from stack
if (VM.BuildFor32Addr) {
asm.emitTEST_Reg_Reg(S0, S0); // test for null
} else {
asm.emitTEST_Reg_Reg_Quad(S0, S0); // test for null
}
ForwardReference isNull = asm.forwardJcc(Assembler.EQ);
asm.emitPOP_Reg(ECX); // load object from stack
ForwardReference isNull = asm.forwardJECXZ(); // test for null

baselineEmitLoadTIB(asm, S0, S0); // S0 = TIB of object
baselineEmitLoadTIB(asm, S0, ECX); // S0 = TIB of object
// S0 = implements bit vector
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, S0, Offset.fromIntZeroExtend(TIB_DOES_IMPLEMENT_INDEX << LG_WORDSIZE));
Expand Down Expand Up @@ -3516,16 +3505,11 @@ protected final void emit_instanceof_resolvedClass(RVMClass type) {
int LHSDepth = type.getTypeDepth();
int LHSId = type.getId();

asm.emitPOP_Reg(S0); // load object from stack
if (VM.BuildFor32Addr) {
asm.emitTEST_Reg_Reg(S0, S0); // test for null
} else {
asm.emitTEST_Reg_Reg_Quad(S0, S0); // test for null
}
ForwardReference isNull = asm.forwardJcc(Assembler.EQ);
asm.emitPOP_Reg(ECX); // load object from stack
ForwardReference isNull = asm.forwardJECXZ(); // test for null

// get superclass display from object's TIB
baselineEmitLoadTIB(asm, S0, S0);
baselineEmitLoadTIB(asm, S0, ECX);
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, S0, Offset.fromIntZeroExtend(TIB_SUPERCLASS_IDS_INDEX << LG_WORDSIZE));
} else {
Expand Down Expand Up @@ -3565,15 +3549,10 @@ protected final void emit_instanceof_resolvedClass(RVMClass type) {
@Override
protected final void emit_instanceof_final(RVMType type) {
asm.emitPOP_Reg(S0); // load object from stack
if (VM.BuildFor32Addr) {
asm.emitTEST_Reg_Reg(S0, S0); // test for null
} else {
asm.emitTEST_Reg_Reg_Quad(S0, S0); // test for null
}
ForwardReference isNull = asm.forwardJcc(Assembler.EQ);
ForwardReference isNull = asm.forwardJECXZ(); // test for null

// compare TIB of object to desired TIB and push true if equal
baselineEmitLoadTIB(asm, S0, S0);
baselineEmitLoadTIB(asm, S0, ECX);
if (VM.BuildFor32Addr) {
asm.emitCMP_Reg_Abs(S0, Magic.getTocPointer().plus(type.getTibOffset()));
} else {
Expand Down

0 comments on commit 887b09c

Please sign in to comment.