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/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;