Make wide-volatile loads and stores atomic.
This implements the four wide-volatile instructions added in a previous
change, and modifies the verifier to substitute the opcodes into the
instruction stream when appropriate.
For mterp, the ARM wide get/put instructions now have conditional code
that replaces ldrd/strd with a call to the quasiatomic functions. The
C version does essentially the same thing. ARMv4T lacks ldrd/stdrd, and
uses separate implementations for the wide field accesses, so those were
updated as well. x86 will just use stubs.
The JIT should punt these to the interpreter.
Change-Id: Ife88559ed1a698c3267d43c454896f6b12081c0f
Also:
- We don't seem to be using the negative widths in the instruction
table. Not sure they're useful anymore.
- Tabs -> spaces in x86-atom throw-verification-error impl.
diff --git a/docs/verifier.html b/docs/verifier.html
index 022923b..21bbdf0 100644
--- a/docs/verifier.html
+++ b/docs/verifier.html
@@ -45,6 +45,10 @@
it's very helpful to start with the assumption that the bytecode
is valid.
</ol>
+<p>
+It's also a convenient framework to deal with certain situations, notably
+replacement of instructions that access volatile 64-bit fields with
+more rigorous versions that guarantee atomicity.
<h2>Verifier Differences</h2>
diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.c
index 05faf23..8961ce5 100644
--- a/libdex/InstrUtils.c
+++ b/libdex/InstrUtils.c
@@ -35,6 +35,9 @@
*
* (To save space in the binary we could generate a static table with a
* command-line utility.)
+ *
+ * TODO: it doesn't look like we're using the negative values anymore.
+ * Consider switching to only positive values.
*/
InstructionWidth* dexCreateInstrWidthTable(void)
{
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
index 8449ae5..0c4e162 100644
--- a/libdex/InstrUtils.h
+++ b/libdex/InstrUtils.h
@@ -111,6 +111,7 @@
*/
InstructionWidth* dexCreateInstrWidthTable(void);
+#if 0 // no longer used
/*
* Returns the width of the specified instruction, or 0 if not defined.
* Optimized instructions use negative values.
@@ -120,6 +121,7 @@
// assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
return widths[opCode];
}
+#endif
/*
* Return the width of the specified instruction, or 0 if not defined.
@@ -128,7 +130,7 @@
{
//assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
- int val = dexGetInstrWidth(widths, opCode);
+ int val = widths[opCode];
if (val < 0)
val = -val;
/* XXX - the no-compare trick may be a cycle slower on ARM */
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 7ef559b..8187354 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -2921,6 +2921,10 @@
* Replace an instruction with "throw-verification-error". This allows us to
* defer error reporting until the code path is first used.
*
+ * This is expected to be called during "just in time" verification, not
+ * from within dexopt. (Verification failures in dexopt will result in
+ * postponement of verification to first use of the class.)
+ *
* The throw-verification-error instruction requires two code units. Some
* of the replaced instructions require three; the third code unit will
* receive a "nop". The instruction's length will be left unchanged
@@ -2942,8 +2946,6 @@
u2 oldInsn = *oldInsns;
bool result = false;
- //dvmMakeCodeReadWrite(meth);
-
//LOGD(" was 0x%04x\n", oldInsn);
u2* newInsns = (u2*) meth->insns + insnIdx;
@@ -3040,10 +3042,53 @@
result = true;
bail:
- //dvmMakeCodeReadOnly(meth);
return result;
}
+/*
+ * Replace {iget,iput,sget,sput}-wide with the -wide-volatile form.
+ *
+ * If this is called during dexopt, we can modify the instruction in
+ * place. If this happens during just-in-time verification, we need to
+ * use the DEX read/write page feature.
+ *
+ * NOTE:
+ * This shouldn't really be tied to verification. It ought to be a
+ * separate pass that is run before or after the verifier. However, that
+ * requires a bunch of extra code, and the only advantage of doing so is
+ * that the feature isn't disabled when verification is turned off. At
+ * some point we may need to revisit this choice.
+ */
+static void replaceVolatileInstruction(Method* meth, InsnFlags* insnFlags,
+ int insnIdx)
+{
+ u2* oldInsns = (u2*)meth->insns + insnIdx;
+ u2 oldInsn = *oldInsns;
+ u2 newVal;
+
+ switch (oldInsn & 0xff) {
+ case OP_IGET_WIDE: newVal = OP_IGET_WIDE_VOLATILE; break;
+ case OP_IPUT_WIDE: newVal = OP_IPUT_WIDE_VOLATILE; break;
+ case OP_SGET_WIDE: newVal = OP_SGET_WIDE_VOLATILE; break;
+ case OP_SPUT_WIDE: newVal = OP_SPUT_WIDE_VOLATILE; break;
+ default:
+ LOGE("wide-volatile op mismatch (0x%x)\n", oldInsn);
+ dvmAbort();
+ return; // in-lieu-of noreturn attribute
+ }
+
+ /* merge new opcode into 16-bit code unit */
+ newVal |= (oldInsn & 0xff00);
+
+ if (gDvm.optimizing) {
+ /* dexopt time, alter the output */
+ *oldInsns = newVal;
+ } else {
+ /* runtime, make the page read/write */
+ dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns, newVal);
+ }
+}
+
/*
* ===========================================================================
@@ -4472,6 +4517,7 @@
}
break;
case OP_IGET_WIDE:
+ case OP_IGET_WIDE_VOLATILE:
{
RegType dstType;
ClassObject* fieldClass;
@@ -4506,6 +4552,13 @@
setRegisterType(workRegs, insnRegCount, decInsn.vA,
dstType, &failure);
}
+ if (VERIFY_OK(failure)) {
+ if (decInsn.opCode != OP_IGET_WIDE_VOLATILE &&
+ dvmIsVolatileField(&instField->field))
+ {
+ replaceVolatileInstruction(meth, insnFlags, insnIdx);
+ }
+ }
}
break;
case OP_IGET_OBJECT:
@@ -4602,6 +4655,7 @@
}
break;
case OP_IPUT_WIDE:
+ case OP_IPUT_WIDE_VOLATILE:
tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
if (VERIFY_OK(failure)) {
RegType typeHi =
@@ -4639,6 +4693,13 @@
failure = VERIFY_ERROR_GENERIC;
break;
}
+ if (VERIFY_OK(failure)) {
+ if (decInsn.opCode != OP_IPUT_WIDE_VOLATILE &&
+ dvmIsVolatileField(&instField->field))
+ {
+ replaceVolatileInstruction(meth, insnFlags, insnIdx);
+ }
+ }
}
break;
case OP_IPUT_OBJECT:
@@ -4748,6 +4809,7 @@
}
break;
case OP_SGET_WIDE:
+ case OP_SGET_WIDE_VOLATILE:
{
StaticField* staticField;
RegType dstType;
@@ -4775,6 +4837,13 @@
setRegisterType(workRegs, insnRegCount, decInsn.vA,
dstType, &failure);
}
+ if (VERIFY_OK(failure)) {
+ if (decInsn.opCode != OP_SGET_WIDE_VOLATILE &&
+ dvmIsVolatileField(&staticField->field))
+ {
+ replaceVolatileInstruction(meth, insnFlags, insnIdx);
+ }
+ }
}
break;
case OP_SGET_OBJECT:
@@ -4864,6 +4933,7 @@
}
break;
case OP_SPUT_WIDE:
+ case OP_SPUT_WIDE_VOLATILE:
tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
if (VERIFY_OK(failure)) {
RegType typeHi =
@@ -4894,6 +4964,13 @@
failure = VERIFY_ERROR_GENERIC;
break;
}
+ if (VERIFY_OK(failure)) {
+ if (decInsn.opCode != OP_SPUT_WIDE_VOLATILE &&
+ dvmIsVolatileField(&staticField->field))
+ {
+ replaceVolatileInstruction(meth, insnFlags, insnIdx);
+ }
+ }
}
break;
case OP_SPUT_OBJECT:
@@ -5420,10 +5497,6 @@
case OP_IPUT_QUICK:
case OP_IPUT_WIDE_QUICK:
case OP_IPUT_OBJECT_QUICK:
- case OP_IGET_WIDE_VOLATILE:
- case OP_IPUT_WIDE_VOLATILE:
- case OP_SGET_WIDE_VOLATILE:
- case OP_SPUT_WIDE_VOLATILE:
case OP_INVOKE_VIRTUAL_QUICK:
case OP_INVOKE_VIRTUAL_QUICK_RANGE:
case OP_INVOKE_SUPER_QUICK:
diff --git a/vm/analysis/DexOptimize.c b/vm/analysis/DexOptimize.c
index a5b8b6f..ae1edfc 100644
--- a/vm/analysis/DexOptimize.c
+++ b/vm/analysis/DexOptimize.c
@@ -1667,7 +1667,7 @@
u4 len = insns[2] | (((u4)insns[3]) << 16);
width = 4 + (elemWidth * len + 1) / 2;
} else {
- width = dexGetInstrWidth(gDvm.instrWidth, inst);
+ width = dexGetInstrWidthAbs(gDvm.instrWidth, inst);
}
assert(width > 0);
diff --git a/vm/mterp/armv4t/OP_IGET_WIDE.S b/vm/mterp/armv4t/OP_IGET_WIDE.S
index 576b43d..dabaeba 100644
--- a/vm/mterp/armv4t/OP_IGET_WIDE.S
+++ b/vm/mterp/armv4t/OP_IGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "null object"
%verify "field already resolved"
@@ -33,11 +34,16 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if $volatile
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
add r9, r9, r3 @ r9<- obj + field offset
ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
diff --git a/vm/mterp/armv4t/OP_IGET_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_IGET_WIDE_VOLATILE.S
new file mode 100644
index 0000000..cdd8708
--- /dev/null
+++ b/vm/mterp/armv4t/OP_IGET_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_IGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv4t/OP_IPUT_WIDE.S b/vm/mterp/armv4t/OP_IPUT_WIDE.S
index c4b43b3..d824d9d 100644
--- a/vm/mterp/armv4t/OP_IPUT_WIDE.S
+++ b/vm/mterp/armv4t/OP_IPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "null object"
%verify "field already resolved"
@@ -35,8 +36,12 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- add r9, r9, r3 @ r9<- object + byte offset
- stmia r9, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ add r2, r9, r3 @ r2<- object + byte offset
+ .if $volatile
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
diff --git a/vm/mterp/armv4t/OP_IPUT_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_IPUT_WIDE_VOLATILE.S
new file mode 100644
index 0000000..6b297f0
--- /dev/null
+++ b/vm/mterp/armv4t/OP_IPUT_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_IPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv4t/OP_SGET_WIDE.S b/vm/mterp/armv4t/OP_SGET_WIDE.S
index 61a7a43..2556a7c 100644
--- a/vm/mterp/armv4t/OP_SGET_WIDE.S
+++ b/vm/mterp/armv4t/OP_SGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "field already resolved"
%verify "field not yet resolved"
@@ -13,12 +14,16 @@
cmp r0, #0 @ is resolved entry null?
beq .L${opcode}_resolve @ yes, do resolve
.L${opcode}_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- add r0, r0, #offStaticField_value
- ldmia r0, {r2-r3} @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ .if $volatile
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldmia r0, {r0-r1} @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
%break
@@ -26,6 +31,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.L${opcode}_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
diff --git a/vm/mterp/armv4t/OP_SGET_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_SGET_WIDE_VOLATILE.S
new file mode 100644
index 0000000..5615ab6
--- /dev/null
+++ b/vm/mterp/armv4t/OP_SGET_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_SGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv4t/OP_SPUT_WIDE.S b/vm/mterp/armv4t/OP_SPUT_WIDE.S
index b90cf50..237233c 100644
--- a/vm/mterp/armv4t/OP_SPUT_WIDE.S
+++ b/vm/mterp/armv4t/OP_SPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "field already resolved"
%verify "field not yet resolved"
@@ -6,27 +7,33 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .L${opcode}_resolve @ yes, do resolve
-.L${opcode}_finish: @ field ptr in r0, AA in r9
+.L${opcode}_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- add r0, r0, #offStaticField_value
- stmia r0, {r2-r3} @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ .if $volatile
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ stmia r2, {r0-r1} @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
%break
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.L${opcode}_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -34,6 +41,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .L${opcode}_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
diff --git a/vm/mterp/armv4t/OP_SPUT_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_SPUT_WIDE_VOLATILE.S
new file mode 100644
index 0000000..850e83b
--- /dev/null
+++ b/vm/mterp/armv4t/OP_SPUT_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_SPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_IGET_WIDE.S b/vm/mterp/armv5te/OP_IGET_WIDE.S
index 22377d9..6d3eb45 100644
--- a/vm/mterp/armv5te/OP_IGET_WIDE.S
+++ b/vm/mterp/armv5te/OP_IGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "null object"
%verify "field already resolved"
@@ -33,10 +34,15 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if $volatile
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
diff --git a/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S
index f7d5254..face363 100644
--- a/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
%verify "executed"
-%include "armv5te/OP_IGET_WIDE.S"
+%include "armv5te/OP_IGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_IPUT_WIDE.S b/vm/mterp/armv5te/OP_IPUT_WIDE.S
index 75465ec..763c6a8 100644
--- a/vm/mterp/armv5te/OP_IPUT_WIDE.S
+++ b/vm/mterp/armv5te/OP_IPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "null object"
%verify "field already resolved"
@@ -35,7 +36,12 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if $volatile
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S
index 2de16c8..944811b 100644
--- a/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
%verify "executed"
-%include "armv5te/OP_IPUT_WIDE.S"
+%include "armv5te/OP_IPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_SGET_WIDE.S b/vm/mterp/armv5te/OP_SGET_WIDE.S
index 1f93a2f..ff0238c 100644
--- a/vm/mterp/armv5te/OP_SGET_WIDE.S
+++ b/vm/mterp/armv5te/OP_SGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "field already resolved"
%verify "field not yet resolved"
@@ -13,11 +14,16 @@
cmp r0, #0 @ is resolved entry null?
beq .L${opcode}_resolve @ yes, do resolve
.L${opcode}_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if $volatile
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
%break
@@ -25,6 +31,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.L${opcode}_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
diff --git a/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S
index 964c8b1..b852348 100644
--- a/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
%verify "executed"
-%include "armv5te/OP_SGET_WIDE.S"
+%include "armv5te/OP_SGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_SPUT_WIDE.S b/vm/mterp/armv5te/OP_SPUT_WIDE.S
index a7bc5f2..69b106c 100644
--- a/vm/mterp/armv5te/OP_SPUT_WIDE.S
+++ b/vm/mterp/armv5te/OP_SPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
%verify "executed"
%verify "field already resolved"
%verify "field not yet resolved"
@@ -6,26 +7,33 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .L${opcode}_resolve @ yes, do resolve
-.L${opcode}_finish: @ field ptr in r0, AA in r9
+.L${opcode}_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if $volatile
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
%break
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.L${opcode}_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -33,6 +41,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .L${opcode}_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
diff --git a/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S
index 7c618f1..a88de85 100644
--- a/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
%verify "executed"
-%include "armv5te/OP_SPUT_WIDE.S"
+%include "armv5te/OP_SPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c b/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
index 954c2d7..a080823 100644
--- a/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
diff --git a/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c b/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
index a0c015b..d888b4a 100644
--- a/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
diff --git a/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c b/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
index b7812fa..26a67bf 100644
--- a/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
diff --git a/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c b/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
index 684099c..bdf552c 100644
--- a/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
diff --git a/vm/mterp/config-armv4t b/vm/mterp/config-armv4t
index 01eddb2..9746376 100644
--- a/vm/mterp/config-armv4t
+++ b/vm/mterp/config-armv4t
@@ -50,6 +50,10 @@
op OP_IPUT_WIDE_QUICK armv4t
op OP_SGET_WIDE armv4t
op OP_SPUT_WIDE armv4t
+ op OP_IGET_WIDE_VOLATILE armv4t
+ op OP_IPUT_WIDE_VOLATILE armv4t
+ op OP_SGET_WIDE_VOLATILE armv4t
+ op OP_SPUT_WIDE_VOLATILE armv4t
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 6068de5..302e9c8 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -2888,12 +2888,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_resolve @ yes, do resolve
.LOP_SGET_WIDE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- add r0, r0, #offStaticField_value
- ldmia r0, {r2-r3} @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ .if 0
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldmia r0, {r0-r1} @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -3059,21 +3063,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- add r0, r0, #offStaticField_value
- stmia r0, {r2-r3} @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ .if 0
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ stmia r2, {r0-r1} @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
.balign 64
@@ -7591,8 +7599,8 @@
/* ------------------------------ */
.balign 64
.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
-/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
-/* File: armv5te/OP_IGET_WIDE.S */
+/* File: armv4t/OP_IGET_WIDE_VOLATILE.S */
+/* File: armv4t/OP_IGET_WIDE.S */
/*
* Wide 32-bit instance field get.
*/
@@ -7617,8 +7625,8 @@
/* ------------------------------ */
.balign 64
.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
-/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
-/* File: armv5te/OP_IPUT_WIDE.S */
+/* File: armv4t/OP_IPUT_WIDE_VOLATILE.S */
+/* File: armv4t/OP_IPUT_WIDE.S */
/* iput-wide vA, vB, field@CCCC */
mov r0, rINST, lsr #12 @ r0<- B
ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex
@@ -7640,8 +7648,8 @@
/* ------------------------------ */
.balign 64
.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
-/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
-/* File: armv5te/OP_SGET_WIDE.S */
+/* File: armv4t/OP_SGET_WIDE_VOLATILE.S */
+/* File: armv4t/OP_SGET_WIDE.S */
/*
* 64-bit SGET handler.
*/
@@ -7653,11 +7661,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
.LOP_SGET_WIDE_VOLATILE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ .if 1
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldmia r0, {r0-r1} @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -7665,26 +7678,31 @@
/* ------------------------------ */
.balign 64
.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
-/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
-/* File: armv5te/OP_SPUT_WIDE.S */
+/* File: armv4t/OP_SPUT_WIDE_VOLATILE.S */
+/* File: armv4t/OP_SPUT_WIDE.S */
/*
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ .if 1
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ stmia r2, {r0-r1} @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
@@ -8744,11 +8762,16 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if 0
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
add r9, r9, r3 @ r9<- obj + field offset
ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -8897,10 +8920,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- add r9, r9, r3 @ r9<- object + byte offset
- stmia r9, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ add r2, r9, r3 @ r2<- object + byte offset
+ .if 0
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_IPUT_OBJECT */
@@ -9029,6 +9056,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9142,6 +9171,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9149,6 +9180,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
@@ -9534,10 +9566,16 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
+ .if 1
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ add r9, r9, r3 @ r9<- obj + field offset
+ ldmia r9, {r0-r1} @ r0/r1<- obj.field (64-bit align ok)
+ .endif
mov r2, rINST, lsr #8 @ r2<- A+
- ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -9560,9 +9598,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ add r2, r9, r3 @ r2<- object + byte offset
+ .if 1
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ stmia r2, {r0-r1} @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9570,6 +9613,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9587,6 +9632,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9594,6 +9641,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 6ab1a37..f886355 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -2868,11 +2868,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_resolve @ yes, do resolve
.LOP_SGET_WIDE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 0
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -3038,20 +3043,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 0
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
.balign 64
@@ -7313,11 +7323,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
.LOP_SGET_WIDE_VOLATILE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 1
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -7331,20 +7346,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
@@ -8264,10 +8284,15 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if 0
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -8416,9 +8441,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 0
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_IPUT_OBJECT */
@@ -8547,6 +8577,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -8660,6 +8692,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -8667,6 +8701,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
@@ -9052,10 +9087,15 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if 1
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -9078,9 +9118,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9088,6 +9133,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9105,6 +9152,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9112,6 +9161,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 6990b44..c21aee7 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -2890,11 +2890,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_resolve @ yes, do resolve
.LOP_SGET_WIDE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 0
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -3060,20 +3065,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 0
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
.balign 64
@@ -7653,11 +7663,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
.LOP_SGET_WIDE_VOLATILE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 1
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -7671,20 +7686,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
@@ -8740,10 +8760,15 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if 0
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -8892,9 +8917,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 0
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_IPUT_OBJECT */
@@ -9023,6 +9053,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9136,6 +9168,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9143,6 +9177,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
@@ -9528,10 +9563,15 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if 1
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -9554,9 +9594,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9564,6 +9609,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9581,6 +9628,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9588,6 +9637,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index a60f78c..37316d8 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -2858,11 +2858,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_resolve @ yes, do resolve
.LOP_SGET_WIDE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 0
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -3028,20 +3033,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 0
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
.balign 64
@@ -7194,38 +7204,111 @@
/* ------------------------------ */
.balign 64
-.L_OP_UNUSED_E8: /* 0xe8 */
-/* File: armv5te/OP_UNUSED_E8.S */
-/* File: armv5te/unused.S */
- bl common_abort
-
+.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
+/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
+/* File: armv5te/OP_IGET_WIDE.S */
+ /*
+ * Wide 32-bit instance field get.
+ */
+ /* iget-wide 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<- 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 .LOP_IGET_WIDE_VOLATILE_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
+ bne .LOP_IGET_WIDE_VOLATILE_finish
+ b common_exceptionThrown
/* ------------------------------ */
.balign 64
-.L_OP_UNUSED_E9: /* 0xe9 */
-/* File: armv5te/OP_UNUSED_E9.S */
-/* File: armv5te/unused.S */
- bl common_abort
-
+.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
+/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
+/* File: armv5te/OP_IPUT_WIDE.S */
+ /* iput-wide 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<- 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 .LOP_IPUT_WIDE_VOLATILE_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 .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up
+ b common_exceptionThrown
/* ------------------------------ */
.balign 64
-.L_OP_UNUSED_EA: /* 0xea */
-/* File: armv5te/OP_UNUSED_EA.S */
-/* File: armv5te/unused.S */
- bl common_abort
-
+.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
+/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
+/* File: armv5te/OP_SGET_WIDE.S */
+ /*
+ * 64-bit SGET handler.
+ */
+ /* sget-wide 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?
+ beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
+.LOP_SGET_WIDE_VOLATILE_finish:
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 1
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
+ GET_INST_OPCODE(ip) @ extract opcode from rINST
+ GOTO_OPCODE(ip) @ jump to next instruction
/* ------------------------------ */
.balign 64
-.L_OP_UNUSED_EB: /* 0xeb */
-/* File: armv5te/OP_UNUSED_EB.S */
-/* File: armv5te/unused.S */
- bl common_abort
-
+.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
+/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
+/* File: armv5te/OP_SPUT_WIDE.S */
+ /*
+ * 64-bit SPUT handler.
+ */
+ /* sput-wide vAA, field@BBBB */
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
+ FETCH(r1, 1) @ r1<- field ref BBBB
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
+ mov r9, rINST, lsr #8 @ r9<- AA
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
+ cmp r2, #0 @ is resolved entry null?
+ beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
@@ -8420,6 +8503,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -8533,6 +8618,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -8540,6 +8627,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
@@ -8914,6 +9002,96 @@
GOTO_OPCODE(ip) @ jump to next instruction
+/* continuation for OP_IGET_WIDE_VOLATILE */
+
+ /*
+ * Currently:
+ * r0 holds resolved field
+ * r9 holds object
+ */
+.LOP_IGET_WIDE_VOLATILE_finish:
+ cmp r9, #0 @ check object for null
+ ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
+ beq common_errNullObject @ object was null
+ .if 1
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
+ add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
+ GET_INST_OPCODE(ip) @ extract opcode from rINST
+ stmia r3, {r0-r1} @ fp[A]<- r0/r1
+ GOTO_OPCODE(ip) @ jump to next instruction
+
+
+/* continuation for OP_IPUT_WIDE_VOLATILE */
+
+ /*
+ * Currently:
+ * r0 holds resolved field
+ * r9 holds object
+ */
+.LOP_IPUT_WIDE_VOLATILE_finish:
+ mov r2, rINST, lsr #8 @ r2<- A+
+ cmp r9, #0 @ check object for null
+ and r2, r2, #15 @ r2<- A
+ ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
+ add r2, rFP, r2, lsl #2 @ r3<- &fp[A]
+ beq common_errNullObject @ object was null
+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ ldmia r2, {r0-r1} @ r0/r1<- fp[A]
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
+
+
+/* continuation for OP_SGET_WIDE_VOLATILE */
+
+ /*
+ * Continuation if the field has not yet been resolved.
+ * r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
+ */
+.LOP_SGET_WIDE_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_SGET_WIDE_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
+
+/* continuation for OP_SPUT_WIDE_VOLATILE */
+
+ /*
+ * Continuation if the field has not yet been resolved.
+ * r1: BBBB field ref
+ * r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
+ */
+.LOP_SPUT_WIDE_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?
+ mov r2, r0 @ copy to r2
+ bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
+ b common_exceptionThrown @ no, handle exception
+
+
/* continuation for OP_EXECUTE_INLINE */
/*
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 2e48175..5a78a34 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -2858,11 +2858,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_resolve @ yes, do resolve
.LOP_SGET_WIDE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 0
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -3028,20 +3033,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 0
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
.balign 64
@@ -7257,11 +7267,16 @@
cmp r0, #0 @ is resolved entry null?
beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve
.LOP_SGET_WIDE_VOLATILE_finish:
- mov r1, rINST, lsr #8 @ r1<- AA
- ldrd r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
- add r1, rFP, r1, lsl #2 @ r1<- &fp[AA]
+ mov r9, rINST, lsr #8 @ r9<- AA
+ .if 1
+ add r0, r0, #offStaticField_value @ r0<- pointer to data
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
+ ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+ .endif
+ add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- stmia r1, {r2-r3} @ vAA/vAA+1<- r2/r3
+ stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
@@ -7275,20 +7290,25 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex
+ ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex
FETCH(r1, 1) @ r1<- field ref BBBB
- ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+ ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
mov r9, rINST, lsr #8 @ r9<- AA
- ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr
+ ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr
add r9, rFP, r9, lsl #2 @ r9<- &fp[AA]
- cmp r0, #0 @ is resolved entry null?
+ cmp r2, #0 @ is resolved entry null?
beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
- ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
- GOTO_OPCODE(ip) @ jump to next instruction
+ ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r2, #offStaticField_value @ r2<- pointer to data
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* ------------------------------ */
@@ -8483,6 +8503,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -8596,6 +8618,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -8603,6 +8627,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
@@ -8988,10 +9013,15 @@
cmp r9, #0 @ check object for null
ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field
beq common_errNullObject @ object was null
- mov r2, rINST, lsr #8 @ r2<- A+
+ .if 1
+ add r0, r9, r3 @ r0<- address of field
+ bl android_quasiatomic_read_64 @ r0/r1<- contents of field
+ .else
ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok)
- and r2, r2, #15 @ r2<- A
+ .endif
+ mov r2, rINST, lsr #8 @ r2<- A+
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
+ and r2, r2, #15 @ r2<- A
add r3, rFP, r2, lsl #2 @ r3<- &fp[A]
GET_INST_OPCODE(ip) @ extract opcode from rINST
stmia r3, {r0-r1} @ fp[A]<- r0/r1
@@ -9014,9 +9044,14 @@
beq common_errNullObject @ object was null
FETCH_ADVANCE_INST(2) @ advance rPC, load rINST
ldmia r2, {r0-r1} @ r0/r1<- fp[A]
- GET_INST_OPCODE(ip) @ extract opcode from rINST
- strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0
- GOTO_OPCODE(ip) @ jump to next instruction
+ GET_INST_OPCODE(r10) @ extract opcode from rINST
+ .if 1
+ add r2, r9, r3 @ r2<- target address
+ bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+ .else
+ strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1
+ .endif
+ GOTO_OPCODE(r10) @ jump to next instruction
/* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9024,6 +9059,8 @@
/*
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
+ *
+ * Returns StaticField pointer in r0.
*/
.LOP_SGET_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9041,6 +9078,8 @@
* Continuation if the field has not yet been resolved.
* r1: BBBB field ref
* r9: &fp[AA]
+ *
+ * Returns StaticField pointer in r2.
*/
.LOP_SPUT_WIDE_VOLATILE_resolve:
ldr r2, [rGLUE, #offGlue_method] @ r2<- current method
@@ -9048,6 +9087,7 @@
ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz
bl dvmResolveStaticField @ r0<- resolved StaticField ptr
cmp r0, #0 @ success?
+ mov r2, r0 @ copy to r2
bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish
b common_exceptionThrown @ no, handle exception
diff --git a/vm/mterp/out/InterpAsm-x86-atom.S b/vm/mterp/out/InterpAsm-x86-atom.S
index 860ec44..d32ff2f 100644
--- a/vm/mterp/out/InterpAsm-x86-atom.S
+++ b/vm/mterp/out/InterpAsm-x86-atom.S
@@ -14810,16 +14810,16 @@
* Syntax: op vAA, ref@BBBB
*/
- movl rGLUE, %edx # %edx<- pMterpGlue
- movl offGlue_method(%edx), %ecx # %ecx<- glue->method
- EXPORT_PC # in case an exception is thrown
- FETCH 1, %eax # %eax<- BBBB
- movl %eax, -4(%esp) # push parameter BBBB; ref
- movl rINST, -8(%esp) # push parameter AA
- movl %ecx, -12(%esp) # push parameter glue->method
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ movl offGlue_method(%edx), %ecx # %ecx<- glue->method
+ EXPORT_PC # in case an exception is thrown
+ FETCH 1, %eax # %eax<- BBBB
+ movl %eax, -4(%esp) # push parameter BBBB; ref
+ movl rINST, -8(%esp) # push parameter AA
+ movl %ecx, -12(%esp) # push parameter glue->method
lea -12(%esp), %esp
- call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
- jmp common_exceptionThrown # failed; handle exception
+ call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
+ jmp common_exceptionThrown # failed; handle exception
/* ------------------------------ */
.balign 64
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 65b0b89..6c90b34 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -2775,19 +2775,19 @@
OP_END
/* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 7bd8ad3..26c2c7b 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -3138,19 +3138,19 @@
OP_END
/* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index f8b3a75..927664e 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -2877,19 +2877,19 @@
OP_END
/* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c
index a5b9fd8..a922509 100644
--- a/vm/mterp/out/InterpC-x86-atom.c
+++ b/vm/mterp/out/InterpC-x86-atom.c
@@ -1193,19 +1193,19 @@
/* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index 97fbe01..209b450 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1193,19 +1193,19 @@
/* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
OP_END
/* File: c/OP_EXECUTE_INLINE_RANGE.c */
diff --git a/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S b/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
index 94b7ec6..52e52bf 100644
--- a/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
+++ b/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
@@ -28,13 +28,13 @@
* Syntax: op vAA, ref@BBBB
*/
- movl rGLUE, %edx # %edx<- pMterpGlue
- movl offGlue_method(%edx), %ecx # %ecx<- glue->method
- EXPORT_PC # in case an exception is thrown
- FETCH 1, %eax # %eax<- BBBB
- movl %eax, -4(%esp) # push parameter BBBB; ref
- movl rINST, -8(%esp) # push parameter AA
- movl %ecx, -12(%esp) # push parameter glue->method
+ movl rGLUE, %edx # %edx<- pMterpGlue
+ movl offGlue_method(%edx), %ecx # %ecx<- glue->method
+ EXPORT_PC # in case an exception is thrown
+ FETCH 1, %eax # %eax<- BBBB
+ movl %eax, -4(%esp) # push parameter BBBB; ref
+ movl rINST, -8(%esp) # push parameter AA
+ movl %ecx, -12(%esp) # push parameter glue->method
lea -12(%esp), %esp
- call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
- jmp common_exceptionThrown # failed; handle exception
+ call dvmThrowVerificationError # call: (const Method* method, int kind, int ref)
+ jmp common_exceptionThrown # failed; handle exception
diff --git a/vm/oo/Array.c b/vm/oo/Array.c
index 4af03a9..7edb823 100644
--- a/vm/oo/Array.c
+++ b/vm/oo/Array.c
@@ -616,9 +616,6 @@
/*
* Synthesize a primitive class.
*
- * The spec for java.lang.Class.isPrimitive describes the names to
- * be used for these classes.
- *
* Just creates the class and returns it (does not add it to the class list).
*/
static ClassObject* createPrimitiveClass(int idx)
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index be2c9f2..5ceb42c 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -21,6 +21,8 @@
#ifndef _DALVIK_OO_OBJECT
#define _DALVIK_OO_OBJECT
+#include <Atomic.h>
+
#include <stddef.h>
/* fwd decl */
@@ -713,6 +715,10 @@
INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
return ((JValue*)BYTE_OFFSET(obj, offset))->l;
}
+INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) {
+ const s8* addr = BYTE_OFFSET(obj, offset);
+ return android_quasiatomic_read_64((s8*)addr);
+}
INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
((JValue*)BYTE_OFFSET(obj, offset))->i = val;
@@ -741,6 +747,10 @@
INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) {
((JValue*)BYTE_OFFSET(obj, offset))->l = val;
}
+INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
+ s8* addr = BYTE_OFFSET(obj, offset);
+ android_quasiatomic_swap_64(val, addr);
+}
/*
* Static field access functions.
@@ -776,6 +786,10 @@
INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
return sfield->value.l;
}
+INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
+ const s8* addr = &sfield->value.j;
+ return android_quasiatomic_read_64((s8*)addr);
+}
INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
sfield->value.i = val;
@@ -804,6 +818,10 @@
INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
sfield->value.l = val;
}
+INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
+ s8* addr = &sfield->value.j;
+ android_quasiatomic_swap_64(val, addr);
+}
/*
* Helpers.
@@ -859,6 +877,9 @@
INLINE bool dvmIsFinalField(const Field* field) {
return (field->accessFlags & ACC_FINAL) != 0;
}
+INLINE bool dvmIsVolatileField(const Field* field) {
+ return (field->accessFlags & ACC_VOLATILE) != 0;
+}
INLINE bool dvmIsInterfaceClass(const ClassObject* clazz) {
return (clazz->accessFlags & ACC_INTERFACE) != 0;