Bug 1529933 - Execute a fence before mprotect. r=luke
authorLars T Hansen <lhansen@mozilla.com>
Thu, 14 Mar 2019 17:22:50 +0100
changeset 522071 7b9be2d40a83d028ef43b3ad88c16a616c4e178b
parent 522070 adbb2fb5c8eca65f1df0ca77b20933c9aae54ae7
child 522073 8ae5bb51b14199227e03a37b0bdd3b35f1f4d01e
child 522098 cc090db10bec9cc215fc448c309c21c16895a1db
push id10871
push usercbrindusan@mozilla.com
push dateMon, 18 Mar 2019 15:49:32 +0000
treeherdermozilla-beta@018abdd16060 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1529933
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1529933 - Execute a fence before mprotect. r=luke Differential Revision: https://phabricator.services.mozilla.com/D23527
js/src/jit/ProcessExecutableMemory.cpp
--- a/js/src/jit/ProcessExecutableMemory.cpp
+++ b/js/src/jit/ProcessExecutableMemory.cpp
@@ -18,16 +18,17 @@
 #include "jsfriendapi.h"
 #include "jsmath.h"
 #include "jsutil.h"
 
 #include "gc/Memory.h"
 #ifdef JS_CODEGEN_ARM64
 #  include "jit/arm64/vixl/Cpu-vixl.h"
 #endif
+#include "jit/AtomicOperations.h"
 #include "threading/LockGuard.h"
 #include "threading/Mutex.h"
 #include "util/Windows.h"
 #include "vm/MutexIDs.h"
 
 #ifdef XP_WIN
 #  include "mozilla/StackWalk_windows.h"
 #  include "mozilla/WindowsVersion.h"
@@ -720,16 +721,29 @@ bool js::jit::ReprotectRegion(void* star
   // Round size up
   size += (pageSize - 1);
   size &= ~(pageSize - 1);
 
   MOZ_ASSERT((uintptr_t(pageStart) % pageSize) == 0);
 
   execMemory.assertValidAddress(pageStart, size);
 
+  // On weak memory systems, make sure new code is visible on all cores before
+  // addresses of the code are made public.  Now is the latest moment in time
+  // when we can do that, and we're assuming that every other thread that has
+  // written into the memory that is being reprotected here has synchronized
+  // with this thread in such a way that the memory writes have become visible
+  // and we therefore only need to execute the fence once here.  See bug 1529933
+  // for a longer discussion of why this is both necessary and sufficient.
+  //
+  // We use the C++ fence here -- and not AtomicOperations::fenceSeqCst() --
+  // primarily because ReprotectRegion will be called while we construct our own
+  // jitted atomics.  But the C++ fence is sufficient and correct, too.
+  std::atomic_thread_fence(std::memory_order_seq_cst);
+
 #ifdef XP_WIN
   DWORD oldProtect;
   DWORD flags = ProtectionSettingToFlags(protection);
   if (!VirtualProtect(pageStart, size, flags, &oldProtect)) {
     return false;
   }
 #else
   unsigned flags = ProtectionSettingToFlags(protection);