From: buzbee Date: Thu, 15 Jul 2010 23:03:32 +0000 (-0700) Subject: x86 interpreter write barrier support X-Git-Tag: android-x86-4.0-r1~391^2~8^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=3d95064ad1d8e6da4f9a523b2c2f11cf1f1ea952;p=android-x86%2Fdalvik.git x86 interpreter write barrier support Fix for 2837703. Also added support for new Dalvik volatile ops. Change-Id: Ic2b8d31afc8806077c5bf27ec90c643f7e47591e --- diff --git a/vm/mterp/config-x86 b/vm/mterp/config-x86 index 78ae1a0e3..627e06cd6 100644 --- a/vm/mterp/config-x86 +++ b/vm/mterp/config-x86 @@ -35,14 +35,6 @@ import c/opcommon.c op-start x86 # stub -- need native impl op OP_EXECUTE_INLINE_RANGE c - op OP_IGET_VOLATILE c - op OP_IPUT_VOLATILE c - op OP_SGET_VOLATILE c - op OP_SPUT_VOLATILE c - op OP_IGET_OBJECT_VOLATILE c - op OP_IPUT_OBJECT_VOLATILE c - op OP_SGET_OBJECT_VOLATILE c - op OP_SPUT_OBJECT_VOLATILE c op OP_IGET_WIDE_VOLATILE c op OP_IPUT_WIDE_VOLATILE c op OP_SGET_WIDE_VOLATILE c diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S index 914b1d170..5dd26010d 100644 --- a/vm/mterp/out/InterpAsm-x86.S +++ b/vm/mterp/out/InterpAsm-x86.S @@ -2221,12 +2221,10 @@ dvmAsmInstructionStart = .L_OP_NOP .balign 64 .L_OP_IPUT_OBJECT: /* 0x5b */ /* File: x86/OP_IPUT_OBJECT.S */ -/* File: x86/OP_IPUT.S */ - /* - * General 32-bit instance field put. + * Object field put. * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * for: iput-object */ /* op vA, vB, field@CCCC */ GET_GLUE(%ecx) @@ -2246,7 +2244,6 @@ dvmAsmInstructionStart = .L_OP_NOP GET_GLUE(rIBASE) jmp .LOP_IPUT_OBJECT_resolve - /* ------------------------------ */ .balign 64 .L_OP_IPUT_BOOLEAN: /* 0x5c */ @@ -2560,7 +2557,7 @@ dvmAsmInstructionStart = .L_OP_NOP /* * General 32-bit SPUT handler. * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * for: sput, sput-boolean, sput-byte, sput-char, sput-short */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) @@ -2609,28 +2606,21 @@ dvmAsmInstructionStart = .L_OP_NOP .balign 64 .L_OP_SPUT_OBJECT: /* 0x69 */ /* File: x86/OP_SPUT_OBJECT.S */ -/* File: x86/OP_SPUT.S */ /* - * General 32-bit SPUT handler. - * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * SPUT object handler. */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) movzwl 2(rPC),%eax # eax<- field ref BBBB movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields - movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr + movl (%ecx,%eax,4),%eax # eax<- resolved StaticField testl %eax,%eax # resolved entry null? je .LOP_SPUT_OBJECT_resolve # if not, make it so .LOP_SPUT_OBJECT_finish: # field ptr in eax movzbl rINST_HI,%ecx # ecx<- AA GET_VREG(%ecx,%ecx) - FETCH_INST_WORD(2) - movl %ecx,offStaticField_value(%eax) - ADVANCE_PC(2) - GOTO_NEXT - + jmp .LOP_SPUT_OBJECT_continue /* ------------------------------ */ .balign 64 @@ -2640,7 +2630,7 @@ dvmAsmInstructionStart = .L_OP_NOP /* * General 32-bit SPUT handler. * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * for: sput, sput-boolean, sput-byte, sput-char, sput-short */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) @@ -2667,7 +2657,7 @@ dvmAsmInstructionStart = .L_OP_NOP /* * General 32-bit SPUT handler. * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * for: sput, sput-boolean, sput-byte, sput-char, sput-short */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) @@ -2694,7 +2684,7 @@ dvmAsmInstructionStart = .L_OP_NOP /* * General 32-bit SPUT handler. * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * for: sput, sput-boolean, sput-byte, sput-char, sput-short */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) @@ -2721,7 +2711,7 @@ dvmAsmInstructionStart = .L_OP_NOP /* * General 32-bit SPUT handler. * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * for: sput, sput-boolean, sput-byte, sput-char, sput-short */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) @@ -5684,73 +5674,145 @@ dvmAsmInstructionStart = .L_OP_NOP /* ------------------------------ */ .balign 64 .L_OP_IGET_VOLATILE: /* 0xe3 */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_IGET_VOLATILE # do the real work +/* File: x86/OP_IGET_VOLATILE.S */ +/* File: x86/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op vA, vB, field@CCCC */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() - GOTO_NEXT + SPILL(rIBASE) # need another reg + movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC + movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex + movzbl rINST_HI,%ecx # ecx<- BA + sarl $4,%ecx # ecx<- B + movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields + movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA + andb $0xf,rINST_LO # rINST_FULL<- A + GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr + movl (%eax,rIBASE,4),%eax # resolved entry + testl %eax,%eax # is resolved entry null? + jne .LOP_IGET_VOLATILE_finish # no, already resolved + movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField + GET_GLUE(rIBASE) + jmp .LOP_IGET_VOLATILE_resolve + + /* ------------------------------ */ .balign 64 .L_OP_IPUT_VOLATILE: /* 0xe4 */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_IPUT_VOLATILE # do the real work +/* File: x86/OP_IPUT_VOLATILE.S */ +/* File: x86/OP_IPUT.S */ + + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field@CCCC */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() - GOTO_NEXT + SPILL(rIBASE) # need another reg + movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC + movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex + movzbl rINST_HI,%ecx # ecx<- BA + sarl $4,%ecx # ecx<- B + movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields + movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA + andb $0xf,rINST_LO # rINST_FULL<- A + GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr + movl (%eax,rIBASE,4),%eax # resolved entry + testl %eax,%eax # is resolved entry null? + jne .LOP_IPUT_VOLATILE_finish # no, already resolved + movl rIBASE,OUT_ARG1(%esp) + GET_GLUE(rIBASE) + jmp .LOP_IPUT_VOLATILE_resolve + + /* ------------------------------ */ .balign 64 .L_OP_SGET_VOLATILE: /* 0xe5 */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_SGET_VOLATILE # do the real work +/* File: x86/OP_SGET_VOLATILE.S */ +/* File: x86/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field@BBBB */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex + movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields + movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr + testl %eax,%eax # resolved entry null? + je .LOP_SGET_VOLATILE_resolve # if not, make it so +.LOP_SGET_VOLATILE_finish: # field ptr in eax + movl offStaticField_value(%eax),%eax + movzbl rINST_HI,%ecx # ecx<- AA + FETCH_INST_WORD(2) + ADVANCE_PC(2) + SET_VREG(%eax,%ecx) GOTO_NEXT + + /* ------------------------------ */ .balign 64 .L_OP_SPUT_VOLATILE: /* 0xe6 */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_SPUT_VOLATILE # do the real work +/* File: x86/OP_SPUT_VOLATILE.S */ +/* File: x86/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field@BBBB */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex + movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields + movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr + testl %eax,%eax # resolved entry null? + je .LOP_SPUT_VOLATILE_resolve # if not, make it so +.LOP_SPUT_VOLATILE_finish: # field ptr in eax + movzbl rINST_HI,%ecx # ecx<- AA + GET_VREG(%ecx,%ecx) + FETCH_INST_WORD(2) + movl %ecx,offStaticField_value(%eax) + ADVANCE_PC(2) GOTO_NEXT + + /* ------------------------------ */ .balign 64 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_IGET_OBJECT_VOLATILE # do the real work +/* File: x86/OP_IGET_OBJECT_VOLATILE.S */ +/* File: x86/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op vA, vB, field@CCCC */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() - GOTO_NEXT + SPILL(rIBASE) # need another reg + movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC + movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex + movzbl rINST_HI,%ecx # ecx<- BA + sarl $4,%ecx # ecx<- B + movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields + movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA + andb $0xf,rINST_LO # rINST_FULL<- A + GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr + movl (%eax,rIBASE,4),%eax # resolved entry + testl %eax,%eax # is resolved entry null? + jne .LOP_IGET_OBJECT_VOLATILE_finish # no, already resolved + movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField + GET_GLUE(rIBASE) + jmp .LOP_IGET_OBJECT_VOLATILE_resolve + + /* ------------------------------ */ .balign 64 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ @@ -5968,7 +6030,7 @@ dvmAsmInstructionStart = .L_OP_NOP .balign 64 .L_OP_IPUT_QUICK: /* 0xf5 */ /* File: x86/OP_IPUT_QUICK.S */ - /* For: iput-quick, iput-object-quick */ + /* For: iput-quick */ /* op vA, vB, offset@CCCC */ movzbl rINST_HI,%ecx # ecx<- BA sarl $4,%ecx # ecx<- B @@ -6011,8 +6073,7 @@ dvmAsmInstructionStart = .L_OP_NOP .balign 64 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ /* File: x86/OP_IPUT_OBJECT_QUICK.S */ -/* File: x86/OP_IPUT_QUICK.S */ - /* For: iput-quick, iput-object-quick */ + /* For: iput-object-quick */ /* op vA, vB, offset@CCCC */ movzbl rINST_HI,%ecx # ecx<- BA sarl $4,%ecx # ecx<- B @@ -6021,13 +6082,11 @@ dvmAsmInstructionStart = .L_OP_NOP andb $0xf,rINST_LO # rINST_FULL<- A GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] movzwl 2(rPC),%eax # eax<- field byte offset - testl %ecx,%ecx # is object null? + testl %ecx,%ecx # is object null? je common_errNullObject movl rINST_FULL,(%ecx,%eax,1) - FETCH_INST_WORD(2) - ADVANCE_PC(2) - GOTO_NEXT - + GET_GLUE(%eax) + jmp .LOP_IPUT_OBJECT_QUICK_finish /* ------------------------------ */ .balign 64 @@ -6142,45 +6201,81 @@ dvmAsmInstructionStart = .L_OP_NOP /* ------------------------------ */ .balign 64 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_IPUT_OBJECT_VOLATILE # do the real work +/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */ +/* File: x86/OP_IPUT_OBJECT.S */ + /* + * Object field put. + * + * for: iput-object + */ + /* op vA, vB, field@CCCC */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() - GOTO_NEXT + SPILL(rIBASE) # need another reg + movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC + movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex + movzbl rINST_HI,%ecx # ecx<- BA + sarl $4,%ecx # ecx<- B + movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields + movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA + andb $0xf,rINST_LO # rINST_FULL<- A + GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr + movl (%eax,rIBASE,4),%eax # resolved entry + testl %eax,%eax # is resolved entry null? + jne .LOP_IPUT_OBJECT_VOLATILE_finish # no, already resolved + movl rIBASE,OUT_ARG1(%esp) + GET_GLUE(rIBASE) + jmp .LOP_IPUT_OBJECT_VOLATILE_resolve + + /* ------------------------------ */ .balign 64 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_SGET_OBJECT_VOLATILE # do the real work +/* File: x86/OP_SGET_OBJECT_VOLATILE.S */ +/* File: x86/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field@BBBB */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex + movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields + movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr + testl %eax,%eax # resolved entry null? + je .LOP_SGET_OBJECT_VOLATILE_resolve # if not, make it so +.LOP_SGET_OBJECT_VOLATILE_finish: # field ptr in eax + movl offStaticField_value(%eax),%eax + movzbl rINST_HI,%ecx # ecx<- AA + FETCH_INST_WORD(2) + ADVANCE_PC(2) + SET_VREG(%eax,%ecx) GOTO_NEXT + + /* ------------------------------ */ .balign 64 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ - /* (stub) */ - GET_GLUE(%ecx) - SAVE_PC_TO_GLUE(%ecx) # only need to export these two - SAVE_FP_TO_GLUE(%ecx) # only need to export these two - movl %ecx,OUT_ARG0(%esp) # glue is first arg to function - call dvmMterp_OP_SPUT_OBJECT_VOLATILE # do the real work +/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */ +/* File: x86/OP_SPUT_OBJECT.S */ + /* + * SPUT object handler. + */ + /* op vAA, field@BBBB */ GET_GLUE(%ecx) - LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values - LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values - FETCH_INST() - GOTO_NEXT + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex + movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields + movl (%ecx,%eax,4),%eax # eax<- resolved StaticField + testl %eax,%eax # resolved entry null? + je .LOP_SPUT_OBJECT_VOLATILE_resolve # if not, make it so +.LOP_SPUT_OBJECT_VOLATILE_finish: # field ptr in eax + movzbl rINST_HI,%ecx # ecx<- AA + GET_VREG(%ecx,%ecx) + jmp .LOP_SPUT_OBJECT_VOLATILE_continue + + /* ------------------------------ */ .balign 64 .L_OP_UNUSED_FF: /* 0xff */ @@ -6570,6 +6665,7 @@ dvmAsmSisterStart: movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags movzbl 1(%ecx),%ecx # ecx<- descriptor[1] movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass + GET_GLUE(%eax) cmpb $'I',%cl # supported? je 1f cmpb $'L',%cl @@ -6577,6 +6673,7 @@ dvmAsmSisterStart: cmpb $'[',%cl jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 1: + movl %ecx,offGlue_retval+4(%eax) # save type .if (!0) SPILL_TMP(rINST_FULL) # save copy, need "B" later sarl $4,rINST_FULL @@ -6610,7 +6707,9 @@ dvmAsmSisterStart: FETCH_INST_WORD(3) rep movsd + GET_GLUE(%ecx) UNSPILL(rIBASE) + movl offGlue_retval+4(%ecx),%eax # eax<- type UNSPILL(rFP) .else testl rINST_FULL,rINST_FULL @@ -6629,10 +6728,19 @@ dvmAsmSisterStart: sub $1,rINST_FULL jne 3b 4: + GET_GLUE(%ecx) UNSPILL(rPC) + movl offGlue_retval+4(%ecx),%eax # eax<- type FETCH_INST_WORD(3) .endif + cmpb $'I',%al # Int array? + je 5f # skip card mark if so + movl offGlue_retval(%ecx),%eax # eax<- object head + movl offGlue_cardTable(%ecx),%ecx # card table base + shrl $GC_CARD_SHIFT,%eax # convert to card num + movb %cl,(%ecx,%eax) # mark card +5: ADVANCE_PC(3) GOTO_NEXT @@ -6674,6 +6782,7 @@ dvmAsmSisterStart: movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags movzbl 1(%ecx),%ecx # ecx<- descriptor[1] movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass + GET_GLUE(%eax) cmpb $'I',%cl # supported? je 1f cmpb $'L',%cl @@ -6681,6 +6790,7 @@ dvmAsmSisterStart: cmpb $'[',%cl jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet 1: + movl %ecx,offGlue_retval+4(%eax) # save type .if (!1) SPILL_TMP(rINST_FULL) # save copy, need "B" later sarl $4,rINST_FULL @@ -6714,7 +6824,9 @@ dvmAsmSisterStart: FETCH_INST_WORD(3) rep movsd + GET_GLUE(%ecx) UNSPILL(rIBASE) + movl offGlue_retval+4(%ecx),%eax # eax<- type UNSPILL(rFP) .else testl rINST_FULL,rINST_FULL @@ -6733,10 +6845,19 @@ dvmAsmSisterStart: sub $1,rINST_FULL jne 3b 4: + GET_GLUE(%ecx) UNSPILL(rPC) + movl offGlue_retval+4(%ecx),%eax # eax<- type FETCH_INST_WORD(3) .endif + cmpb $'I',%al # Int array? + je 5f # skip card mark if so + movl offGlue_retval(%ecx),%eax # eax<- object head + movl offGlue_cardTable(%ecx),%ecx # card table base + shrl $GC_CARD_SHIFT,%eax # convert to card num + movb %cl,(%ecx,%eax) # mark card +5: ADVANCE_PC(3) GOTO_NEXT @@ -6838,7 +6959,15 @@ dvmAsmSisterStart: UNSPILL(rPC) UNSPILL_TMP(%ecx) testl %eax,%eax + GET_GLUE(%eax) je common_errArrayStore + movl offGlue_cardTable(%eax),%eax # get card table base + movl rINST_FULL,(%ecx) + FETCH_INST_WORD(2) + shrl $GC_CARD_SHIFT,%ecx # convert addr to card number + movb %al,(%eax,%ecx) # mark card + ADVANCE_PC(2) + GOTO_NEXT .LOP_APUT_OBJECT_skip_check: movl rINST_FULL,(%ecx) @@ -7213,8 +7342,15 @@ dvmAsmSisterStart: UNSPILL(rIBASE) testl %ecx,%ecx # object null? je common_errNullObject # object was null - movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) + movl rINST_FULL,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) + GET_GLUE(%eax) + testl rINST_FULL,rINST_FULL # stored a NULL? + movl offGlue_cardTable(%eax),%eax # get card table base FETCH_INST_WORD(2) + je 1f # skip card mark if null store + shrl $GC_CARD_SHIFT,%ecx # object head to card number + movb %al,(%eax,%ecx) # mark card +1: ADVANCE_PC(2) GOTO_NEXT @@ -7544,9 +7680,20 @@ dvmAsmSisterStart: /* continuation for OP_SPUT_OBJECT */ - /* - * Go resolve the field - */ + +.LOP_SPUT_OBJECT_continue: + movl %ecx,offStaticField_value(%eax) + testl %ecx,%ecx + GET_GLUE(%ecx) + FETCH_INST_WORD(2) + je 1f + movl offGlue_cardTable(%ecx),%ecx # get card table base + shrl $GC_CARD_SHIFT,%eax # head to card number + movb %cl,(%ecx,%eax) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT + .LOP_SPUT_OBJECT_resolve: GET_GLUE(%ecx) movzwl 2(rPC),%eax # eax<- field ref BBBB @@ -8319,6 +8466,156 @@ dvmAsmSisterStart: ADVANCE_PC(2) GOTO_NEXT +/* continuation for OP_IGET_VOLATILE */ + + +.LOP_IGET_VOLATILE_resolve: + EXPORT_PC() + SPILL(rPC) + movl offGlue_method(rIBASE),rPC # rPC<- current method + UNSPILL(rIBASE) + movl offMethod_clazz(rPC),rPC # rPC<- method->clazz + SPILL_TMP(%ecx) # save object pointer across call + movl rPC,OUT_ARG0(%esp) # pass in method->clazz + call dvmResolveInstField # ... to dvmResolveInstField + UNSPILL_TMP(%ecx) + UNSPILL(rPC) + testl %eax,%eax # ... which returns InstrField ptr + jne .LOP_IGET_VOLATILE_finish + jmp common_exceptionThrown + +.LOP_IGET_VOLATILE_finish: + /* + * Currently: + * eax holds resolved field + * ecx holds object + * rIBASE is scratch, but needs to be unspilled + * rINST_FULL holds A + */ + movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field + UNSPILL(rIBASE) + testl %ecx,%ecx # object null? + je common_errNullObject # object was null + movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) + movl rINST_FULL,%eax # eax<- A + FETCH_INST_WORD(2) + SET_VREG(%ecx,%eax) + ADVANCE_PC(2) + GOTO_NEXT + +/* continuation for OP_IPUT_VOLATILE */ + + +.LOP_IPUT_VOLATILE_resolve: + EXPORT_PC() + SPILL(rPC) + movl offGlue_method(rIBASE),rPC # rPC<- current method + UNSPILL(rIBASE) + movl offMethod_clazz(rPC),rPC # rPC<- method->clazz + SPILL_TMP(%ecx) # save object pointer across call + movl rPC,OUT_ARG0(%esp) # pass in method->clazz + call dvmResolveInstField # ... to dvmResolveInstField + UNSPILL_TMP(%ecx) + UNSPILL(rPC) + testl %eax,%eax # ... which returns InstrField ptr + jne .LOP_IPUT_VOLATILE_finish + jmp common_exceptionThrown + +.LOP_IPUT_VOLATILE_finish: + /* + * Currently: + * eax holds resolved field + * ecx holds object + * rIBASE is scratch, but needs to be unspilled + * rINST_FULL holds A + */ + GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] + movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field + UNSPILL(rIBASE) + testl %ecx,%ecx # object null? + je common_errNullObject # object was null + movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) + FETCH_INST_WORD(2) + ADVANCE_PC(2) + GOTO_NEXT + +/* continuation for OP_SGET_VOLATILE */ + + /* + * Go resolve the field + */ +.LOP_SGET_VOLATILE_resolve: + GET_GLUE(%ecx) + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_method(%ecx),%ecx # ecx<- current method + EXPORT_PC() # could throw, need to export + movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz + SPILL(rPC) + movl %eax,OUT_ARG1(%esp) + movl %ecx,OUT_ARG0(%esp) + call dvmResolveStaticField # eax<- resolved StaticField ptr + UNSPILL(rPC) + testl %eax,%eax + jne .LOP_SGET_VOLATILE_finish # success, continue + jmp common_exceptionThrown # no, handle exception + +/* continuation for OP_SPUT_VOLATILE */ + + /* + * Go resolve the field + */ +.LOP_SPUT_VOLATILE_resolve: + GET_GLUE(%ecx) + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_method(%ecx),%ecx # ecx<- current method + EXPORT_PC() # could throw, need to export + movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz + SPILL(rPC) + movl %eax,OUT_ARG1(%esp) + movl %ecx,OUT_ARG0(%esp) + call dvmResolveStaticField # eax<- resolved StaticField ptr + UNSPILL(rPC) + testl %eax,%eax + jne .LOP_SPUT_VOLATILE_finish # success, continue + jmp common_exceptionThrown # no, handle exception + +/* continuation for OP_IGET_OBJECT_VOLATILE */ + + +.LOP_IGET_OBJECT_VOLATILE_resolve: + EXPORT_PC() + SPILL(rPC) + movl offGlue_method(rIBASE),rPC # rPC<- current method + UNSPILL(rIBASE) + movl offMethod_clazz(rPC),rPC # rPC<- method->clazz + SPILL_TMP(%ecx) # save object pointer across call + movl rPC,OUT_ARG0(%esp) # pass in method->clazz + call dvmResolveInstField # ... to dvmResolveInstField + UNSPILL_TMP(%ecx) + UNSPILL(rPC) + testl %eax,%eax # ... which returns InstrField ptr + jne .LOP_IGET_OBJECT_VOLATILE_finish + jmp common_exceptionThrown + +.LOP_IGET_OBJECT_VOLATILE_finish: + /* + * Currently: + * eax holds resolved field + * ecx holds object + * rIBASE is scratch, but needs to be unspilled + * rINST_FULL holds A + */ + movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field + UNSPILL(rIBASE) + testl %ecx,%ecx # object null? + je common_errNullObject # object was null + movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) + movl rINST_FULL,%eax # eax<- A + FETCH_INST_WORD(2) + SET_VREG(%ecx,%eax) + ADVANCE_PC(2) + GOTO_NEXT + /* continuation for OP_EXECUTE_INLINE */ .LOP_EXECUTE_INLINE_continue: @@ -8361,6 +8658,113 @@ dvmAsmSisterStart: jmp *gDvmInlineOpsTable(%eax) # will return to caller of .LOP_EXECUTE_INLINE_continue +/* continuation for OP_IPUT_OBJECT_QUICK */ + +.LOP_IPUT_OBJECT_QUICK_finish: + testl rINST_FULL,rINST_FULL # did we store null? + FETCH_INST_WORD(2) + movl offGlue_cardTable(%eax),%eax # get card table base + je 1f # skip card mark if null store + shrl $GC_CARD_SHIFT,%ecx # object head to card number + movb %al,(%eax,%ecx) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT + +/* continuation for OP_IPUT_OBJECT_VOLATILE */ + + +.LOP_IPUT_OBJECT_VOLATILE_resolve: + EXPORT_PC() + SPILL(rPC) + movl offGlue_method(rIBASE),rPC # rPC<- current method + UNSPILL(rIBASE) + movl offMethod_clazz(rPC),rPC # rPC<- method->clazz + SPILL_TMP(%ecx) # save object pointer across call + movl rPC,OUT_ARG0(%esp) # pass in method->clazz + call dvmResolveInstField # ... to dvmResolveInstField + UNSPILL_TMP(%ecx) + UNSPILL(rPC) + testl %eax,%eax # ... which returns InstrField ptr + jne .LOP_IPUT_OBJECT_VOLATILE_finish + jmp common_exceptionThrown + +.LOP_IPUT_OBJECT_VOLATILE_finish: + /* + * Currently: + * eax holds resolved field + * ecx holds object + * rIBASE is scratch, but needs to be unspilled + * rINST_FULL holds A + */ + GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] + movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field + UNSPILL(rIBASE) + testl %ecx,%ecx # object null? + je common_errNullObject # object was null + movl rINST_FULL,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) + GET_GLUE(%eax) + testl rINST_FULL,rINST_FULL # stored a NULL? + movl offGlue_cardTable(%eax),%eax # get card table base + FETCH_INST_WORD(2) + je 1f # skip card mark if null store + shrl $GC_CARD_SHIFT,%ecx # object head to card number + movb %al,(%eax,%ecx) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT + +/* continuation for OP_SGET_OBJECT_VOLATILE */ + + /* + * Go resolve the field + */ +.LOP_SGET_OBJECT_VOLATILE_resolve: + GET_GLUE(%ecx) + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_method(%ecx),%ecx # ecx<- current method + EXPORT_PC() # could throw, need to export + movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz + SPILL(rPC) + movl %eax,OUT_ARG1(%esp) + movl %ecx,OUT_ARG0(%esp) + call dvmResolveStaticField # eax<- resolved StaticField ptr + UNSPILL(rPC) + testl %eax,%eax + jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue + jmp common_exceptionThrown # no, handle exception + +/* continuation for OP_SPUT_OBJECT_VOLATILE */ + + +.LOP_SPUT_OBJECT_VOLATILE_continue: + movl %ecx,offStaticField_value(%eax) + testl %ecx,%ecx + GET_GLUE(%ecx) + FETCH_INST_WORD(2) + je 1f + movl offGlue_cardTable(%ecx),%ecx # get card table base + shrl $GC_CARD_SHIFT,%eax # head to card number + movb %cl,(%ecx,%eax) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT + +.LOP_SPUT_OBJECT_VOLATILE_resolve: + GET_GLUE(%ecx) + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_method(%ecx),%ecx # ecx<- current method + EXPORT_PC() # could throw, need to export + movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz + SPILL(rPC) + movl %eax,OUT_ARG1(%esp) + movl %ecx,OUT_ARG0(%esp) + call dvmResolveStaticField # eax<- resolved StaticField ptr + UNSPILL(rPC) + testl %eax,%eax + jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue + jmp common_exceptionThrown # no, handle exception + .size dvmAsmSisterStart, .-dvmAsmSisterStart .global dvmAsmSisterEnd dvmAsmSisterEnd: diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c index 142d7c9f0..1ce03027f 100644 --- a/vm/mterp/out/InterpC-x86.c +++ b/vm/mterp/out/InterpC-x86.c @@ -1201,26 +1201,6 @@ GOTO_TARGET_DECL(exceptionThrown); } \ FINISH(2); -/* File: c/OP_IGET_VOLATILE.c */ -HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) -OP_END - -/* File: c/OP_IPUT_VOLATILE.c */ -HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) -OP_END - -/* File: c/OP_SGET_VOLATILE.c */ -HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) -OP_END - -/* File: c/OP_SPUT_VOLATILE.c */ -HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) -OP_END - -/* File: c/OP_IGET_OBJECT_VOLATILE.c */ -HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) -OP_END - /* File: c/OP_IGET_WIDE_VOLATILE.c */ HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) OP_END @@ -1282,18 +1262,6 @@ HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/) FINISH(3); OP_END -/* File: c/OP_IPUT_OBJECT_VOLATILE.c */ -HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) -OP_END - -/* File: c/OP_SGET_OBJECT_VOLATILE.c */ -HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) -OP_END - -/* File: c/OP_SPUT_OBJECT_VOLATILE.c */ -HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) -OP_END - /* File: c/gotoTargets.c */ /* * C footer. This has some common code shared by the various targets. diff --git a/vm/mterp/x86/OP_APUT_OBJECT.S b/vm/mterp/x86/OP_APUT_OBJECT.S index 20699503c..d2ec56557 100644 --- a/vm/mterp/x86/OP_APUT_OBJECT.S +++ b/vm/mterp/x86/OP_APUT_OBJECT.S @@ -37,7 +37,15 @@ UNSPILL(rPC) UNSPILL_TMP(%ecx) testl %eax,%eax + GET_GLUE(%eax) je common_errArrayStore + movl offGlue_cardTable(%eax),%eax # get card table base + movl rINST_FULL,(%ecx) + FETCH_INST_WORD(2) + shrl $$GC_CARD_SHIFT,%ecx # convert addr to card number + movb %al,(%eax,%ecx) # mark card + ADVANCE_PC(2) + GOTO_NEXT .L${opcode}_skip_check: movl rINST_FULL,(%ecx) diff --git a/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S b/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S index a98f6b955..b990aeb81 100644 --- a/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S +++ b/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S @@ -48,6 +48,7 @@ movl $$ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags movzbl 1(%ecx),%ecx # ecx<- descriptor[1] movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass + GET_GLUE(%eax) cmpb $$'I',%cl # supported? je 1f cmpb $$'L',%cl @@ -55,6 +56,7 @@ cmpb $$'[',%cl jne .L${opcode}_notimpl # no, not handled yet 1: + movl %ecx,offGlue_retval+4(%eax) # save type .if (!$isrange) SPILL_TMP(rINST_FULL) # save copy, need "B" later sarl $$4,rINST_FULL @@ -88,7 +90,9 @@ FETCH_INST_WORD(3) rep movsd + GET_GLUE(%ecx) UNSPILL(rIBASE) + movl offGlue_retval+4(%ecx),%eax # eax<- type UNSPILL(rFP) .else testl rINST_FULL,rINST_FULL @@ -107,10 +111,19 @@ sub $$1,rINST_FULL jne 3b 4: + GET_GLUE(%ecx) UNSPILL(rPC) + movl offGlue_retval+4(%ecx),%eax # eax<- type FETCH_INST_WORD(3) .endif + cmpb $$'I',%al # Int array? + je 5f # skip card mark if so + movl offGlue_retval(%ecx),%eax # eax<- object head + movl offGlue_cardTable(%ecx),%ecx # card table base + shrl $$GC_CARD_SHIFT,%eax # convert to card num + movb %cl,(%ecx,%eax) # mark card +5: ADVANCE_PC(3) GOTO_NEXT diff --git a/vm/mterp/x86/OP_IGET_OBJECT_VOLATILE.S b/vm/mterp/x86/OP_IGET_OBJECT_VOLATILE.S new file mode 100644 index 000000000..4576d391d --- /dev/null +++ b/vm/mterp/x86/OP_IGET_OBJECT_VOLATILE.S @@ -0,0 +1,3 @@ +%verify "executed" +%verify "negative value is sign-extended" +%include "x86/OP_IGET.S" diff --git a/vm/mterp/x86/OP_IGET_VOLATILE.S b/vm/mterp/x86/OP_IGET_VOLATILE.S new file mode 100644 index 000000000..4576d391d --- /dev/null +++ b/vm/mterp/x86/OP_IGET_VOLATILE.S @@ -0,0 +1,3 @@ +%verify "executed" +%verify "negative value is sign-extended" +%include "x86/OP_IGET.S" diff --git a/vm/mterp/x86/OP_IPUT_OBJECT.S b/vm/mterp/x86/OP_IPUT_OBJECT.S index caf007e6e..39c64e712 100644 --- a/vm/mterp/x86/OP_IPUT_OBJECT.S +++ b/vm/mterp/x86/OP_IPUT_OBJECT.S @@ -1,2 +1,70 @@ +%default { "sqnum":"0" } %verify "executed" -%include "x86/OP_IPUT.S" +%verify "null object" +%verify "field already resolved" +%verify "field not yet resolved" +%verify "field cannot be resolved" + /* + * Object field put. + * + * for: iput-object + */ + /* op vA, vB, field@CCCC */ + GET_GLUE(%ecx) + SPILL(rIBASE) # need another reg + movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC + movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex + movzbl rINST_HI,%ecx # ecx<- BA + sarl $$4,%ecx # ecx<- B + movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields + movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA + andb $$0xf,rINST_LO # rINST_FULL<- A + GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr + movl (%eax,rIBASE,4),%eax # resolved entry + testl %eax,%eax # is resolved entry null? + jne .L${opcode}_finish # no, already resolved + movl rIBASE,OUT_ARG1(%esp) + GET_GLUE(rIBASE) + jmp .L${opcode}_resolve +%break + + +.L${opcode}_resolve: + EXPORT_PC() + SPILL(rPC) + movl offGlue_method(rIBASE),rPC # rPC<- current method + UNSPILL(rIBASE) + movl offMethod_clazz(rPC),rPC # rPC<- method->clazz + SPILL_TMP(%ecx) # save object pointer across call + movl rPC,OUT_ARG0(%esp) # pass in method->clazz + call dvmResolveInstField # ... to dvmResolveInstField + UNSPILL_TMP(%ecx) + UNSPILL(rPC) + testl %eax,%eax # ... which returns InstrField ptr + jne .L${opcode}_finish + jmp common_exceptionThrown + +.L${opcode}_finish: + /* + * Currently: + * eax holds resolved field + * ecx holds object + * rIBASE is scratch, but needs to be unspilled + * rINST_FULL holds A + */ + GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] + movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field + UNSPILL(rIBASE) + testl %ecx,%ecx # object null? + je common_errNullObject # object was null + movl rINST_FULL,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) + GET_GLUE(%eax) + testl rINST_FULL,rINST_FULL # stored a NULL? + movl offGlue_cardTable(%eax),%eax # get card table base + FETCH_INST_WORD(2) + je 1f # skip card mark if null store + shrl $$GC_CARD_SHIFT,%ecx # object head to card number + movb %al,(%eax,%ecx) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT diff --git a/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S b/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S index a8e851cb2..fb7205b38 100644 --- a/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S +++ b/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S @@ -1,2 +1,28 @@ %verify "executed" -%include "x86/OP_IPUT_QUICK.S" +%verify "null object" + /* For: iput-object-quick */ + /* op vA, vB, offset@CCCC */ + movzbl rINST_HI,%ecx # ecx<- BA + sarl $$4,%ecx # ecx<- B + GET_VREG(%ecx,%ecx) # vB (object we're operating on) + movzbl rINST_HI,rINST_FULL + andb $$0xf,rINST_LO # rINST_FULL<- A + GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] + movzwl 2(rPC),%eax # eax<- field byte offset + testl %ecx,%ecx # is object null? + je common_errNullObject + movl rINST_FULL,(%ecx,%eax,1) + GET_GLUE(%eax) + jmp .L${opcode}_finish +%break + +.L${opcode}_finish: + testl rINST_FULL,rINST_FULL # did we store null? + FETCH_INST_WORD(2) + movl offGlue_cardTable(%eax),%eax # get card table base + je 1f # skip card mark if null store + shrl $$GC_CARD_SHIFT,%ecx # object head to card number + movb %al,(%eax,%ecx) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT diff --git a/vm/mterp/x86/OP_IPUT_OBJECT_VOLATILE.S b/vm/mterp/x86/OP_IPUT_OBJECT_VOLATILE.S new file mode 100644 index 000000000..3959c06dd --- /dev/null +++ b/vm/mterp/x86/OP_IPUT_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "x86/OP_IPUT_OBJECT.S" diff --git a/vm/mterp/x86/OP_IPUT_QUICK.S b/vm/mterp/x86/OP_IPUT_QUICK.S index 60d6fadc4..e62ec00fc 100644 --- a/vm/mterp/x86/OP_IPUT_QUICK.S +++ b/vm/mterp/x86/OP_IPUT_QUICK.S @@ -1,6 +1,6 @@ %verify "executed" %verify "null object" - /* For: iput-quick, iput-object-quick */ + /* For: iput-quick */ /* op vA, vB, offset@CCCC */ movzbl rINST_HI,%ecx # ecx<- BA sarl $$4,%ecx # ecx<- B diff --git a/vm/mterp/x86/OP_IPUT_VOLATILE.S b/vm/mterp/x86/OP_IPUT_VOLATILE.S new file mode 100644 index 000000000..caf007e6e --- /dev/null +++ b/vm/mterp/x86/OP_IPUT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "x86/OP_IPUT.S" diff --git a/vm/mterp/x86/OP_SGET_OBJECT_VOLATILE.S b/vm/mterp/x86/OP_SGET_OBJECT_VOLATILE.S new file mode 100644 index 000000000..3b3a492d1 --- /dev/null +++ b/vm/mterp/x86/OP_SGET_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "x86/OP_SGET.S" diff --git a/vm/mterp/x86/OP_SGET_VOLATILE.S b/vm/mterp/x86/OP_SGET_VOLATILE.S new file mode 100644 index 000000000..3b3a492d1 --- /dev/null +++ b/vm/mterp/x86/OP_SGET_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "x86/OP_SGET.S" diff --git a/vm/mterp/x86/OP_SPUT.S b/vm/mterp/x86/OP_SPUT.S index 952ca8750..440dcfbcf 100644 --- a/vm/mterp/x86/OP_SPUT.S +++ b/vm/mterp/x86/OP_SPUT.S @@ -5,7 +5,7 @@ /* * General 32-bit SPUT handler. * - * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + * for: sput, sput-boolean, sput-byte, sput-char, sput-short */ /* op vAA, field@BBBB */ GET_GLUE(%ecx) diff --git a/vm/mterp/x86/OP_SPUT_OBJECT.S b/vm/mterp/x86/OP_SPUT_OBJECT.S index ec0489fe3..f55d15110 100644 --- a/vm/mterp/x86/OP_SPUT_OBJECT.S +++ b/vm/mterp/x86/OP_SPUT_OBJECT.S @@ -1,2 +1,49 @@ %verify "executed" -%include "x86/OP_SPUT.S" +%verify "field already resolved" +%verify "field not yet resolved" +%verify "field cannot be resolved" + /* + * SPUT object handler. + */ + /* op vAA, field@BBBB */ + GET_GLUE(%ecx) + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex + movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields + movl (%ecx,%eax,4),%eax # eax<- resolved StaticField + testl %eax,%eax # resolved entry null? + je .L${opcode}_resolve # if not, make it so +.L${opcode}_finish: # field ptr in eax + movzbl rINST_HI,%ecx # ecx<- AA + GET_VREG(%ecx,%ecx) + jmp .L${opcode}_continue +%break + + +.L${opcode}_continue: + movl %ecx,offStaticField_value(%eax) + testl %ecx,%ecx + GET_GLUE(%ecx) + FETCH_INST_WORD(2) + je 1f + movl offGlue_cardTable(%ecx),%ecx # get card table base + shrl $$GC_CARD_SHIFT,%eax # head to card number + movb %cl,(%ecx,%eax) # mark card +1: + ADVANCE_PC(2) + GOTO_NEXT + +.L${opcode}_resolve: + GET_GLUE(%ecx) + movzwl 2(rPC),%eax # eax<- field ref BBBB + movl offGlue_method(%ecx),%ecx # ecx<- current method + EXPORT_PC() # could throw, need to export + movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz + SPILL(rPC) + movl %eax,OUT_ARG1(%esp) + movl %ecx,OUT_ARG0(%esp) + call dvmResolveStaticField # eax<- resolved StaticField ptr + UNSPILL(rPC) + testl %eax,%eax + jne .L${opcode}_finish # success, continue + jmp common_exceptionThrown # no, handle exception diff --git a/vm/mterp/x86/OP_SPUT_OBJECT_VOLATILE.S b/vm/mterp/x86/OP_SPUT_OBJECT_VOLATILE.S new file mode 100644 index 000000000..afc666874 --- /dev/null +++ b/vm/mterp/x86/OP_SPUT_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "x86/OP_SPUT_OBJECT.S" diff --git a/vm/mterp/x86/OP_SPUT_VOLATILE.S b/vm/mterp/x86/OP_SPUT_VOLATILE.S new file mode 100644 index 000000000..ec0489fe3 --- /dev/null +++ b/vm/mterp/x86/OP_SPUT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "x86/OP_SPUT.S"