Interpreter & JIT support for write barriers
In this iteration, cards are marked on either the store address or
the object head (whichever leads to faster code). In all cases,
though, card marks are deferred until after the associated store
has completed.
Change-Id: I633d6e8c3bebdb80bde92efb4fa6fc7cc84f60fc
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 03fc2af..d69991d 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -24,6 +24,25 @@
* applicable directory below this one.
*/
+/*
+ * Mark garbage collection card. Skip if the value we're storing is null.
+ */
+static void markCard(CompilationUnit *cUnit, int valReg, int tgtAddrReg)
+{
+ int regCardBase = dvmCompilerAllocTemp(cUnit);
+ int regCardNo = dvmCompilerAllocTemp(cUnit);
+ opRegImm(cUnit, kOpCmp, valReg, 0); /* storing null? */
+ ArmLIR *branchOver = opCondBranch(cUnit, kArmCondEq);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState, cardTable),
+ regCardBase);
+ opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
+ storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
+ kUnsignedByte);
+ ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *)target;
+}
+
static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
int srcSize, int tgtSize)
{
@@ -306,7 +325,7 @@
*
*/
static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
- int fieldOffset)
+ int fieldOffset, bool isObject)
{
RegisterClass regClass = dvmCompilerRegClassBySize(size);
RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
@@ -319,6 +338,10 @@
HEAP_ACCESS_SHADOW(true);
storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
HEAP_ACCESS_SHADOW(false);
+ if (isObject) {
+ /* NOTE: marking card based on object head */
+ markCard(cUnit, rlSrc.lowReg, rlObj.lowReg);
+ }
}
@@ -528,12 +551,14 @@
dvmCompilerLockTemp(cUnit, regPtr); // r4PC
dvmCompilerLockTemp(cUnit, regIndex); // r7
dvmCompilerLockTemp(cUnit, r0);
+ dvmCompilerLockTemp(cUnit, r1);
/* Bad? - roll back and re-execute if so */
genRegImmCheck(cUnit, kArmCondEq, r0, 0, mir->offset, pcrLabel);
- /* Resume here - must reload element, regPtr & index preserved */
+ /* Resume here - must reload element & array, regPtr & index preserved */
loadValueDirectFixed(cUnit, rlSrc, r0);
+ loadValueDirectFixed(cUnit, rlArray, r1);
ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
target->defMask = ENCODE_ALL;
@@ -543,6 +568,9 @@
storeBaseIndexed(cUnit, regPtr, regIndex, r0,
scale, kWord);
HEAP_ACCESS_SHADOW(false);
+
+ /* NOTE: marking card here based on object head */
+ markCard(cUnit, r0, r1);
}
static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
@@ -1488,6 +1516,10 @@
HEAP_ACCESS_SHADOW(true);
storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
HEAP_ACCESS_SHADOW(false);
+ if (mir->dalvikInsn.opCode == OP_SPUT_OBJECT) {
+ /* NOTE: marking card based on field address */
+ markCard(cUnit, rlSrc.lowReg, tReg);
+ }
break;
}
@@ -2218,16 +2250,18 @@
genIPutWide(cUnit, mir, fieldOffset);
break;
case OP_IPUT:
+ genIPut(cUnit, mir, kWord, fieldOffset, false);
+ break;
case OP_IPUT_OBJECT:
- genIPut(cUnit, mir, kWord, fieldOffset);
+ genIPut(cUnit, mir, kWord, fieldOffset, true);
break;
case OP_IPUT_SHORT:
case OP_IPUT_CHAR:
- genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
+ genIPut(cUnit, mir, kUnsignedHalf, fieldOffset, false);
break;
case OP_IPUT_BYTE:
case OP_IPUT_BOOLEAN:
- genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
+ genIPut(cUnit, mir, kUnsignedByte, fieldOffset, false);
break;
case OP_IGET_WIDE_VOLATILE:
case OP_IPUT_WIDE_VOLATILE:
@@ -2251,8 +2285,10 @@
genIGet(cUnit, mir, kWord, fieldOffset);
break;
case OP_IPUT_QUICK:
+ genIPut(cUnit, mir, kWord, fieldOffset, false);
+ break;
case OP_IPUT_OBJECT_QUICK:
- genIPut(cUnit, mir, kWord, fieldOffset);
+ genIPut(cUnit, mir, kWord, fieldOffset, true);
break;
case OP_IGET_WIDE_QUICK:
genIGetWide(cUnit, mir, fieldOffset);
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index c794db2..6ba9e12 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -128,6 +128,8 @@
const u1* interpStackEnd;
/* points at self->suspendCount */
volatile int* pSelfSuspendCount;
+ /* Biased base of GC's card table */
+ u1* cardTable;
#if defined(WITH_DEBUGGER)
/* points at gDvm.debuggerActive, or NULL if debugger not enabled */
volatile u1* pDebuggerActive;
@@ -151,8 +153,8 @@
*/
unsigned char* pJitProfTable;
JitState jitState;
- const void* jitResumeNPC; // Native PC of compiled code
- const u2* jitResumeDPC; // Dalvik PC corresponding to NPC
+ const void* jitResumeNPC; // Native PC of compiled code
+ const u2* jitResumeDPC; // Dalvik PC corresponding to NPC
int jitThreshold;
/*
* ppJitProfTable holds the address of gDvmJit.pJitProfTable, which
diff --git a/vm/mterp/Mterp.c b/vm/mterp/Mterp.c
index 51cef04..4b0ceb8 100644
--- a/vm/mterp/Mterp.c
+++ b/vm/mterp/Mterp.c
@@ -76,6 +76,7 @@
glue->interpStackEnd = self->interpStackEnd;
glue->pSelfSuspendCount = &self->suspendCount;
+ glue->cardTable = gDvm.biasedCardTableBase;
#if defined(WITH_JIT)
glue->pJitProfTable = gDvmJit.pProfTable;
glue->ppJitProfTable = &gDvmJit.pProfTable;
diff --git a/vm/mterp/armv5te/OP_APUT_OBJECT.S b/vm/mterp/armv5te/OP_APUT_OBJECT.S
index 03477f5..e926db6 100644
--- a/vm/mterp/armv5te/OP_APUT_OBJECT.S
+++ b/vm/mterp/armv5te/OP_APUT_OBJECT.S
@@ -36,6 +36,13 @@
bl dvmCanPutArrayElement @ test object type vs. array type
cmp r0, #0 @ okay?
beq common_errArrayStore @ no
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.L${opcode}_skip_check:
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
GET_INST_OPCODE(ip) @ extract opcode from rINST
diff --git a/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S b/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S
index 1241c13..b9abe5a 100644
--- a/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S
+++ b/vm/mterp/armv5te/OP_FILLED_NEW_ARRAY.S
@@ -33,15 +33,15 @@
.L${opcode}_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if $isrange
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .L${opcode}_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -49,7 +49,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -81,8 +82,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
diff --git a/vm/mterp/armv5te/OP_IPUT.S b/vm/mterp/armv5te/OP_IPUT.S
index 78d333d..53f4b4e 100644
--- a/vm/mterp/armv5te/OP_IPUT.S
+++ b/vm/mterp/armv5te/OP_IPUT.S
@@ -7,7 +7,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
diff --git a/vm/mterp/armv5te/OP_IPUT_OBJECT.S b/vm/mterp/armv5te/OP_IPUT_OBJECT.S
index 7a4d936..5e0fe83 100644
--- a/vm/mterp/armv5te/OP_IPUT_OBJECT.S
+++ b/vm/mterp/armv5te/OP_IPUT_OBJECT.S
@@ -1,2 +1,51 @@
+%default { "barrier":"@ no-op ", "sqnum":"0" }
%verify "executed"
-%include "armv5te/OP_IPUT.S"
+%verify "null object"
+%verify "field already resolved"
+%verify "field not yet resolved"
+%verify "field cannot be resolved"
+ /*
+ * 32-bit instance field put.
+ *
+ * for: iput-object, iput-object-volatile
+ */
+ /* op vA, vB, field@CCCC */
+ mov r0, rINST, lsr #12 @ r0<- B
+ ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
+ FETCH(r1, 1) @ r1<- field ref CCCC
+ ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+ GET_VREG(r9, r0) @ r9<- fp[B], the object pointer
+ ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr
+ cmp r0, #0 @ is resolved entry null?
+ bne .L${opcode}_finish @ no, already resolved
+8: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
+ EXPORT_PC() @ resolve() could throw
+ ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
+ bl dvmResolveInstField @ r0<- resolved InstField ptr
+ cmp r0, #0 @ success?
+ bne .L${opcode}_finish @ yes, finish up
+ b common_exceptionThrown
+%break
+
+ /*
+ * Currently:
+ * r0 holds resolved field
+ * r9 holds object
+ */
+.L${opcode}_finish:
+ @bl common_squeak${sqnum}
+ mov r1, rINST, lsr #8 @ r1<- A+
+ ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
+ and r1, r1, #15 @ r1<- A
+ cmp r9, #0 @ check object for null
+ GET_VREG(r0, r1) @ r0<- fp[A]
+ 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
+ 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 6838faf..648a69c 100644
--- a/vm/mterp/armv5te/OP_IPUT_OBJECT_QUICK.S
+++ b/vm/mterp/armv5te/OP_IPUT_OBJECT_QUICK.S
@@ -1,2 +1,19 @@
%verify "executed"
-%include "armv5te/OP_IPUT_QUICK.S"
+%verify "null object"
+ /* For: iput-object-quick */
+ /* op vA, vB, offset@CCCC */
+ mov r2, rINST, lsr #12 @ r2<- B
+ GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
+ FETCH(r1, 1) @ r1<- field byte offset
+ cmp r3, #0 @ check object for null
+ mov r2, rINST, lsr #8 @ r2<- A(+)
+ beq common_errNullObject @ object was null
+ and r2, r2, #15
+ GET_VREG(r0, r2) @ r0<- fp[A]
+ ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
+ 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
+ GET_INST_OPCODE(ip) @ extract opcode from rINST
+ GOTO_OPCODE(ip) @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S b/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S
index ba3f615..b4d24e7 100644
--- a/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S
@@ -1,2 +1,2 @@
%verify "executed"
-%include "armv5te/OP_IPUT.S" {"barrier":"SMP_DMB"}
+%include "armv5te/OP_IPUT_OBJECT.S" {"barrier":"SMP_DMB"}
diff --git a/vm/mterp/armv5te/OP_IPUT_QUICK.S b/vm/mterp/armv5te/OP_IPUT_QUICK.S
index c15da2b..ad76eca 100644
--- a/vm/mterp/armv5te/OP_IPUT_QUICK.S
+++ b/vm/mterp/armv5te/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 */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
diff --git a/vm/mterp/armv5te/OP_SPUT.S b/vm/mterp/armv5te/OP_SPUT.S
index c9919ba..e709b22 100644
--- a/vm/mterp/armv5te/OP_SPUT.S
+++ b/vm/mterp/armv5te/OP_SPUT.S
@@ -6,7 +6,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
diff --git a/vm/mterp/armv5te/OP_SPUT_OBJECT.S b/vm/mterp/armv5te/OP_SPUT_OBJECT.S
index 1048982..54a04fc 100644
--- a/vm/mterp/armv5te/OP_SPUT_OBJECT.S
+++ b/vm/mterp/armv5te/OP_SPUT_OBJECT.S
@@ -1,2 +1,38 @@
+%default { "barrier":"@ no-op " }
%verify "executed"
-%include "armv5te/OP_SPUT.S"
+%verify "field already resolved"
+%verify "field not yet resolved"
+%verify "field cannot be resolved"
+ /*
+ * 32-bit SPUT handler for objects
+ *
+ * for: sput-object, sput-object-volatile
+ */
+ /* op vAA, field@BBBB */
+ ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ FETCH(r1, 1) @ r1<- field ref BBBB
+ 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?
+ 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
+ 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
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S b/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S
index cfb2b27..fe12b9e 100644
--- a/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S
@@ -1,2 +1,2 @@
%verify "executed"
-%include "armv5te/OP_SPUT.S" {"barrier":"SMP_DMB"}
+%include "armv5te/OP_SPUT_OBJECT.S" {"barrier":"SMP_DMB"}
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index dde675e..bcff8f0 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -97,8 +97,33 @@
MTERP_OFFSET(offGlue_bailPtr, MterpGlue, bailPtr, 28)
MTERP_OFFSET(offGlue_interpStackEnd, MterpGlue, interpStackEnd, 32)
MTERP_OFFSET(offGlue_pSelfSuspendCount, MterpGlue, pSelfSuspendCount, 36)
+MTERP_OFFSET(offGlue_cardTable, MterpGlue, cardTable, 40)
#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
-MTERP_OFFSET(offGlue_pDebuggerActive, MterpGlue, pDebuggerActive, 40)
+MTERP_OFFSET(offGlue_pDebuggerActive, MterpGlue, pDebuggerActive, 44)
+MTERP_OFFSET(offGlue_pActiveProfilers, MterpGlue, pActiveProfilers, 48)
+MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 52)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable, MterpGlue, pJitProfTable, 60)
+MTERP_OFFSET(offGlue_jitState, MterpGlue, jitState, 64)
+MTERP_OFFSET(offGlue_jitResumeNPC, MterpGlue, jitResumeNPC, 68)
+MTERP_OFFSET(offGlue_jitResumeDPC, MterpGlue, jitResumeDPC, 72)
+MTERP_OFFSET(offGlue_jitThreshold, MterpGlue, jitThreshold, 76)
+MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 80)
+MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 84)
+#endif
+#elif defined(WITH_DEBUGGER)
+MTERP_OFFSET(offGlue_pDebuggerActive, MterpGlue, pDebuggerActive, 44)
+MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 48)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable, MterpGlue, pJitProfTable, 56)
+MTERP_OFFSET(offGlue_jitState, MterpGlue, jitState, 60)
+MTERP_OFFSET(offGlue_jitResumeNPC, MterpGlue, jitResumeNPC, 64)
+MTERP_OFFSET(offGlue_jitResumeDPC, MterpGlue, jitResumeDPC, 68)
+MTERP_OFFSET(offGlue_jitThreshold, MterpGlue, jitThreshold, 72)
+MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 76)
+MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 80)
+#endif
+#elif defined(WITH_PROFILER)
MTERP_OFFSET(offGlue_pActiveProfilers, MterpGlue, pActiveProfilers, 44)
MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 48)
#if defined(WITH_JIT)
@@ -110,40 +135,16 @@
MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 76)
MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 80)
#endif
-#elif defined(WITH_DEBUGGER)
-MTERP_OFFSET(offGlue_pDebuggerActive, MterpGlue, pDebuggerActive, 40)
-MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 44)
-#if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitProfTable, MterpGlue, pJitProfTable, 52)
-MTERP_OFFSET(offGlue_jitState, MterpGlue, jitState, 56)
-MTERP_OFFSET(offGlue_jitResumeNPC, MterpGlue, jitResumeNPC, 60)
-MTERP_OFFSET(offGlue_jitResumeDPC, MterpGlue, jitResumeDPC, 64)
-MTERP_OFFSET(offGlue_jitThreshold, MterpGlue, jitThreshold, 68)
-MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 72)
-MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 76)
-#endif
-#elif defined(WITH_PROFILER)
-MTERP_OFFSET(offGlue_pActiveProfilers, MterpGlue, pActiveProfilers, 40)
-MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 44)
-#if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitProfTable, MterpGlue, pJitProfTable, 52)
-MTERP_OFFSET(offGlue_jitState, MterpGlue, jitState, 56)
-MTERP_OFFSET(offGlue_jitResumeNPC, MterpGlue, jitResumeNPC, 60)
-MTERP_OFFSET(offGlue_jitResumeDPC, MterpGlue, jitResumeDPC, 64)
-MTERP_OFFSET(offGlue_jitThreshold, MterpGlue, jitThreshold, 68)
-MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 72)
-MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 76)
-#endif
#else
-MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 40)
+MTERP_OFFSET(offGlue_entryPoint, MterpGlue, entryPoint, 44)
#if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitProfTable, MterpGlue, pJitProfTable, 48)
-MTERP_OFFSET(offGlue_jitState, MterpGlue, jitState, 52)
-MTERP_OFFSET(offGlue_jitResumeNPC, MterpGlue, jitResumeNPC, 56)
-MTERP_OFFSET(offGlue_jitResumeDPC, MterpGlue, jitResumeDPC, 60)
-MTERP_OFFSET(offGlue_jitThreshold, MterpGlue, jitThreshold, 64)
-MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 68)
-MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 72)
+MTERP_OFFSET(offGlue_pJitProfTable, MterpGlue, pJitProfTable, 52)
+MTERP_OFFSET(offGlue_jitState, MterpGlue, jitState, 56)
+MTERP_OFFSET(offGlue_jitResumeNPC, MterpGlue, jitResumeNPC, 60)
+MTERP_OFFSET(offGlue_jitResumeDPC, MterpGlue, jitResumeDPC, 64)
+MTERP_OFFSET(offGlue_jitThreshold, MterpGlue, jitThreshold, 68)
+MTERP_OFFSET(offGlue_ppJitProfTable, MterpGlue, ppJitProfTable, 72)
+MTERP_OFFSET(offGlue_icRechainCount, MterpGlue, icRechainCount, 76)
#endif
#endif
/* make sure all JValue union members are stored at the same offset */
@@ -342,5 +343,8 @@
/* flags for dvmMalloc */
MTERP_CONSTANT(ALLOC_DONT_TRACK, 0x01)
+/* for GC */
+MTERP_CONSTANT(GC_CARD_SHIFT, 7)
+
/* opcode number */
MTERP_CONSTANT(OP_MOVE_EXCEPTION, 0x0d)
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 2e7dcc6..d82272f 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -2612,7 +2612,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2656,11 +2656,10 @@
.balign 64
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: armv5te/OP_IPUT_OBJECT.S */
-/* File: armv5te/OP_IPUT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2679,7 +2678,6 @@
bne .LOP_IPUT_OBJECT_finish @ yes, finish up
b common_exceptionThrown
-
/* ------------------------------ */
.balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
@@ -2689,7 +2687,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2718,7 +2716,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2747,7 +2745,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2776,7 +2774,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2991,7 +2989,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3041,11 +3039,10 @@
.balign 64
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: armv5te/OP_SPUT_OBJECT.S */
-/* File: armv5te/OP_SPUT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3053,15 +3050,14 @@
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?
- beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- @ no-op @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
/* ------------------------------ */
@@ -3072,7 +3068,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3099,7 +3095,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3126,7 +3122,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3153,7 +3149,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7455,7 +7451,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7510,7 +7506,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7833,7 +7829,7 @@
.balign 64
.L_OP_IPUT_QUICK: /* 0xf5 */
/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7872,8 +7868,7 @@
.balign 64
.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
-/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-object-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7883,12 +7878,14 @@
beq common_errNullObject @ object was null
and r2, r2, #15
GET_VREG(r0, r2) @ r0<- fp[A]
+ ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
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
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
@@ -8001,11 +7998,11 @@
.balign 64
.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_IPUT.S */
+/* File: armv5te/OP_IPUT_OBJECT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -8056,11 +8053,11 @@
.balign 64
.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_SPUT.S */
+/* File: armv5te/OP_SPUT_OBJECT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -8068,15 +8065,15 @@
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?
- beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- SMP_DMB @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
/* ------------------------------ */
@@ -8352,15 +8349,15 @@
.LOP_FILLED_NEW_ARRAY_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 0
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8368,7 +8365,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8400,8 +8398,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8430,15 +8433,15 @@
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 1
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8446,7 +8449,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8478,8 +8482,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8711,6 +8720,13 @@
bl dvmCanPutArrayElement @ test object type vs. array type
cmp r0, #0 @ okay?
beq common_errArrayStore @ no
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.LOP_APUT_OBJECT_skip_check:
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
GET_INST_OPCODE(ip) @ extract opcode from rINST
@@ -8929,11 +8945,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_IPUT_BOOLEAN */
@@ -9162,19 +9182,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
/* continuation for OP_SPUT_BOOLEAN */
@@ -9769,11 +9788,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_SGET_OBJECT_VOLATILE */
@@ -9792,19 +9815,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT_VOLATILE */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_VOLATILE_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.size dvmAsmSisterStart, .-dvmAsmSisterStart
.global dvmAsmSisterEnd
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 2e86a7f..633a32d 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -2592,7 +2592,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2636,11 +2636,10 @@
.balign 64
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: armv5te/OP_IPUT_OBJECT.S */
-/* File: armv5te/OP_IPUT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2659,7 +2658,6 @@
bne .LOP_IPUT_OBJECT_finish @ yes, finish up
b common_exceptionThrown
-
/* ------------------------------ */
.balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
@@ -2669,7 +2667,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2698,7 +2696,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2727,7 +2725,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2756,7 +2754,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2971,7 +2969,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3021,11 +3019,10 @@
.balign 64
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: armv5te/OP_SPUT_OBJECT.S */
-/* File: armv5te/OP_SPUT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3033,15 +3030,14 @@
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?
- beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- @ no-op @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
/* ------------------------------ */
@@ -3052,7 +3048,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3079,7 +3075,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3106,7 +3102,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3133,7 +3129,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7135,7 +7131,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7190,7 +7186,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7512,7 +7508,7 @@
.balign 64
.L_OP_IPUT_QUICK: /* 0xf5 */
/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7550,8 +7546,7 @@
.balign 64
.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
-/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-object-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7561,12 +7556,14 @@
beq common_errNullObject @ object was null
and r2, r2, #15
GET_VREG(r0, r2) @ r0<- fp[A]
+ ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
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
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
@@ -7679,11 +7676,11 @@
.balign 64
.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_IPUT.S */
+/* File: armv5te/OP_IPUT_OBJECT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7734,11 +7731,11 @@
.balign 64
.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_SPUT.S */
+/* File: armv5te/OP_SPUT_OBJECT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7746,15 +7743,15 @@
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?
- beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- SMP_DMB @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
/* ------------------------------ */
@@ -8030,15 +8027,15 @@
.LOP_FILLED_NEW_ARRAY_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 0
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8046,7 +8043,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8078,8 +8076,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8108,15 +8111,15 @@
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 1
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8124,7 +8127,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8156,8 +8160,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8251,6 +8260,13 @@
bl dvmCanPutArrayElement @ test object type vs. array type
cmp r0, #0 @ okay?
beq common_errArrayStore @ no
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.LOP_APUT_OBJECT_skip_check:
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
GET_INST_OPCODE(ip) @ extract opcode from rINST
@@ -8468,11 +8484,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_IPUT_BOOLEAN */
@@ -8701,19 +8721,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
/* continuation for OP_SPUT_BOOLEAN */
@@ -9307,11 +9326,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_SGET_OBJECT_VOLATILE */
@@ -9330,19 +9353,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT_VOLATILE */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_VOLATILE_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.size dvmAsmSisterStart, .-dvmAsmSisterStart
.global dvmAsmSisterEnd
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index feb908c..66f3a3d 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -2614,7 +2614,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2658,11 +2658,10 @@
.balign 64
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: armv5te/OP_IPUT_OBJECT.S */
-/* File: armv5te/OP_IPUT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2681,7 +2680,6 @@
bne .LOP_IPUT_OBJECT_finish @ yes, finish up
b common_exceptionThrown
-
/* ------------------------------ */
.balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
@@ -2691,7 +2689,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2720,7 +2718,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2749,7 +2747,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2778,7 +2776,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2993,7 +2991,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3043,11 +3041,10 @@
.balign 64
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: armv5te/OP_SPUT_OBJECT.S */
-/* File: armv5te/OP_SPUT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3055,15 +3052,14 @@
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?
- beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- @ no-op @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
/* ------------------------------ */
@@ -3074,7 +3070,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3101,7 +3097,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3128,7 +3124,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3155,7 +3151,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7457,7 +7453,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7512,7 +7508,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7834,7 +7830,7 @@
.balign 64
.L_OP_IPUT_QUICK: /* 0xf5 */
/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7872,8 +7868,7 @@
.balign 64
.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
-/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-object-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7883,12 +7878,14 @@
beq common_errNullObject @ object was null
and r2, r2, #15
GET_VREG(r0, r2) @ r0<- fp[A]
+ ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
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
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
@@ -8001,11 +7998,11 @@
.balign 64
.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_IPUT.S */
+/* File: armv5te/OP_IPUT_OBJECT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -8056,11 +8053,11 @@
.balign 64
.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_SPUT.S */
+/* File: armv5te/OP_SPUT_OBJECT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -8068,15 +8065,15 @@
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?
- beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- SMP_DMB @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
/* ------------------------------ */
@@ -8352,15 +8349,15 @@
.LOP_FILLED_NEW_ARRAY_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 0
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8368,7 +8365,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8400,8 +8398,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8430,15 +8433,15 @@
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 1
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8446,7 +8449,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8478,8 +8482,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8709,6 +8718,13 @@
bl dvmCanPutArrayElement @ test object type vs. array type
cmp r0, #0 @ okay?
beq common_errArrayStore @ no
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.LOP_APUT_OBJECT_skip_check:
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
GET_INST_OPCODE(ip) @ extract opcode from rINST
@@ -8926,11 +8942,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_IPUT_BOOLEAN */
@@ -9159,19 +9179,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
/* continuation for OP_SPUT_BOOLEAN */
@@ -9765,11 +9784,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_SGET_OBJECT_VOLATILE */
@@ -9788,19 +9811,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT_VOLATILE */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_VOLATILE_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.size dvmAsmSisterStart, .-dvmAsmSisterStart
.global dvmAsmSisterEnd
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index f573a40..e837dda 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -2636,11 +2636,10 @@
.balign 64
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: armv5te/OP_IPUT_OBJECT.S */
-/* File: armv5te/OP_IPUT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2659,7 +2658,6 @@
bne .LOP_IPUT_OBJECT_finish @ yes, finish up
b common_exceptionThrown
-
/* ------------------------------ */
.balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
@@ -2669,7 +2667,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2698,7 +2696,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2727,7 +2725,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2756,7 +2754,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2971,7 +2969,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3021,11 +3019,10 @@
.balign 64
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: armv5te/OP_SPUT_OBJECT.S */
-/* File: armv5te/OP_SPUT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3033,15 +3030,14 @@
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?
- beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- @ no-op @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
/* ------------------------------ */
@@ -3052,7 +3048,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3079,7 +3075,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3106,7 +3102,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3133,7 +3129,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7089,7 +7085,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7144,7 +7140,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7500,8 +7496,7 @@
.balign 64
.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
-/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-object-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7511,12 +7506,14 @@
beq common_errNullObject @ object was null
and r2, r2, #15
GET_VREG(r0, r2) @ r0<- fp[A]
+ ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
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
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
@@ -7629,11 +7626,11 @@
.balign 64
.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_IPUT.S */
+/* File: armv5te/OP_IPUT_OBJECT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7684,11 +7681,11 @@
.balign 64
.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_SPUT.S */
+/* File: armv5te/OP_SPUT_OBJECT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7696,15 +7693,15 @@
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?
- beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- SMP_DMB @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
/* ------------------------------ */
@@ -7980,15 +7977,15 @@
.LOP_FILLED_NEW_ARRAY_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 0
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -7996,7 +7993,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8028,8 +8026,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8058,15 +8061,15 @@
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 1
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8074,7 +8077,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8106,8 +8110,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8201,6 +8210,13 @@
bl dvmCanPutArrayElement @ test object type vs. array type
cmp r0, #0 @ okay?
beq common_errArrayStore @ no
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.LOP_APUT_OBJECT_skip_check:
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
GET_INST_OPCODE(ip) @ extract opcode from rINST
@@ -8402,11 +8418,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_IPUT_BOOLEAN */
@@ -8635,19 +8655,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
/* continuation for OP_SPUT_BOOLEAN */
@@ -9241,11 +9260,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_SGET_OBJECT_VOLATILE */
@@ -9264,19 +9287,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT_VOLATILE */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_VOLATILE_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.size dvmAsmSisterStart, .-dvmAsmSisterStart
.global dvmAsmSisterEnd
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 32484e2..dc33638 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -2636,11 +2636,10 @@
.balign 64
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: armv5te/OP_IPUT_OBJECT.S */
-/* File: armv5te/OP_IPUT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2659,7 +2658,6 @@
bne .LOP_IPUT_OBJECT_finish @ yes, finish up
b common_exceptionThrown
-
/* ------------------------------ */
.balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
@@ -2669,7 +2667,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2698,7 +2696,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2727,7 +2725,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2756,7 +2754,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -2971,7 +2969,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3021,11 +3019,10 @@
.balign 64
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: armv5te/OP_SPUT_OBJECT.S */
-/* File: armv5te/OP_SPUT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3033,15 +3030,14 @@
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?
- beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- @ no-op @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
/* ------------------------------ */
@@ -3052,7 +3048,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3079,7 +3075,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3106,7 +3102,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -3133,7 +3129,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7089,7 +7085,7 @@
/*
* General 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7144,7 +7140,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 */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7500,8 +7496,7 @@
.balign 64
.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
-/* File: armv5te/OP_IPUT_QUICK.S */
- /* For: iput-quick, iput-object-quick */
+ /* For: iput-object-quick */
/* op vA, vB, offset@CCCC */
mov r2, rINST, lsr #12 @ r2<- B
GET_VREG(r3, r2) @ r3<- fp[B], the object pointer
@@ -7511,12 +7506,14 @@
beq common_errNullObject @ object was null
and r2, r2, #15
GET_VREG(r0, r2) @ r0<- fp[A]
+ ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base
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
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-
/* ------------------------------ */
.balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
@@ -7629,11 +7626,11 @@
.balign 64
.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_IPUT.S */
+/* File: armv5te/OP_IPUT_OBJECT.S */
/*
- * General 32-bit instance field put.
+ * 32-bit instance field put.
*
- * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+ * for: iput-object, iput-object-volatile
*/
/* op vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
@@ -7684,11 +7681,11 @@
.balign 64
.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
-/* File: armv5te/OP_SPUT.S */
+/* File: armv5te/OP_SPUT_OBJECT.S */
/*
- * General 32-bit SPUT handler.
+ * 32-bit SPUT handler for objects
*
- * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+ * for: sput-object, sput-object-volatile
*/
/* op vAA, field@BBBB */
ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
@@ -7696,15 +7693,15 @@
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?
- beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
- mov r2, rINST, lsr #8 @ r2<- AA
- FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- GET_VREG(r1, r2) @ r1<- fp[AA]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- SMP_DMB @ releasing store
- str r1, [r0, #offStaticField_value] @ field<- vAA
- GOTO_OPCODE(ip) @ jump to next instruction
+ 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
+ bl dvmResolveStaticField @ r0<- resolved StaticField ptr
+ cmp r0, #0 @ success?
+ bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
/* ------------------------------ */
@@ -7980,15 +7977,15 @@
.LOP_FILLED_NEW_ARRAY_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 0
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -7996,7 +7993,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8028,8 +8026,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8058,15 +8061,15 @@
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags
- ldrb r3, [r3, #1] @ r3<- descriptor[1]
+ ldrb rINST, [r3, #1] @ rINST<- descriptor[1]
.if 1
mov r1, r10 @ r1<- AA (length)
.else
mov r1, r10, lsr #4 @ r1<- B (length)
.endif
- cmp r3, #'I' @ array of ints?
- cmpne r3, #'L' @ array of objects?
- cmpne r3, #'[' @ array of arrays?
+ cmp rINST, #'I' @ array of ints?
+ cmpne rINST, #'L' @ array of objects?
+ cmpne rINST, #'[' @ array of arrays?
mov r9, r1 @ save length in r9
bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet
bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags)
@@ -8074,7 +8077,8 @@
beq common_exceptionThrown @ alloc failed, handle exception
FETCH(r1, 2) @ r1<- FEDC or CCCC
- str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array
+ str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
add r0, r0, #offArrayObject_contents @ r0<- newArray->contents
subs r9, r9, #1 @ length--, check for neg
FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST
@@ -8106,8 +8110,13 @@
.endif
2:
- GET_INST_OPCODE(ip) @ ip<- opcode from rINST
- GOTO_OPCODE(ip) @ execute it
+ ldr r0, [rGLUE, #offGlue_retval] @ r0<- object
+ ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type
+ 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
+ GOTO_OPCODE(ip) @ execute it
/*
* Throw an exception indicating that we have not implemented this
@@ -8201,6 +8210,13 @@
bl dvmCanPutArrayElement @ test object type vs. array type
cmp r0, #0 @ okay?
beq common_errArrayStore @ no
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.LOP_APUT_OBJECT_skip_check:
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
GET_INST_OPCODE(ip) @ extract opcode from rINST
@@ -8402,11 +8418,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_IPUT_BOOLEAN */
@@ -8635,19 +8655,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
/* continuation for OP_SPUT_BOOLEAN */
@@ -9241,11 +9260,15 @@
and r1, r1, #15 @ r1<- A
cmp r9, #0 @ check object for null
GET_VREG(r0, r1) @ r0<- fp[A]
+ 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, r3] @ obj.field (8/16/32 bits)<- r0
+ str r0, [r9] @ obj.field (8/16/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
/* continuation for OP_SGET_OBJECT_VOLATILE */
@@ -9264,19 +9287,18 @@
b common_exceptionThrown @ no, handle exception
/* continuation for OP_SPUT_OBJECT_VOLATILE */
-
- /*
- * Continuation if the field has not yet been resolved.
- * r1: BBBB field ref
- */
-.LOP_SPUT_OBJECT_VOLATILE_resolve:
- ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
- EXPORT_PC() @ resolve() could throw, so export now
- ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
- bl dvmResolveStaticField @ r0<- resolved StaticField ptr
- cmp r0, #0 @ success?
- bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish
- b common_exceptionThrown @ no, handle exception
+.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0
+ 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
+ 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
+ GOTO_OPCODE(ip) @ jump to next instruction
.size dvmAsmSisterStart, .-dvmAsmSisterStart
.global dvmAsmSisterEnd
diff --git a/vm/mterp/x86-atom/TODO.txt b/vm/mterp/x86-atom/TODO.txt
index 5b89db9..abeee31 100644
--- a/vm/mterp/x86-atom/TODO.txt
+++ b/vm/mterp/x86-atom/TODO.txt
@@ -1,5 +1,6 @@
Items requiring attention:
+(hi) Add gc card marking to aput/iput/sput/new_filled_array
(hi) Correct stack overflow handling (dvmCleanupStackOverflow takes an
additional argument now)
(hi) "debugger active" test in common_periodicChecks must handle