From: <cap...@us...> - 2008-07-22 15:23:41
|
Revision: 14761 http://jikesrvm.svn.sourceforge.net/jikesrvm/?rev=14761&view=rev Author: captain5050 Date: 2008-07-22 15:23:38 +0000 (Tue, 22 Jul 2008) Log Message: ----------- RVM-592: when converting words into objects add the ability to validate that what is created is a reference. This code refactors base line magic generation so that it maps a method reference to a magic generating class. When validity checks are necessary the magic class is decorated. Using a hash table should be faster than many if statements. Slightly shorter instructions are used for array operations. The code is reorganized in other ways to make the magic implementation easier. Modified Paths: -------------- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java Added Paths: ----------- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineMagic.java Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2008-07-22 15:17:36 UTC (rev 14760) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2008-07-22 15:23:38 UTC (rev 14761) @@ -28,12 +28,7 @@ static void compileArrayStoreBarrier(Assembler asm) { // on entry java stack contains ...|target_array_ref|array_index|ref_to_store| - // SP -> ref_to_store, SP+8 -> target_ref - Offset of8 = Offset.fromIntSignExtend(8); - asm.emitPUSH_RegDisp(SP, of8); - asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 4) - asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 0) - genParameterRegisterLoad(asm, 3); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStoreWriteBarrierMethod.getOffset())); } @@ -47,7 +42,7 @@ asm.emitPUSH_Reg(reg); asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 0) asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 4); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); } @@ -61,7 +56,7 @@ asm.emitPUSH_Imm(fieldOffset.toInt()); asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 0) asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 4); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); } @@ -72,7 +67,7 @@ asm.emitPUSH_Reg(reg); asm.emitPUSH_RegDisp(SP, of4); asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 3); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putstaticWriteBarrierMethod.getOffset())); } @@ -83,14 +78,14 @@ asm.emitPUSH_Imm(fieldOffset.toInt()); asm.emitPUSH_RegDisp(SP, of4); asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 3); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putstaticWriteBarrierMethod.getOffset())); } static void compileArrayLoadBarrier(Assembler asm, boolean pushResult) { // on entry java stack contains ...|target_array_ref|array_index| // SP -> index, SP+4 -> target_ref - genParameterRegisterLoad(asm, 2); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 2); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadReadBarrierMethod.getOffset())); if (pushResult) asm.emitPUSH_Reg(T0); } @@ -101,7 +96,7 @@ genNullCheck(asm, 0); asm.emitPUSH_Reg(reg); asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 3); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.getfieldReadBarrierMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -110,7 +105,7 @@ genNullCheck(asm, 0); asm.emitPUSH_Imm(fieldOffset.toInt()); asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 3); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.getfieldReadBarrierMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -118,7 +113,7 @@ static void compileGetstaticBarrier(Assembler asm, GPR reg, int locationMetadata) { asm.emitPUSH_Reg(reg); asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 2); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 2); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.getstaticReadBarrierMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -126,7 +121,7 @@ static void compileGetstaticBarrierImm(Assembler asm, Offset fieldOffset, int locationMetadata) { asm.emitPUSH_Imm(fieldOffset.toInt()); asm.emitPUSH_Imm(locationMetadata); - genParameterRegisterLoad(asm, 2); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 2); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.getstaticReadBarrierMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -145,26 +140,7 @@ // on entry java stack contains ... [SP+offset] -> target_ref // on exit: stack is the same asm.emitPUSH_RegDisp(SP, Offset.fromIntSignExtend(offset)); // dup - genParameterRegisterLoad(asm, 1); + BaselineCompilerImpl.genParameterRegisterLoad(asm, 1); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.modifyCheckMethod.getOffset())); } - - /** - * (Taken from BaselineCompilerImpl.java) - * - * Copy parameters from operand stack into registers. - * Assumption: parameters are layed out on the stack in order - * with SP pointing to the last parameter. - * Also, this method is called before the generation of a helper method call. - * Assumption: no floating-point parameters. - * @param params number of parameter words (including "this" if any). - */ - private static void genParameterRegisterLoad(Assembler asm, int params) { - if (0 < NUM_PARAMETER_GPRS) { - asm.emitMOV_Reg_RegDisp(T0, SP, Offset.fromIntZeroExtend((params - 1) << LG_WORDSIZE)); - } - if (1 < params && 1 < NUM_PARAMETER_GPRS) { - asm.emitMOV_Reg_RegDisp(T1, SP, Offset.fromIntZeroExtend((params - 2) << LG_WORDSIZE)); - } - } } Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2008-07-22 15:17:36 UTC (rev 14760) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2008-07-22 15:23:38 UTC (rev 14761) @@ -63,12 +63,12 @@ /** Generate array index out of bounds checks? */ private final boolean generateBoundsChecks; - private static final Offset NO_SLOT = Offset.zero(); - private static final Offset ONE_SLOT = NO_SLOT.plus(WORDSIZE); - private static final Offset TWO_SLOTS = ONE_SLOT.plus(WORDSIZE); - private static final Offset THREE_SLOTS = TWO_SLOTS.plus(WORDSIZE); - private static final Offset FOUR_SLOTS = THREE_SLOTS.plus(WORDSIZE); - private static final Offset FIVE_SLOTS = FOUR_SLOTS.plus(WORDSIZE); + static final Offset NO_SLOT = Offset.zero(); + static final Offset ONE_SLOT = NO_SLOT.plus(WORDSIZE); + static final Offset TWO_SLOTS = ONE_SLOT.plus(WORDSIZE); + static final Offset THREE_SLOTS = TWO_SLOTS.plus(WORDSIZE); + static final Offset FOUR_SLOTS = THREE_SLOTS.plus(WORDSIZE); + static final Offset FIVE_SLOTS = FOUR_SLOTS.plus(WORDSIZE); private static final Offset MINUS_ONE_SLOT = NO_SLOT.minus(WORDSIZE); /** @@ -467,10 +467,9 @@ */ @Override protected final void emit_iaload() { - asm.emitMOV_Reg_RegInd(T0, SP); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is array ref - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // push [S0+T0<<2] asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT); } @@ -481,10 +480,9 @@ @Override protected final void emit_faload() { // identical to iaload - code replicated for BaseBase compiler performance - asm.emitMOV_Reg_RegInd(T0, SP); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is array ref - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // push [S0+T0<<2] asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT); } @@ -495,13 +493,13 @@ @Override protected final void emit_aaload() { // identical to iaload - code replicated for BaseBase compiler performance - asm.emitMOV_Reg_RegInd(T0, SP); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is array ref - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (MM_Constants.NEEDS_READ_BARRIER) { + asm.emitADD_Reg_Imm(SP, WORDSIZE * -2); // rewind 2 args on stack Barriers.compileArrayLoadBarrier(asm, true); } else { - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT); // push [S0+T0<<2] } } @@ -511,10 +509,9 @@ */ @Override protected final void emit_caload() { - asm.emitMOV_Reg_RegInd(T0, SP); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is array ref - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // T1 = (int)[S0+T0<<1] asm.emitMOVZX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT); asm.emitPUSH_Reg(T1); // push short onto stack @@ -525,10 +522,9 @@ */ @Override protected final void emit_saload() { - asm.emitMOV_Reg_RegInd(T0, SP); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is array ref - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // T1 = (int)[S0+T0<<1] asm.emitMOVSX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT); asm.emitPUSH_Reg(T1); // push short onto stack @@ -539,13 +535,12 @@ */ @Override protected final void emit_baload() { - asm.emitMOV_Reg_RegInd(T0, SP); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is array ref - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // T1 = (int)[S0+T0<<1] asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT); - asm.emitPUSH_Reg(T1); // push short onto stack + asm.emitPUSH_Reg(T1); // push byte onto stack } /** @@ -553,12 +548,12 @@ */ @Override protected final void emit_laload() { - asm.emitMOV_Reg_RegDisp(T0, SP, NO_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is the array ref - if (!SSE2_BASE) { - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (SSE2_BASE) { + asm.emitADD_Reg_Imm(SP, WORDSIZE * -2); // create space for result } - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (SSE2_BASE) { asm.emitMOVQ_Reg_RegIdx(XMM0, S0, T0, Assembler.LONG, NO_SLOT); asm.emitMOVQ_RegInd_Reg(SP, XMM0); @@ -574,12 +569,12 @@ @Override protected final void emit_daload() { // identical to laload - code replicated for BaseBase compiler performance - asm.emitMOV_Reg_RegDisp(T0, SP, NO_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0 is the array ref - if (!SSE2_BASE) { - asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // complete popping the 2 args + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (SSE2_BASE) { + asm.emitADD_Reg_Imm(SP, WORDSIZE * -2); // create space for result } - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (SSE2_BASE) { asm.emitMOVQ_Reg_RegIdx(XMM0, S0, T0, Assembler.LONG, NO_SLOT); asm.emitMOVQ_RegInd_Reg(SP, XMM0); @@ -599,11 +594,10 @@ @Override protected final void emit_iastore() { Barriers.compileModifyCheck(asm, 8); - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref - asm.emitMOV_Reg_RegInd(T1, SP); // T1 is the byte value - asm.emitADD_Reg_Imm(SP, 3*WORDSIZE); // Shrink stack - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1 } @@ -614,11 +608,10 @@ protected final void emit_fastore() { // identical to iastore - code replicated for BaseBase compiler performance Barriers.compileModifyCheck(asm, 8); - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref - asm.emitMOV_Reg_RegInd(T1, SP); // T1 is the byte value - asm.emitADD_Reg_Imm(SP, 3*WORDSIZE); // Shrink stack - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1 } @@ -631,18 +624,19 @@ Barriers.compileModifyCheck(asm, 8); asm.emitPUSH_RegDisp(SP, TWO_SLOTS); // duplicate array ref asm.emitPUSH_RegDisp(SP, ONE_SLOT); // duplicate object value - genParameterRegisterLoad(2); // pass 2 parameter + genParameterRegisterLoad(asm, 2); // pass 2 parameter // call checkstore(array ref, value) asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.checkstoreMethod.getOffset())); - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is the array ref - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (MM_Constants.NEEDS_WRITE_BARRIER) { + asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index + asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array Barriers.compileArrayStoreBarrier(asm); - asm.emitADD_Reg_Imm(SP, WORDSIZE * 3); // complete popping the 3 args } else { - asm.emitMOV_Reg_RegDisp(T1, SP, NO_SLOT); // T1 is the object value - asm.emitADD_Reg_Imm(SP, WORDSIZE * 3); // complete popping the 3 args + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1 } } @@ -653,11 +647,10 @@ @Override protected final void emit_castore() { Barriers.compileModifyCheck(asm, 8); - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref - asm.emitMOV_Reg_RegInd(T1, SP); // T1 is the char value - asm.emitADD_Reg_Imm(SP, 3*WORDSIZE); // Shrink stack - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // store halfword element into array i.e. [S0 +T0] <- T1 (halfword) asm.emitMOV_RegIdx_Reg_Word(S0, T0, Assembler.SHORT, NO_SLOT, T1); } @@ -669,11 +662,10 @@ protected final void emit_sastore() { // identical to castore - code replicated for BaseBase compiler performance Barriers.compileModifyCheck(asm, 8); - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref - asm.emitMOV_Reg_RegInd(T1, SP); // T1 is the char value - asm.emitADD_Reg_Imm(SP, 3*WORDSIZE); // Shrink stack - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array // store halfword element into array i.e. [S0 +T0] <- T1 (halfword) asm.emitMOV_RegIdx_Reg_Word(S0, T0, Assembler.SHORT, NO_SLOT, T1); } @@ -684,11 +676,10 @@ @Override protected final void emit_bastore() { Barriers.compileModifyCheck(asm, 8); - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // T0 is array index - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref - asm.emitMOV_Reg_RegInd(T1, SP); // T1 is the byte value - asm.emitADD_Reg_Imm(SP, 3*WORDSIZE); // Shrink stack - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array asm.emitMOV_RegIdx_Reg_Byte(S0, T0, Assembler.BYTE, NO_SLOT, T1); // [S0 + T0<<2] <- T1 } @@ -698,15 +689,17 @@ @Override protected final void emit_lastore() { Barriers.compileModifyCheck(asm, 12); - asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T0 is the array index - asm.emitMOV_Reg_RegDisp(S0, SP, THREE_SLOTS); // S0 is the array ref if (SSE2_BASE) { asm.emitMOVQ_Reg_RegInd(XMM0,SP); // XMM0 is the value - asm.emitADD_Reg_Imm(SP, WORDSIZE * 4); // remove index and ref from the stack + asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // remove value from the stack + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref } else { + asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T0 is the array index + asm.emitMOV_Reg_RegDisp(S0, SP, THREE_SLOTS); // S0 is the array ref asm.emitMOV_Reg_RegInd(T1, SP); // low part of long value } - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (SSE2_BASE) { asm.emitMOVQ_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, XMM0); // [S0+T0<<<3] <- XMM0 } else { @@ -726,15 +719,17 @@ protected final void emit_dastore() { // identical to lastore - code replicated for BaseBase compiler performance Barriers.compileModifyCheck(asm, 12); - asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T0 is the array index - asm.emitMOV_Reg_RegDisp(S0, SP, THREE_SLOTS); // S0 is the array ref if (SSE2_BASE) { asm.emitMOVQ_Reg_RegInd(XMM0,SP); // XMM0 is the value - asm.emitADD_Reg_Imm(SP, WORDSIZE * 4); // remove index and ref from the stack + asm.emitADD_Reg_Imm(SP, WORDSIZE * 2); // remove value from the stack + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref } else { + asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T0 is the array index + asm.emitMOV_Reg_RegDisp(S0, SP, THREE_SLOTS); // S0 is the array ref asm.emitMOV_Reg_RegInd(T1, SP); // low part of long value } - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array + if (generateBoundsChecks) genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (SSE2_BASE) { asm.emitMOVQ_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, XMM0); // [S0+T0<<<3] <- XMM0 } else { @@ -1633,7 +1628,7 @@ fr2.resolve(asm); fr4.resolve(asm); } else { - // TODO: use SSE/x87 operations to do this conversion inline taking care of + // TODO: use x87 operations to do this conversion inline taking care of // the boundary cases that differ between x87 and Java // (1) save RVM nonvolatiles @@ -1724,7 +1719,7 @@ fr2.resolve(asm); fr4.resolve(asm); } else { - // TODO: use SSE/x87 operations to do this conversion inline taking care of + // TODO: use x87 operations to do this conversion inline taking care of // the boundary cases that differ between x87 and Java // (1) save RVM nonvolatiles int numNonVols = NONVOLATILE_GPRS.length; @@ -2394,7 +2389,7 @@ */ @Override protected final void emit_unresolved_getstatic(FieldReference fieldRef) { - emitDynamicLinkingSequence(T0, fieldRef, true); + emitDynamicLinkingSequence(asm, T0, fieldRef, true); if (MM_Constants.NEEDS_GETSTATIC_READ_BARRIER && !fieldRef.getFieldContentsType().isPrimitiveType()) { Barriers.compileGetstaticBarrier(asm, T0, fieldRef.getId()); return; @@ -2436,7 +2431,7 @@ */ @Override protected final void emit_unresolved_putstatic(FieldReference fieldRef) { - emitDynamicLinkingSequence(T0, fieldRef, true); + emitDynamicLinkingSequence(asm, T0, fieldRef, true); if (MM_Constants.NEEDS_PUTSTATIC_WRITE_BARRIER && fieldRef.getFieldContentsType().isReferenceType()) { Barriers.compilePutstaticBarrier(asm, T0, fieldRef.getId()); asm.emitADD_Reg_Imm(SP, WORDSIZE); @@ -2481,7 +2476,7 @@ @Override protected final void emit_unresolved_getfield(FieldReference fieldRef) { TypeReference fieldType = fieldRef.getFieldContentsType(); - emitDynamicLinkingSequence(T0, fieldRef, true); + emitDynamicLinkingSequence(asm, T0, fieldRef, true); if (fieldType.isReferenceType()) { // 32bit reference load if (MM_Constants.NEEDS_READ_BARRIER) { @@ -2600,7 +2595,7 @@ @Override protected final void emit_unresolved_putfield(FieldReference fieldRef) { TypeReference fieldType = fieldRef.getFieldContentsType(); - emitDynamicLinkingSequence(T0, fieldRef, true); + emitDynamicLinkingSequence(asm, T0, fieldRef, true); if (fieldType.isReferenceType()) { // 32bit reference store if (MM_Constants.NEEDS_WRITE_BARRIER) { @@ -2718,7 +2713,7 @@ */ @Override protected final void emit_unresolved_invokevirtual(MethodReference methodRef) { - emitDynamicLinkingSequence(T0, methodRef, true); + emitDynamicLinkingSequence(asm, T0, methodRef, true); int methodRefparameterWords = methodRef.getParameterWords() + 1; // +1 for "this" parameter Offset objectOffset = Offset.fromIntZeroExtend(methodRefparameterWords << 2).minus(4); // object offset into stack @@ -2775,7 +2770,7 @@ */ @Override protected final void emit_unresolved_invokespecial(MethodReference methodRef) { - emitDynamicLinkingSequence(S0, methodRef, true); + emitDynamicLinkingSequence(asm, S0, methodRef, true); genParameterRegisterLoad(methodRef, true); asm.emitCALL_RegDisp(S0, Magic.getTocPointer().toWord().toOffset()); genResultRegisterUnload(methodRef); @@ -2787,7 +2782,7 @@ */ @Override protected final void emit_unresolved_invokestatic(MethodReference methodRef) { - emitDynamicLinkingSequence(S0, methodRef, true); + emitDynamicLinkingSequence(asm, S0, methodRef, true); genParameterRegisterLoad(methodRef, false); asm.emitCALL_RegDisp(S0, Magic.getTocPointer().toWord().toOffset()); genResultRegisterUnload(methodRef); @@ -2832,7 +2827,7 @@ Offset.fromIntZeroExtend((count - 1) << 2)); // "this" object asm.emitPUSH_Imm(methodRef.getId()); // dict id of target asm.emitPUSH_Reg(T1); - genParameterRegisterLoad(2); // pass 2 parameter word + genParameterRegisterLoad(asm, 2); // pass 2 parameter word asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.unresolvedInvokeinterfaceImplementsTestMethod.getOffset()));// check that "this" class implements the interface } else { RVMClass interfaceClass = resolvedMethod.getDeclaringClass(); @@ -2893,7 +2888,7 @@ // "this" parameter is obj asm.emitPUSH_RegDisp(SP, Offset.fromIntZeroExtend((count - 1) << LG_WORDSIZE)); asm.emitPUSH_Imm(methodRefId); // id of method to call - genParameterRegisterLoad(2); // pass 2 parameter words + genParameterRegisterLoad(asm, 2); // pass 2 parameter words // invokeinterface(obj, id) returns address to call asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.invokeInterfaceMethod.getOffset())); asm.emitMOV_Reg_Reg(S0, T0); // S0 has address of method @@ -2908,7 +2903,7 @@ baselineEmitLoadTIB(asm, S0, T0); asm.emitPUSH_Reg(S0); asm.emitPUSH_Imm(resolvedMethod.getDeclaringClass().getInterfaceId()); // interface id - genParameterRegisterLoad(2); // pass 2 parameter words + genParameterRegisterLoad(asm, 2); // pass 2 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.findItableMethod.getOffset())); // findItableOffset(tib, id) returns iTable asm.emitMOV_Reg_Reg(S0, T0); // S0 has iTable genParameterRegisterLoad(methodRef, true); @@ -2942,7 +2937,7 @@ asm.emitPUSH_Imm(align); asm.emitPUSH_Imm(offset); asm.emitPUSH_Imm(site); - genParameterRegisterLoad(7); // pass 7 parameter words + genParameterRegisterLoad(asm, 7); // pass 7 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.resolvedNewScalarMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -2956,7 +2951,7 @@ int site = MM_Interface.getAllocationSite(true); asm.emitPUSH_Imm(typeRef.getId()); asm.emitPUSH_Imm(site); // site - genParameterRegisterLoad(2); // pass 2 parameter words + genParameterRegisterLoad(asm, 2); // pass 2 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.unresolvedNewScalarMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -2982,7 +2977,7 @@ asm.emitPUSH_Imm(align); asm.emitPUSH_Imm(offset); asm.emitPUSH_Imm(site); - genParameterRegisterLoad(8); // pass 8 parameter words + genParameterRegisterLoad(asm, 8); // pass 8 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.resolvedNewArrayMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -2997,7 +2992,7 @@ // count is already on stack- nothing required asm.emitPUSH_Imm(tRef.getId()); asm.emitPUSH_Imm(site); // site - genParameterRegisterLoad(3); // pass 3 parameter words + genParameterRegisterLoad(asm, 3); // pass 3 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.unresolvedNewArrayMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -3021,7 +3016,7 @@ asm.emitPUSH_Imm(typeRef.getId()); // type of array elements asm.emitPUSH_Imm((dimensions + OFFSET_WORDS) << LG_WORDSIZE); // offset to dimensions from FP on entry to newarray - genParameterRegisterLoad(PARAMETERS); + genParameterRegisterLoad(asm, PARAMETERS); asm.emitCALL_Abs(Magic.getTocPointer().plus(ArchEntrypoints.newArrayArrayMethod.getOffset())); for (int i = 0; i < dimensions; i++) { asm.emitPOP_Reg(S0); // clear stack of dimensions (todo use and add immediate to do this) @@ -3034,9 +3029,8 @@ */ @Override protected final void emit_arraylength() { - asm.emitMOV_Reg_RegDisp(T0, SP, NO_SLOT); // T0 is array reference - asm.emitMOV_Reg_RegDisp(T0, T0, ObjectModel.getArrayLengthOffset()); // T0 is array length - asm.emitMOV_RegDisp_Reg(SP, NO_SLOT, T0); // replace reference with length on stack + asm.emitPOP_Reg(T0); // T0 is array reference + asm.emitPUSH_RegDisp(T0, ObjectModel.getArrayLengthOffset()); } /** @@ -3044,7 +3038,7 @@ */ @Override protected final void emit_athrow() { - genParameterRegisterLoad(1); // pass 1 parameter word + genParameterRegisterLoad(asm, 1); // pass 1 parameter word asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.athrowMethod.getOffset())); } @@ -3056,7 +3050,7 @@ protected final void emit_checkcast(TypeReference typeRef) { asm.emitPUSH_RegInd(SP); // duplicate the object ref on the stack asm.emitPUSH_Imm(typeRef.getId()); // TypeReference id. - genParameterRegisterLoad(2); // pass 2 parameter words + genParameterRegisterLoad(asm, 2); // pass 2 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.checkcastMethod.getOffset())); // checkcast(obj, type reference id); } @@ -3156,7 +3150,7 @@ @Override protected final void emit_instanceof(TypeReference typeRef) { asm.emitPUSH_Imm(typeRef.getId()); - genParameterRegisterLoad(2); // pass 2 parameter words + genParameterRegisterLoad(asm, 2); // pass 2 parameter words asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.instanceOfMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -3271,7 +3265,7 @@ protected final void emit_monitorenter() { asm.emitMOV_Reg_RegInd(T0, SP); // T0 is object reference genExplicitNullCheck(asm, T0); - genParameterRegisterLoad(1); // pass 1 parameter word + genParameterRegisterLoad(asm, 1); // pass 1 parameter word asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.lockMethod.getOffset())); } @@ -3280,7 +3274,7 @@ */ @Override protected final void emit_monitorexit() { - genParameterRegisterLoad(1); // pass 1 parameter word + genParameterRegisterLoad(asm, 1); // pass 1 parameter word asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.unlockMethod.getOffset())); } @@ -3460,7 +3454,7 @@ asm.emitPUSH_RegDisp(ESP, localOffset(0)); } // pass 1 parameter - genParameterRegisterLoad(1); + genParameterRegisterLoad(asm, 1); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.lockMethod.getOffset())); // after this instruction, the method has the monitor lockOffset = asm.getMachineCodeIndex(); @@ -3474,7 +3468,7 @@ } else { asm.emitPUSH_RegDisp(ESP, localOffset(0)); // push "this" object } - genParameterRegisterLoad(1); // pass 1 parameter + genParameterRegisterLoad(asm, 1); // pass 1 parameter asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.unlockMethod.getOffset())); } @@ -3506,20 +3500,18 @@ * @param indexReg the register containing the index * @param arrayRefReg the register containing the array reference */ - @Inline(value=Inline.When.AllArgumentsAreConstant) - private void genBoundsCheck(Assembler asm, GPR indexReg, GPR arrayRefReg) { - if (generateBoundsChecks) { - // compare index to array length - asm.emitCMP_RegDisp_Reg(arrayRefReg, ObjectModel.getArrayLengthOffset(), indexReg); - // Jmp around trap if index is OK - asm.emitBranchLikelyNextInstruction(); - ForwardReference fr = asm.forwardJcc(Assembler.LGT); - // "pass" index param to C trap handler - ProcessorLocalState.emitMoveRegToField(asm, ArchEntrypoints.arrayIndexTrapParamField.getOffset(), indexReg); - // trap - asm.emitINT_Imm(RuntimeEntrypoints.TRAP_ARRAY_BOUNDS + RVM_TRAP_BASE); - fr.resolve(asm); - } + @Inline(value=Inline.When.ArgumentsAreConstant, arguments={1,2}) + static void genBoundsCheck(Assembler asm, GPR indexReg, GPR arrayRefReg) { + // compare index to array length + asm.emitCMP_RegDisp_Reg(arrayRefReg, ObjectModel.getArrayLengthOffset(), indexReg); + // Jmp around trap if index is OK + asm.emitBranchLikelyNextInstruction(); + ForwardReference fr = asm.forwardJcc(Assembler.LGT); + // "pass" index param to C trap handler + ProcessorLocalState.emitMoveRegToField(asm, ArchEntrypoints.arrayIndexTrapParamField.getOffset(), indexReg); + // trap + asm.emitINT_Imm(RuntimeEntrypoints.TRAP_ARRAY_BOUNDS + RVM_TRAP_BASE); + fr.resolve(asm); } /** @@ -3576,9 +3568,10 @@ * with SP pointing to the last parameter. * Also, this method is called before the generation of a "helper" method call. * Assumption: no floating-point parameters. + * @param asm TODO * @param params number of parameter words (including "this" if any). */ - private void genParameterRegisterLoad(int params) { + static void genParameterRegisterLoad(Assembler asm, int params) { if (VM.VerifyAssertions) VM._assert(0 < params); if (0 < NUM_PARAMETER_GPRS) { asm.emitMOV_Reg_RegDisp(T0, SP, Offset.fromIntZeroExtend((params - 1) << LG_WORDSIZE)); @@ -3838,7 +3831,7 @@ asm.emitSUB_RegDisp_Imm(ECX, Offset.fromIntZeroExtend(compiledMethod.getId() << 2), 1); ForwardReference notTaken = asm.forwardJcc(Assembler.GT); asm.emitPUSH_Imm(id); - genParameterRegisterLoad(1); + genParameterRegisterLoad(asm, 1); asm.emitCALL_Abs(Magic.getTocPointer().plus(AosEntrypoints.invocationCounterTrippedMethod.getOffset())); notTaken.resolve(asm); } @@ -3861,293 +3854,9 @@ } private boolean genMagic(MethodReference m) { - Atom methodName = m.getName(); - - if (m.getType() == TypeReference.Address) { - // Address magic - - TypeReference[] types = m.getParameterTypes(); - - // Loads all take the form: - // ..., Address, [Offset] -> ..., Value - - if (methodName == MagicNames.loadAddress || - methodName == MagicNames.prepareAddress || - methodName == MagicNames.prepareObjectReference || - methodName == MagicNames.loadWord || - methodName == MagicNames.loadObjectReference || - methodName == MagicNames.prepareWord || - methodName == MagicNames.loadInt || - methodName == MagicNames.prepareInt || - methodName == MagicNames.loadFloat) { - - if (types.length == 0) { - // No offset - asm.emitPOP_Reg(T0); // address - asm.emitPUSH_RegInd(T0); // pushes [T0+0] - } else { - // Load at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // object ref - asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0] - } - return true; - } - - if (methodName == MagicNames.loadByte) { - if (types.length == 0) { - // No offset - asm.emitPOP_Reg(T0); // base - asm.emitMOVSX_Reg_RegInd_Byte(T0, T0); - asm.emitPUSH_Reg(T0); - } else { - // Load at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // base - asm.emitMOVSX_Reg_RegIdx_Byte(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and sign extend byte [T0+S0] - asm.emitPUSH_Reg(T0); - } - return true; - } - - if (methodName == MagicNames.loadShort) { - if (types.length == 0) { - // No offset - asm.emitPOP_Reg(T0); // base - asm.emitMOVSX_Reg_RegInd_Word(T0, T0); - asm.emitPUSH_Reg(T0); - } else { - // Load at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // base - asm.emitMOVSX_Reg_RegIdx_Word(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and sign extend word [T0+S0] - asm.emitPUSH_Reg(T0); - } - return true; - } - - if (methodName == MagicNames.loadChar) { - - if (types.length == 0) { - // No offset - asm.emitPOP_Reg(T0); // base - asm.emitMOVZX_Reg_RegInd_Word(T0, T0); - asm.emitPUSH_Reg(T0); - } else { - // Load at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // base - asm.emitMOVZX_Reg_RegIdx_Word(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and zero extend word [T0+S0] - asm.emitPUSH_Reg(T0); - } - return true; - } - - if (methodName == MagicNames.prepareLong || - methodName == MagicNames.loadLong || - methodName == MagicNames.loadDouble) { - - if (types.length == 0) { - // No offset - asm.emitPOP_Reg(T0); // base - asm.emitPUSH_RegDisp(T0, ONE_SLOT); // pushes [T0+4] - asm.emitPUSH_RegInd(T0); // pushes [T0] - } else { - // Load at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // base - asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, ONE_SLOT); // pushes [T0+S0+4] - asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0] - } - return true; - } - - // Stores all take the form: - // ..., Address, [Offset], Value -> ... - if (methodName == MagicNames.store) { - // Always at least one parameter to a store. - // First parameter is the type to be stored. - TypeReference storeType = types[0]; - - if (storeType == TypeReference.Int || - storeType == TypeReference.Address || - storeType == TypeReference.ObjectReference || - storeType == TypeReference.Word || - storeType == TypeReference.Float) { - - if (types.length == 1) { - // No offset - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // address - asm.emitMOV_RegInd_Reg(S0, T0); // [S0+0] <- T0 - } else { - // Store at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(T1); // address - asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0 - } - return true; - } - - if (storeType == TypeReference.Byte) { - if (types.length == 1) { - // No offset - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(T1); // base - asm.emitMOV_RegInd_Reg_Byte(T1, T0); - } else { - // Store at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(T1); // base - asm.emitMOV_RegIdx_Reg_Byte(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0 - } - return true; - } - - if (storeType == TypeReference.Short || storeType == TypeReference.Char) { - - if (types.length == 1) { - // No offset - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(T1); // base - asm.emitMOV_RegInd_Reg_Word(T1, T0); - } else { - // Store at offset - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(T1); // base - asm.emitMOV_RegIdx_Reg_Word(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0 - } - return true; - } - - if (storeType == TypeReference.Double || storeType == TypeReference.Long) { - - if (types.length == 1) { - // No offset - asm.emitMOV_Reg_RegInd(T0, SP); // value high - asm.emitMOV_Reg_RegDisp(T1, SP, TWO_SLOTS); // base - asm.emitMOV_RegInd_Reg(T1, T0); // [T1] <- T0 - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // value low - asm.emitMOV_RegDisp_Reg(T1, ONE_SLOT, T0); // [T1+4] <- T0 - asm.emitADD_Reg_Imm(SP, WORDSIZE * 3); // pop stack locations - } else { - // Store at offset - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // value high - asm.emitMOV_Reg_RegInd(S0, SP); // offset - asm.emitMOV_Reg_RegDisp(T1, SP, THREE_SLOTS); // base - asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0 - asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // value low - asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, ONE_SLOT, T0); // [T1+S0+4] <- T0 - asm.emitADD_Reg_Imm(SP, WORDSIZE * 4); // pop stack locations - } - return true; - } - } else if (methodName == MagicNames.attempt) { - // All attempts are similar 32 bit values. - if (types.length == 3) { - // Offset passed - asm.emitPOP_Reg(S0); // S0 = offset - } - asm.emitPOP_Reg(T1); // newVal - asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPX - if (types.length == 3) { - asm.emitADD_Reg_RegInd(S0, SP); // S0 += base - } else { - // No offset - asm.emitMOV_Reg_RegInd(S0, SP); // S0 = base - } - asm.emitLockNextInstruction(); - asm.emitCMPXCHG_RegInd_Reg(S0, T1); // atomic compare-and-exchange - asm.emitMOV_RegInd_Imm(SP, 1); // 'push' true (overwriting base) - asm.emitBranchLikelyNextInstruction(); - ForwardReference fr = asm.forwardJcc(Assembler.EQ); // skip if compare fails - asm.emitMOV_RegInd_Imm(SP, 0); // 'push' false (overwriting base) - fr.resolve(asm); - return true; - } - } - - if (methodName == MagicNames.attemptInt || - methodName == MagicNames.attemptObject || - methodName == MagicNames.attemptAddress || - methodName == MagicNames.attemptWord) { - // attempt gets called with four arguments: base, offset, oldVal, newVal - // returns ([base+offset] == oldVal) - // if ([base+offset] == oldVal) [base+offset] := newVal - // (operation on memory is atomic) - asm.emitPOP_Reg(T1); // newVal - asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPXCNG - asm.emitPOP_Reg(S0); // S0 = offset - asm.emitADD_Reg_RegInd(S0, SP); // S0 += base - asm.emitLockNextInstruction(); - asm.emitCMPXCHG_RegInd_Reg(S0, T1); // atomic compare-and-exchange - asm.emitMOV_RegInd_Imm(SP, 1); // 'push' true (overwriting base) - asm.emitBranchLikelyNextInstruction(); - ForwardReference fr = asm.forwardJcc(Assembler.EQ); // skip if compare fails - asm.emitMOV_RegInd_Imm(SP, 0); // 'push' false (overwriting base) - fr.resolve(asm); + if (BaselineMagic.generateMagic(asm, m, method, fp2spOffset(NO_SLOT))) { return true; - } - - if (methodName == MagicNames.attemptLong) { - // attempt gets called with four arguments: base, offset, oldVal, newVal - // returns ([base+offset] == oldVal) - // if ([base+offset] == oldVal) [base+offset] := newVal - // (operation on memory is atomic) - //t1:t0 with s0:ebx - asm.emitMOV_Reg_RegDisp(T1, SP, THREE_SLOTS); - asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T1:T0 (EDX:EAX) -> oldVal - asm.emitMOV_RegDisp_Reg(SP, THREE_SLOTS, EBX); // Save EBX - asm.emitMOV_RegDisp_Reg(SP, TWO_SLOTS, ESI); // Save ESI - asm.emitMOV_Reg_RegInd(EBX, SP); - asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0:EBX (ECX:EBX) -> newVal - asm.emitMOV_Reg_RegDisp(ESI, SP, FIVE_SLOTS); // ESI := base - asm.emitADD_Reg_RegDisp(ESI, SP, FOUR_SLOTS); // ESI += offset - asm.emitLockNextInstruction(); - asm.emitCMPXCHG8B_RegInd(ESI); // atomic compare-and-exchange - ForwardReference fr1 = asm.forwardJcc(Assembler.NE); // skip if compare fails - asm.emitMOV_RegDisp_Imm(SP, FIVE_SLOTS, 1); // 'push' true (overwriting base) - ForwardReference fr2 = asm.forwardJMP(); // skip if compare fails - fr1.resolve(asm); - asm.emitMOV_RegDisp_Imm(SP, FIVE_SLOTS, 0); // 'push' false (overwriting base) - fr2.resolve(asm); - asm.emitMOV_Reg_RegDisp(EBX, SP, THREE_SLOTS); // Restore EBX - asm.emitMOV_Reg_RegDisp(ESI, SP, TWO_SLOTS); // Restore ESI - asm.emitADD_Reg_Imm(SP, WORDSIZE*5); // adjust SP popping the 4 args (6 slots) and pushing the result - return true; - } - - if (methodName == MagicNames.saveThreadState) { - Offset offset = ArchEntrypoints.saveThreadStateInstructionsField.getOffset(); - genParameterRegisterLoad(1); // pass 1 parameter word - asm.emitCALL_Abs(Magic.getTocPointer().plus(offset)); - return true; - } - - if (methodName == MagicNames.threadSwitch) { - Offset offset = ArchEntrypoints.threadSwitchInstructionsField.getOffset(); - genParameterRegisterLoad(2); // pass 2 parameter words - asm.emitCALL_Abs(Magic.getTocPointer().plus(offset)); - return true; - } - - if (methodName == MagicNames.restoreHardwareExceptionState) { - Offset offset = ArchEntrypoints.restoreHardwareExceptionStateInstructionsField.getOffset(); - genParameterRegisterLoad(1); // pass 1 parameter word - asm.emitCALL_Abs(Magic.getTocPointer().plus(offset)); - return true; - } - - if (methodName == MagicNames.invokeClassInitializer) { - asm.emitPOP_Reg(S0); - asm.emitCALL_Reg(S0); // call address just popped - return true; - } - - if (m.isSysCall()) { + } else if (m.isSysCall()) { TypeReference[] args = m.getParameterTypes(); TypeReference rtype = m.getReturnType(); Offset offsetToJavaArg = THREE_SLOTS; // the three regs saved in (2) @@ -4206,605 +3915,11 @@ } return true; + } else { + return false; } - - if (methodName == MagicNames.getFramePointer) { - asm.emitLEA_Reg_RegDisp(S0, SP, fp2spOffset(NO_SLOT)); - asm.emitPUSH_Reg(S0); - return true; - } - - if (methodName == MagicNames.getCallerFramePointer) { - asm.emitPOP_Reg(T0); // Callee FP - asm.emitPUSH_RegDisp(T0, Offset.fromIntSignExtend(STACKFRAME_FRAME_POINTER_OFFSET)); // Caller FP - return true; - } - - if (methodName == MagicNames.setCallerFramePointer) { - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // fp - asm.emitMOV_RegDisp_Reg(S0, Offset.fromIntSignExtend(STACKFRAME_FRAME_POINTER_OFFSET), T0); // [S0+SFPO] <- T0 - return true; - } - - if (methodName == MagicNames.getCompiledMethodID) { - asm.emitPOP_Reg(T0); // Callee FP - asm.emitPUSH_RegDisp(T0, Offset.fromIntSignExtend(STACKFRAME_METHOD_ID_OFFSET)); // Callee CMID - return true; - } - - if (methodName == MagicNames.setCompiledMethodID) { - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // fp - asm.emitMOV_RegDisp_Reg(S0, Offset.fromIntSignExtend(STACKFRAME_METHOD_ID_OFFSET), T0); // [S0+SMIO] <- T0 - return true; - } - - if (methodName == MagicNames.getReturnAddressLocation) { - asm.emitPOP_Reg(T0); // Callee FP - asm.emitADD_Reg_Imm(T0, STACKFRAME_RETURN_ADDRESS_OFFSET); // location containing callee return address - asm.emitPUSH_Reg(T0); // Callee return address - return true; - } - - if (methodName == MagicNames.getTocPointer || methodName == MagicNames.getJTOC) { - asm.emitPUSH_Imm((int)Magic.getTocPointer().toWord().toLong()); - return true; - } - - // get the processor register (PR) - if (methodName == MagicNames.getProcessorRegister) { - asm.emitPUSH_Reg(PR); - return true; - } - - // set the processor register (PR) - if (methodName == MagicNames.setProcessorRegister) { - asm.emitPOP_Reg(PR); - return true; - } - - // Get the value in ESI - if (methodName == MagicNames.getESIAsProcessor) { - asm.emitPUSH_Reg(ESI); - return true; - } - - // Set the value in ESI - if (methodName == MagicNames.setESIAsProcessor) { - asm.emitPOP_Reg(ESI); - return true; - } - - if (methodName == MagicNames.getIntAtOffset || - methodName == MagicNames.getWordAtOffset || - methodName == MagicNames.getObjectAtOffset || - methodName == MagicNames.getTIBAtOffset || - methodName == MagicNames.prepareInt || - methodName == MagicNames.prepareObject || - methodName == MagicNames.prepareAddress || - methodName == MagicNames.prepareWord) { - if (m.getParameterTypes().length == 3) { - // discard locationMetadata parameter - asm.emitPOP_Reg(T0); // locationMetadata, not needed by baseline compiler. - } - asm.emitPOP_Reg(T0); // object ref - asm.emitPOP_Reg(S0); // offset - asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0] - return true; - } - - if (methodName == MagicNames.getUnsignedByteAtOffset) { - asm.emitPOP_Reg(T0); // object ref - asm.emitPOP_Reg(S0); // offset - asm.emitMOVZX_Reg_RegIdx_Byte(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and zero extend byte [T0+S0] - asm.emitPUSH_Reg(T0); - return true; - } - - if (methodName == MagicNames.getByteAtOffset) { - asm.emitPOP_Reg(T0); // object ref - asm.emitPOP_Reg(S0); // offset - asm.emitMOVSX_Reg_RegIdx_Byte(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and zero extend byte [T0+S0] - asm.emitPUSH_Reg(T0); - return true; - } - - if (methodName == MagicNames.getCharAtOffset) { - asm.emitPOP_Reg(T0); // object ref - asm.emitPOP_Reg(S0); // offset - asm.emitMOVZX_Reg_RegIdx_Word(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and zero extend char [T0+S0] - asm.emitPUSH_Reg(T0); - return true; - } - - if (methodName == MagicNames.getShortAtOffset) { - asm.emitPOP_Reg(T0); // object ref - asm.emitPOP_Reg(S0); // offset - asm.emitMOVSX_Reg_RegIdx_Word(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and zero extend char [T0+S0] - asm.emitPUSH_Reg(T0); - return true; - } - - if (methodName == MagicNames.setIntAtOffset || - methodName == MagicNames.setWordAtOffset || - methodName == MagicNames.setObjectAtOffset) { - if (m.getParameterTypes().length == 4) { - // discard locationMetadata parameter - asm.emitPOP_Reg(T0); // locationMetadata, not needed by baseline compiler. - } - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T1); // obj ref - asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0 - return true; - } - - if (methodName == MagicNames.setByteAtOffset) { - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T1); // obj ref - asm.emitMOV_RegIdx_Reg_Byte(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0 - return true; - } - - if (methodName == MagicNames.setCharAtOffset) { - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // offset - asm.emitPOP_Reg(T1); // obj ref - asm.emitMOV_RegIdx_Reg_Word(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (char) T0 - return true; - } - - if (methodName == MagicNames.prepareLong || - methodName == MagicNames.getLongAtOffset || methodName == MagicNames.getDoubleAtOffset) { - asm.emitPOP_Reg(T0); // object ref - asm.emitPOP_Reg(S0); // offset - asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, ONE_SLOT); // pushes [T0+S0+4] - asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0] - return true; - } - - if (methodName == MagicNames.setLongAtOffset || methodName == MagicNames.setDoubleAtOffset) { - asm.emitMOV_Reg_RegInd(T0, SP); // value high - asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // offset - asm.emitMOV_Reg_RegDisp(T1, SP, THREE_SLOTS); // obj ref - asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0 - asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT); // value low - asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, ONE_SLOT, T0); // [T1+S0+4] <- T0 - asm.emitADD_Reg_Imm(SP, WORDSIZE * 4); // pop stack locations - return true; - } - - if (methodName == MagicNames.addressArrayCreate) { - // no resolution problem possible. - emit_resolved_newarray(m.getType().resolve().asArray()); - return true; - } - - if (methodName == MagicNames.addressArrayLength) { - emit_arraylength(); // argument order already correct - return true; - } - - if (methodName == MagicNames.addressArrayGet) { - if (m.getType() == TypeReference.CodeArray) { - emit_baload(); - } else { - if (VM.BuildFor32Addr) { - emit_iaload(); - } else if (VM.BuildFor64Addr) { - emit_laload(); - } else { - VM._assert(NOT_REACHED); - } - } - return true; - } - - if (methodName == MagicNames.addressArraySet) { - if (m.getType() == TypeReference.CodeArray) { - emit_bastore(); - } else { - if (VM.BuildFor32Addr) { - emit_iastore(); - } else if (VM.BuildFor64Addr) { - VM._assert(false); // not implemented - } else { - VM._assert(NOT_REACHED); - } - } - return true; - } - - if (methodName == MagicNames.getMemoryInt || - methodName == MagicNames.getMemoryWord || - methodName == MagicNames.getMemoryAddress) { - asm.emitPOP_Reg(T0); // address - asm.emitPUSH_RegInd(T0); // pushes [T0+0] - return true; - } - - if (methodName == MagicNames.setMemoryInt || methodName == MagicNames.setMemoryWord) { - if (m.getParameterTypes().length == 3) { - // discard locationMetadata parameter - asm.emitPOP_Reg(T0); // locationMetadata, not needed by baseline compiler. - } - asm.emitPOP_Reg(T0); // value - asm.emitPOP_Reg(S0); // address - asm.emitMOV_RegInd_Reg(S0, T0); // [S0+0] <- T0 - return true; - } - - if (methodName == MagicNames.objectAsAddress || - methodName == MagicNames.addressAsByteArray || - methodName == MagicNames.addressAsObject || - methodName == MagicNames.addressAsTIB || - methodName == MagicNames.objectAsType || - methodName == MagicNames.objectAsShortArray || - methodName == MagicNames.objectAsIntArray || - methodName == MagicNames.objectAsProcessor || - methodName == MagicNames.objectAsThread || - methodName == MagicNames.threadAsCollectorThread || - methodName == MagicNames.floatAsIntBits || - methodName == MagicNames.intBitsAsFloat || - methodName == MagicNames.doubleAsLongBits || - methodName == MagicNames.longBitsAsDouble) { - // no-op (a type change, not a representation change) - return true; - } - - // code for RVMType Magic.getObjectType(Object object) - if (methodName == MagicNames.getObjectType) { - asm.emitPOP_Reg(T0); // object ref - baselineEmitLoadTIB(asm, S0, T0); - asm.emitPUSH_RegDisp(S0, Offset.fromIntZeroExtend(TIB_TYPE_INDEX << LG_WORDSIZE)); // push RVMType slot of TIB - return true; - } - - if (methodName == MagicNames.getArrayLength) { - asm.emitPOP_Reg(T0); // object ref - asm.emitPUSH_RegDisp(T0, ObjectModel.getArrayLengthOffset()); - return true; - } - - if (methodName == MagicNames.sync) { // nothing required on IA32 - return true; - } - - if (methodName == MagicNames.isync) { // nothing required on IA32 - return true; - } - - // baseline compiled invocation only: all paramaters on the stack - // hi mem - // Code - // GPRs - // FPRs - // Spills - // low-mem - if (methodName == MagicNames.invokeMethodReturningVoid) { - Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); - genParameterRegisterLoad(5); // pass 5 parameter words - asm.emitCALL_Abs(Magic.getTocPointer().plus(offset)); - return true; - } - - if (methodName == MagicNames.invokeMethodReturningInt) { - Offset offset = ArchEntrypoints.reflectiveMethodInvoker... [truncated message content] |
From: <cap...@us...> - 2009-01-28 00:22:19
|
Revision: 15298 http://jikesrvm.svn.sourceforge.net/jikesrvm/?rev=15298&view=rev Author: captain5050 Date: 2009-01-28 00:22:14 +0000 (Wed, 28 Jan 2009) Log Message: ----------- Tighten instructions generated for baseline barriers. Use fewer instructions and ones with shorter encodings. Modified Paths: -------------- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2009-01-27 22:01:16 UTC (rev 15297) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2009-01-28 00:22:14 UTC (rev 15298) @@ -35,13 +35,14 @@ static void compilePutfieldBarrier(Assembler asm, GPR reg, int locationMetadata) { // on entry java stack contains ...|target_ref|ref_to_store| - // SP[0] -> ref_to_store, SP[1] -> target_ref - Offset of1W = Offset.fromIntSignExtend(WORDSIZE); - Offset of2W = Offset.fromIntSignExtend(2*WORDSIZE); - genNullCheck(asm, WORDSIZE); - asm.emitPUSH_RegDisp(SP, of1W); - asm.emitPUSH_Reg(reg); - asm.emitPUSH_RegDisp(SP, of2W); // Push what was originally (SP, 0) + // reg holds offset of field + if(VM.VerifyAssertions) VM._assert(reg == T0); + asm.emitPOP_Reg(S0); // S0 = ref_to_store + asm.emitPOP_Reg(T1); // T1 = target_ref + genNullCheck(asm, T1); + asm.emitPUSH_Reg(T1); // target_ref + asm.emitPUSH_Reg(reg); // offset + asm.emitPUSH_Reg(S0); // ref_to_store asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); @@ -49,13 +50,12 @@ static void compilePutfieldBarrierImm(Assembler asm, Offset fieldOffset, int locationMetadata) { // on entry java stack contains ...|target_ref|ref_to_store| - // SP -> ref_to_store, SP+4 -> target_ref - Offset of1W = Offset.fromIntSignExtend(WORDSIZE); - Offset of2W = Offset.fromIntSignExtend(2*WORDSIZE); - genNullCheck(asm, WORDSIZE); - asm.emitPUSH_RegDisp(SP, of1W); + asm.emitPOP_Reg(S0); // S0 = ref_to_store + asm.emitPOP_Reg(T1); // T1 = target_ref + genNullCheck(asm, T1); + asm.emitPUSH_Reg(T1); // target_ref asm.emitPUSH_Imm(fieldOffset.toInt()); - asm.emitPUSH_RegDisp(SP, of2W); // Push what was originally (SP, 0) + asm.emitPUSH_Reg(S0); // ref_to_store asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); @@ -63,10 +63,11 @@ static void compilePutstaticBarrier(Assembler asm, GPR reg, int locationMetadata) { // on entry java stack contains ...|ref_to_store| - // SP -> ref_to_store - Offset of1W = Offset.fromIntSignExtend(WORDSIZE); - asm.emitPUSH_Reg(reg); - asm.emitPUSH_RegDisp(SP, of1W); + // reg holds offset of field + if(VM.VerifyAssertions) VM._assert(reg != S0); + asm.emitPOP_Reg(S0); // S0 = ref_to_store + asm.emitPUSH_Reg(reg); // offset + asm.emitPUSH_Reg(S0); // ref_to_store asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putstaticWriteBarrierMethod.getOffset())); @@ -74,10 +75,9 @@ static void compilePutstaticBarrierImm(Assembler asm, Offset fieldOffset, int locationMetadata) { // on entry java stack contains ...|ref_to_store| - // SP -> ref_to_store - Offset of1W = Offset.fromIntSignExtend(WORDSIZE); + asm.emitPOP_Reg(S0); // S0 = ref_to_store asm.emitPUSH_Imm(fieldOffset.toInt()); - asm.emitPUSH_RegDisp(SP, of1W); + asm.emitPUSH_Reg(S0); // ref_to_store asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putstaticWriteBarrierMethod.getOffset())); @@ -133,13 +133,30 @@ */ private static void genNullCheck(Assembler asm, int offset) { if (VM.BuildFor32Addr) { - asm.emitMOV_Reg_RegDisp(T1, SP, Offset.fromIntZeroExtend(offset)); + if (offset == 0) { + asm.emitMOV_Reg_RegInd(T1, SP); + } else { + asm.emitMOV_Reg_RegDisp(T1, SP, Offset.fromIntZeroExtend(offset)); + } } else { - asm.emitMOV_Reg_RegDisp_Quad(T1, SP, Offset.fromIntZeroExtend(offset)); + if (offset == 0) { + asm.emitMOV_Reg_RegInd_Quad(T1, SP); + } else { + asm.emitMOV_Reg_RegDisp_Quad(T1, SP, Offset.fromIntZeroExtend(offset)); + } } BaselineCompilerImpl.baselineEmitLoadTIB(asm, T1, T1); } + /** + * Generate a cheap nullcheck by attempting at offset 0 from the object + * in reg + */ + private static void genNullCheck(Assembler asm, GPR reg) { + // do load from reg, without clobbering any registers and using a short encoding + asm.emitTEST_RegInd_Reg(reg, reg); + } + static void compileModifyCheck(Assembler asm, int offset) { if (!Configuration.ExtremeAssertions) return; // on entry java stack contains ... [SP+offset] -> target_ref Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2009-01-27 22:01:16 UTC (rev 15297) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2009-01-28 00:22:14 UTC (rev 15298) @@ -2662,7 +2662,6 @@ emitDynamicLinkingSequence(asm, T0, fieldRef, true); if (MemoryManagerConstants.NEEDS_PUTSTATIC_WRITE_BARRIER && fieldRef.getFieldContentsType().isReferenceType()) { Barriers.compilePutstaticBarrier(asm, T0, fieldRef.getId()); - adjustStack(WORDSIZE, true); } else { if (fieldRef.getSize() <= BYTES_IN_INT) { // field is one word if (VM.BuildFor32Addr) { @@ -2696,7 +2695,6 @@ Offset fieldOffset = field.getOffset(); if (MemoryManagerConstants.NEEDS_PUTSTATIC_WRITE_BARRIER && field.isReferenceType() && !field.isUntraced()) { Barriers.compilePutstaticBarrierImm(asm, fieldOffset, fieldRef.getId()); - adjustStack(WORDSIZE, true); } else { if (field.getSize() <= BYTES_IN_INT) { // field is one word if (VM.BuildFor32Addr) { @@ -2870,7 +2868,6 @@ // 32/64bit reference store if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) { Barriers.compilePutfieldBarrier(asm, T0, fieldRef.getId()); - adjustStack(2*WORDSIZE, true); // complete popping the value and reference } else { asm.emitPOP_Reg(T1); // T1 is the value to be stored asm.emitPOP_Reg(S0); // S0 is the object reference @@ -2942,7 +2939,6 @@ // 32/64bit reference store if (MemoryManagerConstants.NEEDS_WRITE_BARRIER && !field.isUntraced()) { Barriers.compilePutfieldBarrierImm(asm, fieldOffset, fieldRef.getId()); - adjustStack(WORDSIZE * 2, true); // complete popping the value and reference } else { asm.emitPOP_Reg(T0); // T0 is the value to be stored asm.emitPOP_Reg(S0); // S0 is the object reference This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2009-01-28 16:55:33
|
Revision: 15300 http://jikesrvm.svn.sourceforge.net/jikesrvm/?rev=15300&view=rev Author: captain5050 Date: 2009-01-28 16:55:24 +0000 (Wed, 28 Jan 2009) Log Message: ----------- More fine tuning of write barrier code to have shorter instruction encoding and fewer instructions, also more javadoc added. Modified Paths: -------------- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2009-01-28 16:06:54 UTC (rev 15299) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2009-01-28 16:55:24 UTC (rev 15300) @@ -27,35 +27,53 @@ */ class Barriers implements BaselineConstants { - static void compileArrayStoreBarrier(Assembler asm) { - // on entry java stack contains ...|target_array_ref|array_index|ref_to_store| + /** + * Generate code to perform an array store barrier + * + * @param asm the assembler to generate the code in + * @param ref the register holding the array reference + * @param index the register holding index into the array + * @param value the register holding the value to store + */ + static void compileArrayStoreBarrier(Assembler asm, GPR ref, GPR index, GPR value) { + asm.emitPUSH_Reg(ref); + asm.emitPUSH_Reg(index); + asm.emitPUSH_Reg(value); BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStoreWriteBarrierMethod.getOffset())); } - static void compilePutfieldBarrier(Assembler asm, GPR reg, int locationMetadata) { - // on entry java stack contains ...|target_ref|ref_to_store| - // reg holds offset of field - if(VM.VerifyAssertions) VM._assert(reg == T0); - asm.emitPOP_Reg(S0); // S0 = ref_to_store - asm.emitPOP_Reg(T1); // T1 = target_ref - genNullCheck(asm, T1); - asm.emitPUSH_Reg(T1); // target_ref - asm.emitPUSH_Reg(reg); // offset - asm.emitPUSH_Reg(S0); // ref_to_store + /** + * Generate code to perform a putfield barrier + * + * @param asm the assembler to generate the code in + * @param ref the register holding the array reference + * @param offset the register holding the offset of the field + * @param value the register holding the value to store + */ + static void compilePutfieldBarrier(Assembler asm, GPR ref, GPR offset, GPR value, int locationMetadata) { + BaselineCompilerImpl.genNullCheck(asm, ref); + asm.emitPUSH_Reg(ref); + asm.emitPUSH_Reg(offset); + asm.emitPUSH_Reg(value); asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); - } + } - static void compilePutfieldBarrierImm(Assembler asm, Offset fieldOffset, int locationMetadata) { - // on entry java stack contains ...|target_ref|ref_to_store| - asm.emitPOP_Reg(S0); // S0 = ref_to_store - asm.emitPOP_Reg(T1); // T1 = target_ref - genNullCheck(asm, T1); - asm.emitPUSH_Reg(T1); // target_ref + /** + * Generate code to perform a putfield barrier when the field is at a known offset + * + * @param asm the assembler to generate the code in + * @param ref the register holding the array reference + * @param fieldOffset the offset of the field + * @param value the register holding the value to store + */ + static void compilePutfieldBarrierImm(Assembler asm, GPR ref, Offset fieldOffset, GPR value, int locationMetadata) { + BaselineCompilerImpl.genNullCheck(asm, ref); + asm.emitPUSH_Reg(ref); asm.emitPUSH_Imm(fieldOffset.toInt()); - asm.emitPUSH_Reg(S0); // ref_to_store + asm.emitPUSH_Reg(value); asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); @@ -71,7 +89,7 @@ asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putstaticWriteBarrierMethod.getOffset())); - } + } static void compilePutstaticBarrierImm(Assembler asm, Offset fieldOffset, int locationMetadata) { // on entry java stack contains ...|ref_to_store| Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2009-01-28 16:06:54 UTC (rev 15299) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2009-01-28 16:55:24 UTC (rev 15300) @@ -707,16 +707,13 @@ genParameterRegisterLoad(asm, 2); // pass 2 parameter // call checkstore(array ref, value) asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.checkstoreMethod.getOffset())); + asm.emitPOP_Reg(T1); // T1 is the value + asm.emitPOP_Reg(T0); // T0 is array index + asm.emitPOP_Reg(S0); // S0 is array ref + genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) { - stackMoveHelper(T0, ONE_SLOT); // T0 is array index - stackMoveHelper(S0, TWO_SLOTS); // S0 is array ref - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array - Barriers.compileArrayStoreBarrier(asm); + Barriers.compileArrayStoreBarrier(asm, S0, T0, T1); } else { - asm.emitPOP_Reg(T1); // T1 is the value - asm.emitPOP_Reg(T0); // T0 is array index - asm.emitPOP_Reg(S0); // S0 is array ref - genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array if (VM.BuildFor32Addr) { asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1 } else { @@ -2866,11 +2863,11 @@ emitDynamicLinkingSequence(asm, T0, fieldRef, true); if (fieldType.isReferenceType()) { // 32/64bit reference store + asm.emitPOP_Reg(T1); // T1 is the value to be stored + asm.emitPOP_Reg(S0); // S0 is the object reference if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) { - Barriers.compilePutfieldBarrier(asm, T0, fieldRef.getId()); + Barriers.compilePutfieldBarrier(asm, S0, T0, T1, fieldRef.getId()); } else { - asm.emitPOP_Reg(T1); // T1 is the value to be stored - asm.emitPOP_Reg(S0); // S0 is the object reference if (VM.BuildFor32Addr) { asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.BYTE, NO_SLOT, T1); // [S0+T0] <- T1 } else { @@ -2937,11 +2934,11 @@ Barriers.compileModifyCheck(asm, 4); if (field.isReferenceType()) { // 32/64bit reference store + asm.emitPOP_Reg(T0); // T0 is the value to be stored + asm.emitPOP_Reg(S0); // S0 is the object reference if (MemoryManagerConstants.NEEDS_WRITE_BARRIER && !field.isUntraced()) { - Barriers.compilePutfieldBarrierImm(asm, fieldOffset, fieldRef.getId()); + Barriers.compilePutfieldBarrierImm(asm, S0, fieldOffset, T0, fieldRef.getId()); } else { - asm.emitPOP_Reg(T0); // T0 is the value to be stored - asm.emitPOP_Reg(S0); // S0 is the object reference // [S0+fieldOffset] <- T0 if (VM.BuildFor32Addr) { asm.emitMOV_RegDisp_Reg(S0, fieldOffset, T0); @@ -3665,7 +3662,7 @@ } else { asm.emitMOV_Reg_RegInd_Quad(T0, SP); // T0 is object reference } - genExplicitNullCheck(asm, T0); + genNullCheck(asm, T0); genParameterRegisterLoad(asm, 1); // pass 1 parameter word asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.lockMethod.getOffset())); } @@ -3922,15 +3919,21 @@ * @param objRefReg the register containing the array reference */ @Inline - private void genExplicitNullCheck(Assembler asm, GPR objRefReg) { - // compare to zero - asm.emitTEST_Reg_Reg(objRefReg, objRefReg); - // Jmp around trap if index is OK - asm.emitBranchLikelyNextInstruction(); - ForwardReference fr = asm.forwardJcc(Assembler.NE); - // trap - asm.emitINT_Imm(RuntimeEntrypoints.TRAP_NULL_POINTER + RVM_TRAP_BASE); - fr.resolve(asm); + static void genNullCheck(Assembler asm, GPR objRefReg) { + boolean cheapTest = true; + if (cheapTest) { + // perform load to cause trap + asm.emitTEST_RegInd_Reg(objRefReg, objRefReg); + } else { + // compare to zero + asm.emitTEST_Reg_Reg(objRefReg, objRefReg); + // Jmp around trap if index is OK + asm.emitBranchLikelyNextInstruction(); + ForwardReference fr = asm.forwardJcc(Assembler.NE); + // trap + asm.emitINT_Imm(RuntimeEntrypoints.TRAP_NULL_POINTER + RVM_TRAP_BASE); + fr.resolve(asm); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dfr...@us...> - 2009-02-28 12:56:36
|
Revision: 15549 http://jikesrvm.svn.sourceforge.net/jikesrvm/?rev=15549&view=rev Author: dframpton-oss Date: 2009-02-28 12:56:28 +0000 (Sat, 28 Feb 2009) Log Message: ----------- Switch back to doing null checks that are actually correct. Object references do not have to point into objects (they do not for empty arrays or objects with 4 or less bytes of payload). Detecting null by trying to indirect through the object reference and catching segfaults is just flat wrong. This fixes the intermittent pmd crash that was recently introduced in r15298... Modified Paths: -------------- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2009-02-28 02:38:21 UTC (rev 15548) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java 2009-02-28 12:56:28 UTC (rev 15549) @@ -13,7 +13,6 @@ package org.jikesrvm.compilers.baseline.ia32; import org.jikesrvm.Configuration; -import org.jikesrvm.VM; import org.jikesrvm.ArchitectureSpecific.Assembler; import org.jikesrvm.ia32.BaselineConstants; import org.jikesrvm.runtime.Entrypoints; @@ -55,7 +54,7 @@ asm.emitPUSH_Reg(offset); asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); - BaselineCompilerImpl.genNullCheck(asm, T0); + genNullCheck(asm, T0); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); } @@ -72,7 +71,7 @@ asm.emitPUSH_Imm(fieldOffset.toInt()); asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 4); - BaselineCompilerImpl.genNullCheck(asm, T0); + genNullCheck(asm, T0); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putfieldWriteBarrierMethod.getOffset())); } @@ -104,19 +103,19 @@ static void compileGetfieldBarrier(Assembler asm, GPR reg, int locationMetadata) { // on entry java stack contains ...|target_ref| // SP -> target_ref - genNullCheck(asm, 0); asm.emitPUSH_Reg(reg); asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); + genNullCheck(asm, T0); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.getfieldReadBarrierMethod.getOffset())); asm.emitPUSH_Reg(T0); } static void compileGetfieldBarrierImm(Assembler asm, Offset fieldOffset, int locationMetadata) { - genNullCheck(asm, 0); asm.emitPUSH_Imm(fieldOffset.toInt()); asm.emitPUSH_Imm(locationMetadata); BaselineCompilerImpl.genParameterRegisterLoad(asm, 3); + genNullCheck(asm, T0); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.getfieldReadBarrierMethod.getOffset())); asm.emitPUSH_Reg(T0); } @@ -137,27 +136,6 @@ asm.emitPUSH_Reg(T0); } - /** - * Generate a cheap nullcheck by attempting to load the TIB of the object - * at the given offset to SP. - */ - private static void genNullCheck(Assembler asm, int offset) { - if (VM.BuildFor32Addr) { - if (offset == 0) { - asm.emitMOV_Reg_RegInd(T1, SP); - } else { - asm.emitMOV_Reg_RegDisp(T1, SP, Offset.fromIntZeroExtend(offset)); - } - } else { - if (offset == 0) { - asm.emitMOV_Reg_RegInd_Quad(T1, SP); - } else { - asm.emitMOV_Reg_RegDisp_Quad(T1, SP, Offset.fromIntZeroExtend(offset)); - } - } - BaselineCompilerImpl.baselineEmitLoadTIB(asm, T1, T1); - } - static void compileModifyCheck(Assembler asm, int offset) { if (!Configuration.ExtremeAssertions) return; // on entry java stack contains ... [SP+offset] -> target_ref @@ -166,4 +144,15 @@ BaselineCompilerImpl.genParameterRegisterLoad(asm, 1); asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.modifyCheckMethod.getOffset())); } + + /** + * Generate an implicit null check by loading the TIB of the given object. + * Scribbles over S0. + * + * @param asm the assembler to generate into + * @param objRefReg the register containing the reference + */ + private static void genNullCheck(Assembler asm, GPR objRefReg) { + BaselineCompilerImpl.baselineEmitLoadTIB(asm, S0, T0); + } } Modified: rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java =================================================================== --- rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2009-02-28 02:38:21 UTC (rev 15548) +++ rvmroot/trunk/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java 2009-02-28 12:56:28 UTC (rev 15549) @@ -3920,30 +3920,23 @@ } /** - * Generate an explicit null check, trapping if the register is null - * otherwise falling through. + * Generate an explicit null check (compare to zero). + * * @param asm the assembler to generate into - * @param objRefReg the register containing the array reference + * @param objRefReg the register containing the reference */ @Inline - static void genNullCheck(Assembler asm, GPR objRefReg) { - boolean cheapTest = true; - if (cheapTest) { - // perform load to cause trap - asm.emitTEST_RegInd_Reg(objRefReg, objRefReg); - } else { - // compare to zero - asm.emitTEST_Reg_Reg(objRefReg, objRefReg); - // Jmp around trap if index is OK - asm.emitBranchLikelyNextInstruction(); - ForwardReference fr = asm.forwardJcc(Assembler.NE); - // trap - asm.emitINT_Imm(RuntimeEntrypoints.TRAP_NULL_POINTER + RVM_TRAP_BASE); - fr.resolve(asm); - } + private static void genNullCheck(Assembler asm, GPR objRefReg) { + // compare to zero + asm.emitTEST_Reg_Reg(objRefReg, objRefReg); + // Jmp around trap if index is OK + asm.emitBranchLikelyNextInstruction(); + ForwardReference fr = asm.forwardJcc(Assembler.NE); + // trap + asm.emitINT_Imm(RuntimeEntrypoints.TRAP_NULL_POINTER + RVM_TRAP_BASE); + fr.resolve(asm); } - /** * Generate an array bounds check trapping if the array bound check fails, * otherwise falling through. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |