diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-07-08 20:01:12 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-07-08 20:01:12 +0000 |
commit | 75e8a9117af00bc1ffe2a64c1a4232554fc506f4 (patch) | |
tree | 2dca1af5fb87230fbd7e2c5d6577f5aa186904a6 /lib/tsan/rtl/tsan_sync.cc | |
parent | 54e0edaf51707800948263a1a929cfc64f6df285 (diff) |
tsan: allow memory overlap in __tsan_java_move
JVM actually moves memory between overlapping ranges.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@212560 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/rtl/tsan_sync.cc')
-rw-r--r-- | lib/tsan/rtl/tsan_sync.cc | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/lib/tsan/rtl/tsan_sync.cc b/lib/tsan/rtl/tsan_sync.cc index 3462b04c2..15392c957 100644 --- a/lib/tsan/rtl/tsan_sync.cc +++ b/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; |