summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-07-08 20:01:12 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-07-08 20:01:12 +0000
commit3f5ad1a98e211216be9612a60ca30644e0f4073d (patch)
tree82a73f2dc557fd6cbca90e076ba2c7072c4832f6 /compiler-rt/lib
parent7a88ec9ac05c4f9e4cc03bd9e84af9e6da73c8b9 (diff)
downloadbcm5719-llvm-3f5ad1a98e211216be9612a60ca30644e0f4073d.tar.gz
bcm5719-llvm-3f5ad1a98e211216be9612a60ca30644e0f4073d.zip
tsan: allow memory overlap in __tsan_java_move
JVM actually moves memory between overlapping ranges. llvm-svn: 212560
Diffstat (limited to 'compiler-rt/lib')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interface_java.cc12
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interface_java.h2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_sync.cc15
3 files changed, 23 insertions, 6 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc
index e63b93f4139..5dfb476dd2e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc
@@ -126,7 +126,8 @@ void __tsan_java_move(jptr src, jptr dst, jptr size) {
CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
CHECK_GE(dst, jctx->heap_begin);
CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
- CHECK(dst >= src + size || src >= dst + size);
+ CHECK_NE(dst, src);
+ CHECK_NE(size, 0);
// Assuming it's not running concurrently with threads that do
// memory accesses and mutex operations (stop-the-world phase).
@@ -136,7 +137,14 @@ void __tsan_java_move(jptr src, jptr dst, jptr size) {
u64 *s = (u64*)MemToShadow(src);
u64 *d = (u64*)MemToShadow(dst);
u64 *send = (u64*)MemToShadow(src + size);
- for (; s != send; s++, d++) {
+ uptr inc = 1;
+ if (dst > src) {
+ s = (u64*)MemToShadow(src + size) - 1;
+ d = (u64*)MemToShadow(dst + size) - 1;
+ send = (u64*)MemToShadow(src) - 1;
+ inc = -1;
+ }
+ for (; s != send; s += inc, d += inc) {
*d = *s;
*s = 0;
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_java.h b/compiler-rt/lib/tsan/rtl/tsan_interface_java.h
index 6a838851e43..1f793df712d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_java.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_java.h
@@ -50,7 +50,7 @@ void __tsan_java_alloc(jptr ptr, jptr size) INTERFACE_ATTRIBUTE;
void __tsan_java_free(jptr ptr, jptr size) INTERFACE_ATTRIBUTE;
// Callback for memory move by GC.
// Can be aggregated for several objects (preferably).
-// The ranges must not overlap.
+// The ranges can overlap.
void __tsan_java_move(jptr src, jptr dst, jptr size) INTERFACE_ATTRIBUTE;
// This function must be called on the finalizer thread
// before executing a batch of finalizers.
diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
index 3462b04c21a..15392c9578b 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_sync.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
@@ -180,13 +180,22 @@ SyncVar* MetaMap::GetAndLock(ThreadState *thr, uptr pc,
}
void MetaMap::MoveMemory(uptr src, uptr dst, uptr sz) {
- // Here we assume that src and dst do not overlap,
- // and there are no concurrent accesses to the regions (e.g. stop-the-world).
+ // src and dst can overlap,
+ // there are no concurrent accesses to the regions (e.g. stop-the-world).
+ CHECK_NE(src, dst);
+ CHECK_NE(sz, 0);
uptr diff = dst - src;
u32 *src_meta = MemToMeta(src);
u32 *dst_meta = MemToMeta(dst);
u32 *src_meta_end = MemToMeta(src + sz);
- for (; src_meta != src_meta_end; src_meta++, dst_meta++) {
+ uptr inc = 1;
+ if (dst > src) {
+ src_meta = MemToMeta(src + sz) - 1;
+ dst_meta = MemToMeta(dst + sz) - 1;
+ src_meta_end = MemToMeta(src) - 1;
+ inc = -1;
+ }
+ for (; src_meta != src_meta_end; src_meta += inc, dst_meta += inc) {
CHECK_EQ(*dst_meta, 0);
u32 idx = *src_meta;
*src_meta = 0;
OpenPOWER on IntegriCloud