Change GC card making to use object head, bug fix for volatile sput obj

This CL changes the way we mark GC card to consistently use the object
head (previously, we marked somewhere in the object - often the head, but
not always).  Also, previously a coding error caused us to skip the card
mark for OP_APUT_OBJECT_VOLATILES.  Fixed here.

Change-Id: I53eb333b9bd0b770201af0dc617d9a8f38afa699
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index f6f2ad9..44f47b7 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1522,7 +1522,9 @@
         case OP_SPUT: {
             int valOffset = offsetof(StaticField, value);
             int tReg = dvmCompilerAllocTemp(cUnit);
+            int objHead;
             bool isVolatile;
+            bool isSputObject;
             const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ?
                 mir->meta.calleeMethod : cUnit->method;
             void *fieldPtr = (void*)
@@ -1532,6 +1534,9 @@
                          (mir->dalvikInsn.opCode == OP_SPUT_OBJECT_VOLATILE) ||
                          dvmIsVolatileField(fieldPtr);
 
+            isSputObject = (mir->dalvikInsn.opCode == OP_SPUT_OBJECT) ||
+                           (mir->dalvikInsn.opCode == OP_SPUT_OBJECT_VOLATILE);
+
             if (fieldPtr == NULL) {
                 LOGE("Unexpected null static field");
                 dvmAbort();
@@ -1540,18 +1545,22 @@
             rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
             rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
             loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
-
+            if (isSputObject) {
+                objHead = dvmCompilerAllocTemp(cUnit);
+                loadConstant(cUnit, objHead, (intptr_t)method->clazz);
+            }
             HEAP_ACCESS_SHADOW(true);
             storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
+            dvmCompilerFreeTemp(cUnit, tReg);
             HEAP_ACCESS_SHADOW(false);
             if (isVolatile) {
                 dvmCompilerGenMemBarrier(cUnit);
             }
-            if (mir->dalvikInsn.opCode == OP_SPUT_OBJECT) {
-                /* NOTE: marking card based on field address */
-                markCard(cUnit, rlSrc.lowReg, tReg);
+            if (isSputObject) {
+                /* NOTE: marking card based object head */
+                markCard(cUnit, rlSrc.lowReg, objHead);
+                dvmCompilerFreeTemp(cUnit, objHead);
             }
-            dvmCompilerFreeTemp(cUnit, tReg);
 
             break;
         }
diff --git a/vm/mterp/armv5te/OP_APUT_OBJECT.S b/vm/mterp/armv5te/OP_APUT_OBJECT.S
index e926db6..9e98784 100644
--- a/vm/mterp/armv5te/OP_APUT_OBJECT.S
+++ b/vm/mterp/armv5te/OP_APUT_OBJECT.S
@@ -10,13 +10,13 @@
     mov     r9, rINST, lsr #8           @ r9<- AA
     and     r2, r0, #255                @ r2<- BB
     mov     r3, r0, lsr #8              @ r3<- CC
-    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
-    cmp     r1, #0                      @ null array object?
+    cmp     rINST, #0                   @ null array object?
     GET_VREG(r9, r9)                    @ r9<- vAA
     beq     common_errNullObject        @ yes, bail
-    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
-    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
+    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
     cmp     r0, r3                      @ compare unsigned index, length
     bcc     .L${opcode}_finish          @ we're okay, continue on
     b       common_errArrayIndex        @ index >= length, bail
@@ -24,7 +24,7 @@
 %break
     /*
      * On entry:
-     *  r1 = vBB (arrayObj)
+     *  rINST = vBB (arrayObj)
      *  r9 = vAA (obj)
      *  r10 = offset into array (vBB + vCC * width)
      */
@@ -32,16 +32,17 @@
     cmp     r9, #0                      @ storing null reference?
     beq     .L${opcode}_skip_check      @ yes, skip type checks
     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
-    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
     bl      dvmCanPutArrayElement       @ test object type vs. array type
     cmp     r0, #0                      @ okay?
     beq     common_errArrayStore        @ no
+    mov     r1, rINST                   @ r1<- arrayObj
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     str     r9, [r10]                   @ vBB[vCC]<- vAA
-    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
+    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 .L${opcode}_skip_check:
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
diff --git a/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S b/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S
index b9abe5a..5bb2d43 100644
--- a/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S
+++ b/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S
@@ -87,7 +87,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
diff --git a/vm/mterp/armv5te/OP_IPUT_OBJECT.S b/vm/mterp/armv5te/OP_IPUT_OBJECT.S
index 5e0fe83..079094e 100644
--- a/vm/mterp/armv5te/OP_IPUT_OBJECT.S
+++ b/vm/mterp/armv5te/OP_IPUT_OBJECT.S
@@ -42,10 +42,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     $barrier                            @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_IPUT_OBJECT_QUICK.S b/vm/mterp/armv5te/OP_IPUT_OBJECT_QUICK.S
index 648a69c..7e7144a 100644
--- a/vm/mterp/armv5te/OP_IPUT_OBJECT_QUICK.S
+++ b/vm/mterp/armv5te/OP_IPUT_OBJECT_QUICK.S
@@ -14,6 +14,6 @@
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
     cmp     r0, #0
-    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
+    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_SPUT_OBJECT.S b/vm/mterp/armv5te/OP_SPUT_OBJECT.S
index 54a04fc..5d9baec 100644
--- a/vm/mterp/armv5te/OP_SPUT_OBJECT.S
+++ b/vm/mterp/armv5te/OP_SPUT_OBJECT.S
@@ -14,25 +14,26 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .L${opcode}_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .L${opcode}_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
 %break
-.L${opcode}_finish:   @ field ptr in r0
+.L${opcode}_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     $barrier                            @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 0fb8a1c..b944a4b 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -2290,13 +2290,13 @@
     mov     r9, rINST, lsr #8           @ r9<- AA
     and     r2, r0, #255                @ r2<- BB
     mov     r3, r0, lsr #8              @ r3<- CC
-    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
-    cmp     r1, #0                      @ null array object?
+    cmp     rINST, #0                   @ null array object?
     GET_VREG(r9, r9)                    @ r9<- vAA
     beq     common_errNullObject        @ yes, bail
-    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
-    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
+    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
     cmp     r0, r3                      @ compare unsigned index, length
     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
     b       common_errArrayIndex        @ index >= length, bail
@@ -3069,10 +3069,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
@@ -7900,7 +7900,7 @@
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
     cmp     r0, #0
-    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
+    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -8083,10 +8083,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
@@ -8421,7 +8421,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8505,7 +8505,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8726,7 +8726,7 @@
 /* continuation for OP_APUT_OBJECT */
     /*
      * On entry:
-     *  r1 = vBB (arrayObj)
+     *  rINST = vBB (arrayObj)
      *  r9 = vAA (obj)
      *  r10 = offset into array (vBB + vCC * width)
      */
@@ -8734,16 +8734,17 @@
     cmp     r9, #0                      @ storing null reference?
     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
-    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
     bl      dvmCanPutArrayElement       @ test object type vs. array type
     cmp     r0, #0                      @ okay?
     beq     common_errArrayStore        @ no
+    mov     r1, rINST                   @ r1<- arrayObj
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     str     r9, [r10]                   @ vBB[vCC]<- vAA
-    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
+    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 .LOP_APUT_OBJECT_skip_check:
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
@@ -8966,10 +8967,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     @ no-op                             @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9200,17 +9200,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT */
-.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     @ no-op                             @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
 /* continuation for OP_SPUT_BOOLEAN */
@@ -9809,10 +9810,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     SMP_DMB                            @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9833,17 +9833,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT_VOLATILE */
-.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     SMP_DMB                            @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 88dc89c..ba4f5c3 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -2270,13 +2270,13 @@
     mov     r9, rINST, lsr #8           @ r9<- AA
     and     r2, r0, #255                @ r2<- BB
     mov     r3, r0, lsr #8              @ r3<- CC
-    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
-    cmp     r1, #0                      @ null array object?
+    cmp     rINST, #0                   @ null array object?
     GET_VREG(r9, r9)                    @ r9<- vAA
     beq     common_errNullObject        @ yes, bail
-    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
-    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
+    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
     cmp     r0, r3                      @ compare unsigned index, length
     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
     b       common_errArrayIndex        @ index >= length, bail
@@ -3049,10 +3049,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
@@ -7578,7 +7578,7 @@
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
     cmp     r0, #0
-    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
+    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7761,10 +7761,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
@@ -8099,7 +8099,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8183,7 +8183,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8266,7 +8266,7 @@
 /* continuation for OP_APUT_OBJECT */
     /*
      * On entry:
-     *  r1 = vBB (arrayObj)
+     *  rINST = vBB (arrayObj)
      *  r9 = vAA (obj)
      *  r10 = offset into array (vBB + vCC * width)
      */
@@ -8274,16 +8274,17 @@
     cmp     r9, #0                      @ storing null reference?
     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
-    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
     bl      dvmCanPutArrayElement       @ test object type vs. array type
     cmp     r0, #0                      @ okay?
     beq     common_errArrayStore        @ no
+    mov     r1, rINST                   @ r1<- arrayObj
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     str     r9, [r10]                   @ vBB[vCC]<- vAA
-    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
+    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 .LOP_APUT_OBJECT_skip_check:
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
@@ -8505,10 +8506,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     @ no-op                             @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -8739,17 +8739,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT */
-.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     @ no-op                             @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
 /* continuation for OP_SPUT_BOOLEAN */
@@ -9347,10 +9348,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     SMP_DMB                            @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9371,17 +9371,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT_VOLATILE */
-.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     SMP_DMB                            @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 47c8002..ad38849 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -2292,13 +2292,13 @@
     mov     r9, rINST, lsr #8           @ r9<- AA
     and     r2, r0, #255                @ r2<- BB
     mov     r3, r0, lsr #8              @ r3<- CC
-    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
-    cmp     r1, #0                      @ null array object?
+    cmp     rINST, #0                   @ null array object?
     GET_VREG(r9, r9)                    @ r9<- vAA
     beq     common_errNullObject        @ yes, bail
-    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
-    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
+    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
     cmp     r0, r3                      @ compare unsigned index, length
     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
     b       common_errArrayIndex        @ index >= length, bail
@@ -3071,10 +3071,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
@@ -7900,7 +7900,7 @@
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
     cmp     r0, #0
-    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
+    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -8083,10 +8083,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
@@ -8421,7 +8421,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8505,7 +8505,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8724,7 +8724,7 @@
 /* continuation for OP_APUT_OBJECT */
     /*
      * On entry:
-     *  r1 = vBB (arrayObj)
+     *  rINST = vBB (arrayObj)
      *  r9 = vAA (obj)
      *  r10 = offset into array (vBB + vCC * width)
      */
@@ -8732,16 +8732,17 @@
     cmp     r9, #0                      @ storing null reference?
     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
-    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
     bl      dvmCanPutArrayElement       @ test object type vs. array type
     cmp     r0, #0                      @ okay?
     beq     common_errArrayStore        @ no
+    mov     r1, rINST                   @ r1<- arrayObj
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     str     r9, [r10]                   @ vBB[vCC]<- vAA
-    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
+    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 .LOP_APUT_OBJECT_skip_check:
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
@@ -8963,10 +8964,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     @ no-op                             @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9197,17 +9197,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT */
-.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     @ no-op                             @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
 /* continuation for OP_SPUT_BOOLEAN */
@@ -9805,10 +9806,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     SMP_DMB                            @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9829,17 +9829,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT_VOLATILE */
-.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     SMP_DMB                            @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index 46e6b63..4d1c234 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -2274,13 +2274,13 @@
     mov     r9, rINST, lsr #8           @ r9<- AA
     and     r2, r0, #255                @ r2<- BB
     mov     r3, r0, lsr #8              @ r3<- CC
-    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
-    cmp     r1, #0                      @ null array object?
+    cmp     rINST, #0                   @ null array object?
     GET_VREG(r9, r9)                    @ r9<- vAA
     beq     common_errNullObject        @ yes, bail
-    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
-    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
+    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
     cmp     r0, r3                      @ compare unsigned index, length
     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
     b       common_errArrayIndex        @ index >= length, bail
@@ -3053,10 +3053,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
@@ -7532,7 +7532,7 @@
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
     cmp     r0, #0
-    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
+    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7715,10 +7715,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
@@ -8053,7 +8053,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8137,7 +8137,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8220,7 +8220,7 @@
 /* continuation for OP_APUT_OBJECT */
     /*
      * On entry:
-     *  r1 = vBB (arrayObj)
+     *  rINST = vBB (arrayObj)
      *  r9 = vAA (obj)
      *  r10 = offset into array (vBB + vCC * width)
      */
@@ -8228,16 +8228,17 @@
     cmp     r9, #0                      @ storing null reference?
     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
-    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
     bl      dvmCanPutArrayElement       @ test object type vs. array type
     cmp     r0, #0                      @ okay?
     beq     common_errArrayStore        @ no
+    mov     r1, rINST                   @ r1<- arrayObj
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     str     r9, [r10]                   @ vBB[vCC]<- vAA
-    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
+    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 .LOP_APUT_OBJECT_skip_check:
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
@@ -8443,10 +8444,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     @ no-op                             @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -8677,17 +8677,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT */
-.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     @ no-op                             @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
 /* continuation for OP_SPUT_BOOLEAN */
@@ -9285,10 +9286,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     SMP_DMB                            @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9309,17 +9309,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT_VOLATILE */
-.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     SMP_DMB                            @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index c092019..b3fd662 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -2274,13 +2274,13 @@
     mov     r9, rINST, lsr #8           @ r9<- AA
     and     r2, r0, #255                @ r2<- BB
     mov     r3, r0, lsr #8              @ r3<- CC
-    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
-    cmp     r1, #0                      @ null array object?
+    cmp     rINST, #0                   @ null array object?
     GET_VREG(r9, r9)                    @ r9<- vAA
     beq     common_errNullObject        @ yes, bail
-    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
-    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
+    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
     cmp     r0, r3                      @ compare unsigned index, length
     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
     b       common_errArrayIndex        @ index >= length, bail
@@ -3053,10 +3053,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
@@ -7532,7 +7532,7 @@
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
     cmp     r0, #0
-    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
+    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7715,10 +7715,10 @@
     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ is resolved entry null?
+    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
-    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
     EXPORT_PC()                         @ resolve() could throw, so export now
-    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
@@ -8053,7 +8053,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8137,7 +8137,7 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
     cmp     r1, #'I'                         @ Is int array?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
+    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
     GOTO_OPCODE(ip)                          @ execute it
 
     /*
@@ -8220,7 +8220,7 @@
 /* continuation for OP_APUT_OBJECT */
     /*
      * On entry:
-     *  r1 = vBB (arrayObj)
+     *  rINST = vBB (arrayObj)
      *  r9 = vAA (obj)
      *  r10 = offset into array (vBB + vCC * width)
      */
@@ -8228,16 +8228,17 @@
     cmp     r9, #0                      @ storing null reference?
     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
-    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
     bl      dvmCanPutArrayElement       @ test object type vs. array type
     cmp     r0, #0                      @ okay?
     beq     common_errArrayStore        @ no
+    mov     r1, rINST                   @ r1<- arrayObj
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     str     r9, [r10]                   @ vBB[vCC]<- vAA
-    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
+    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 .LOP_APUT_OBJECT_skip_check:
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
@@ -8443,10 +8444,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     @ no-op                             @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -8677,17 +8677,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT */
-.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     @ no-op                             @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
 /* continuation for OP_SPUT_BOOLEAN */
@@ -9285,10 +9286,9 @@
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    add     r9, r3                      @ r9<- direct ptr to target location
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     SMP_DMB                            @ releasing store
-    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
+    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
     cmp     r0, #0                      @ stored a null reference?
     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -9309,17 +9309,18 @@
     b       common_exceptionThrown      @ no, handle exception
 
 /* continuation for OP_SPUT_OBJECT_VOLATILE */
-.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
+.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0, method in r9
     mov     r2, rINST, lsr #8           @ r2<- AA
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     GET_VREG(r1, r2)                    @ r1<- fp[AA]
     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     add     r0, #offStaticField_value   @ r0<- pointer to store target
     SMP_DMB                            @ releasing store
     str     r1, [r0]                    @ field<- vAA
     cmp     r1, #0                      @ stored a null object?
-    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
+    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 324258f..f256ac1 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -2894,7 +2894,7 @@
     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
+.LOP_SPUT_OBJECT_finish:                              # field ptr in eax
     movzbl    rINSTbl,%ecx                       # ecx<- AA
     GET_VREG_R  %ecx %ecx
     jmp       .LOP_SPUT_OBJECT_continue
@@ -6395,7 +6395,7 @@
     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
+.LOP_SPUT_OBJECT_VOLATILE_finish:                              # field ptr in eax
     movzbl    rINSTbl,%ecx                       # ecx<- AA
     GET_VREG_R  %ecx %ecx
     jmp       .LOP_SPUT_OBJECT_VOLATILE_continue
@@ -6826,7 +6826,7 @@
     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
+    movb    %cl,(%ecx,%eax)                  # mark card based on object head
 5:
     ADVANCE_PC 3
     GOTO_NEXT_R %edx
@@ -6936,7 +6936,7 @@
     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
+    movb    %cl,(%ecx,%eax)                  # mark card based on object head
 5:
     ADVANCE_PC 3
     GOTO_NEXT_R %edx
@@ -7024,23 +7024,25 @@
      */
 .LOP_APUT_OBJECT_continue:
     leal      offArrayObject_contents(%eax,%ecx,4),%ecx
-    testl     rINST,rINST     # storing null reference?
+    testl     rINST,rINST                    # storing null reference?
     je        .LOP_APUT_OBJECT_skip_check
-    SPILL_TMP1(%ecx)
-    movl      offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
-    movl      offObject_clazz(rINST),%ecx # ecx<- obj->clazz
+    SPILL_TMP1(%ecx)                         # save target address
+    SPILL_TMP2(%eax)                         # save object head
+    movl      offObject_clazz(%eax),%eax     # eax<- arrayObj->clazz
+    movl      offObject_clazz(rINST),%ecx    # ecx<- obj->clazz
     movl      %eax,OUT_ARG1(%esp)
     movl      %ecx,OUT_ARG0(%esp)
-    call      dvmCanPutArrayElement     # test object type vs. array type
-    UNSPILL_TMP1(%ecx)
+    call      dvmCanPutArrayElement          # test object type vs. array type
+    UNSPILL_TMP1(%ecx)                       # recover target address
     testl     %eax,%eax
     movl      rGLUE,%eax
     je        common_errArrayStore
     movl      offGlue_cardTable(%eax),%eax   # get card table base
-    movl      rINST,(%ecx)
+    movl      rINST,(%ecx)                   # store into array
+    UNSPILL_TMP2(%ecx)                       # recover object head
     FETCH_INST_OPCODE 2 %edx
-    shrl      $GC_CARD_SHIFT,%ecx           # convert addr to card number
-    movb      %al,(%eax,%ecx)                # mark card
+    shrl      $GC_CARD_SHIFT,%ecx           # object head to card number
+    movb      %al,(%eax,%ecx)                # mark card using object head
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
 
@@ -7376,7 +7378,7 @@
     FETCH_INST_OPCODE 2 %edx
     je      1f                                  # skip card mark if null store
     shrl    $GC_CARD_SHIFT,%ecx                # object head to card number
-    movb    %al,(%eax,%ecx)                     # mark card
+    movb    %al,(%eax,%ecx)                     # mark card using object head
 1:
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
@@ -7671,11 +7673,13 @@
 
 
 .LOP_SPUT_OBJECT_continue:
-    movl      %ecx,offStaticField_value(%eax)
-    testl     %ecx,%ecx
+    movl      %ecx,offStaticField_value(%eax)    # do the store
+    testl     %ecx,%ecx                          # stored null object ptr?
     movl      rGLUE,%ecx
     FETCH_INST_OPCODE 2 %edx
-    je        1f
+    movl      offGlue_method(%ecx),%eax          # eax<- current method
+    je        1f                                 # skip card mark if null
+    movl      offMethod_clazz(%eax),%eax         # eax<- method->clazz
     movl      offGlue_cardTable(%ecx),%ecx       # get card table base
     shrl      $GC_CARD_SHIFT,%eax               # head to card number
     movb      %cl,(%ecx,%eax)                    # mark card
@@ -8584,7 +8588,7 @@
     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
+    movb      %al,(%eax,%ecx)               # mark card based on object head
 1:
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
@@ -8623,7 +8627,7 @@
     FETCH_INST_OPCODE 2 %edx
     je      1f                                  # skip card mark if null store
     shrl    $GC_CARD_SHIFT,%ecx                # object head to card number
-    movb    %al,(%eax,%ecx)                     # mark card
+    movb    %al,(%eax,%ecx)                     # mark card using object head
 1:
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
@@ -8650,11 +8654,13 @@
 
 
 .LOP_SPUT_OBJECT_VOLATILE_continue:
-    movl      %ecx,offStaticField_value(%eax)
-    testl     %ecx,%ecx
+    movl      %ecx,offStaticField_value(%eax)    # do the store
+    testl     %ecx,%ecx                          # stored null object ptr?
     movl      rGLUE,%ecx
     FETCH_INST_OPCODE 2 %edx
-    je        1f
+    movl      offGlue_method(%ecx),%eax          # eax<- current method
+    je        1f                                 # skip card mark if null
+    movl      offMethod_clazz(%eax),%eax         # eax<- method->clazz
     movl      offGlue_cardTable(%ecx),%ecx       # get card table base
     shrl      $GC_CARD_SHIFT,%eax               # head to card number
     movb      %cl,(%ecx,%eax)                    # mark card
diff --git a/vm/mterp/x86/OP_APUT_OBJECT.S b/vm/mterp/x86/OP_APUT_OBJECT.S
index 8ffbb03..f9af064 100644
--- a/vm/mterp/x86/OP_APUT_OBJECT.S
+++ b/vm/mterp/x86/OP_APUT_OBJECT.S
@@ -24,23 +24,25 @@
      */
 .L${opcode}_continue:
     leal      offArrayObject_contents(%eax,%ecx,4),%ecx
-    testl     rINST,rINST     # storing null reference?
+    testl     rINST,rINST                    # storing null reference?
     je        .L${opcode}_skip_check
-    SPILL_TMP1(%ecx)
-    movl      offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
-    movl      offObject_clazz(rINST),%ecx # ecx<- obj->clazz
+    SPILL_TMP1(%ecx)                         # save target address
+    SPILL_TMP2(%eax)                         # save object head
+    movl      offObject_clazz(%eax),%eax     # eax<- arrayObj->clazz
+    movl      offObject_clazz(rINST),%ecx    # ecx<- obj->clazz
     movl      %eax,OUT_ARG1(%esp)
     movl      %ecx,OUT_ARG0(%esp)
-    call      dvmCanPutArrayElement     # test object type vs. array type
-    UNSPILL_TMP1(%ecx)
+    call      dvmCanPutArrayElement          # test object type vs. array type
+    UNSPILL_TMP1(%ecx)                       # recover target address
     testl     %eax,%eax
     movl      rGLUE,%eax
     je        common_errArrayStore
     movl      offGlue_cardTable(%eax),%eax   # get card table base
-    movl      rINST,(%ecx)
+    movl      rINST,(%ecx)                   # store into array
+    UNSPILL_TMP2(%ecx)                       # recover object head
     FETCH_INST_OPCODE 2 %edx
-    shrl      $$GC_CARD_SHIFT,%ecx           # convert addr to card number
-    movb      %al,(%eax,%ecx)                # mark card
+    shrl      $$GC_CARD_SHIFT,%ecx           # object head to card number
+    movb      %al,(%eax,%ecx)                # mark card using object head
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
 
diff --git a/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S b/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S
index 60974ac..dc11dd2 100644
--- a/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S
+++ b/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S
@@ -114,7 +114,7 @@
     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
+    movb    %cl,(%ecx,%eax)                  # mark card based on object head
 5:
     ADVANCE_PC 3
     GOTO_NEXT_R %edx
diff --git a/vm/mterp/x86/OP_IPUT_OBJECT.S b/vm/mterp/x86/OP_IPUT_OBJECT.S
index a9a99ea..03dcb08 100644
--- a/vm/mterp/x86/OP_IPUT_OBJECT.S
+++ b/vm/mterp/x86/OP_IPUT_OBJECT.S
@@ -58,7 +58,7 @@
     FETCH_INST_OPCODE 2 %edx
     je      1f                                  # skip card mark if null store
     shrl    $$GC_CARD_SHIFT,%ecx                # object head to card number
-    movb    %al,(%eax,%ecx)                     # mark card
+    movb    %al,(%eax,%ecx)                     # mark card using object head
 1:
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
diff --git a/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S b/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S
index 8e8c47d..7fa99a8 100644
--- a/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S
+++ b/vm/mterp/x86/OP_IPUT_OBJECT_QUICK.S
@@ -21,7 +21,7 @@
     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
+    movb      %al,(%eax,%ecx)               # mark card based on object head
 1:
     ADVANCE_PC 2
     GOTO_NEXT_R %edx
diff --git a/vm/mterp/x86/OP_SPUT_OBJECT.S b/vm/mterp/x86/OP_SPUT_OBJECT.S
index f9e0be1..f198cce 100644
--- a/vm/mterp/x86/OP_SPUT_OBJECT.S
+++ b/vm/mterp/x86/OP_SPUT_OBJECT.S
@@ -13,7 +13,7 @@
     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
+.L${opcode}_finish:                              # field ptr in eax
     movzbl    rINSTbl,%ecx                       # ecx<- AA
     GET_VREG_R  %ecx %ecx
     jmp       .L${opcode}_continue
@@ -21,11 +21,13 @@
 
 
 .L${opcode}_continue:
-    movl      %ecx,offStaticField_value(%eax)
-    testl     %ecx,%ecx
+    movl      %ecx,offStaticField_value(%eax)    # do the store
+    testl     %ecx,%ecx                          # stored null object ptr?
     movl      rGLUE,%ecx
     FETCH_INST_OPCODE 2 %edx
-    je        1f
+    movl      offGlue_method(%ecx),%eax          # eax<- current method
+    je        1f                                 # skip card mark if null
+    movl      offMethod_clazz(%eax),%eax         # eax<- method->clazz
     movl      offGlue_cardTable(%ecx),%ecx       # get card table base
     shrl      $$GC_CARD_SHIFT,%eax               # head to card number
     movb      %cl,(%ecx,%eax)                    # mark card