Backed out 2 changesets (bug 1305360) for sm(nu) failures a=backout
authorWes Kocher <wkocher@mozilla.com>
Thu, 29 Sep 2016 13:52:09 -0700
changeset 315839 282b5fdbd98b40b96bc8568294fc500aa2f06838
parent 315838 0cc441ce2c8c394767c8f3161fad0047555dbaac
child 315840 bc3137d7d869992394745738791cadfc23a927b2
push id82289
push userkwierso@gmail.com
push dateThu, 29 Sep 2016 20:52:11 +0000
treeherdermozilla-inbound@282b5fdbd98b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1305360
milestone52.0a1
backs outa70dda2a48b40683107eacf133e4ba27cf86dba1
eab2157634632da5e39a037c5b62d7bfa6123c7e
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
Backed out 2 changesets (bug 1305360) for sm(nu) failures a=backout Backed out changeset a70dda2a48b4 (bug 1305360) Backed out changeset eab215763463 (bug 1305360)
js/src/ds/MemoryProtectionExceptionHandler.cpp
js/src/ds/MemoryProtectionExceptionHandler.h
js/src/ds/PageProtectingVector.h
js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
js/src/jit/x86-shared/BaseAssembler-x86-shared.h
js/src/moz.build
js/src/vm/Initialization.cpp
deleted file mode 100644
--- a/js/src/ds/MemoryProtectionExceptionHandler.cpp
+++ /dev/null
@@ -1,753 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ds/MemoryProtectionExceptionHandler.h"
-
-#include "mozilla/Assertions.h"
-#include "mozilla/Atomics.h"
-
-#if defined(XP_WIN)
-# include "jswin.h"
-#elif defined(XP_LINUX)
-# include <signal.h>
-# include <sys/types.h>
-# include <unistd.h>
-#elif defined(XP_DARWIN)
-# include <mach/mach.h>
-#endif
-
-#ifdef ANDROID
-# include <android/log.h>
-#endif
-
-#include "ds/SplayTree.h"
-
-#include "threading/LockGuard.h"
-#include "threading/Mutex.h"
-
-namespace js {
-
-/*
- * A class to store the addresses of the regions recognized as protected
- * by this exception handler. We use a splay tree to store these addresses.
- */
-class ProtectedRegionTree
-{
-    struct Region
-    {
-        uintptr_t first;
-        uintptr_t last;
-
-        Region(uintptr_t addr, size_t size) : first(addr),
-                                              last(addr + (size - 1)) {}
-
-        static int compare(const Region& A, const Region& B) {
-            if (A.last < B.first)
-                return -1;
-            if (A.first > B.last)
-                return 1;
-            return 0;
-        }
-    };
-
-    Mutex lock;
-    LifoAlloc alloc;
-    SplayTree<Region, Region> tree;
-
-  public:
-    ProtectedRegionTree() : alloc(4096),
-                            tree(&alloc) {}
-
-    ~ProtectedRegionTree() { MOZ_ASSERT(tree.empty()); }
-
-    void insert(uintptr_t addr, size_t size) {
-        MOZ_ASSERT(addr && size);
-        LockGuard<Mutex> guard(lock);
-        AutoEnterOOMUnsafeRegion oomUnsafe;
-        if (!tree.insert(Region(addr, size)))
-            oomUnsafe.crash("Failed to store allocation ID.");
-    }
-
-    void remove(uintptr_t addr) {
-        MOZ_ASSERT(addr);
-        LockGuard<Mutex> guard(lock);
-        tree.remove(Region(addr, 1));
-    }
-
-    bool isProtected(uintptr_t addr) {
-        if (!addr)
-            return false;
-        LockGuard<Mutex> guard(lock);
-        return tree.maybeLookup(Region(addr, 1));
-    }
-};
-
-static bool sExceptionHandlerInstalled = false;
-
-static ProtectedRegionTree sProtectedRegions;
-
-bool
-MemoryProtectionExceptionHandler::isDisabled()
-{
-    // There isn't currently any reason to disable it.
-    return false;
-}
-
-void
-MemoryProtectionExceptionHandler::addRegion(void* addr, size_t size)
-{
-    if (sExceptionHandlerInstalled)
-        sProtectedRegions.insert(uintptr_t(addr), size);
-}
-
-void
-MemoryProtectionExceptionHandler::removeRegion(void* addr)
-{
-    if (sExceptionHandlerInstalled)
-        sProtectedRegions.remove(uintptr_t(addr));
-}
-
-/* -------------------------------------------------------------------------- */
-
-/*
- * This helper function attempts to replicate the functionality of
- * mozilla::MOZ_ReportCrash() in an async-signal-safe way.
- */
-static MOZ_COLD MOZ_ALWAYS_INLINE void
-ReportCrashIfDebug(const char* aStr)
-    MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
-{
-#ifdef DEBUG
-# if defined(XP_WIN)
-    DWORD bytesWritten;
-    BOOL ret = WriteFile(GetStdHandle(STD_ERROR_HANDLE), aStr,
-                         strlen(aStr) + 1, &bytesWritten, nullptr);
-    ::__debugbreak();
-# elif defined(ANDROID)
-    int ret = __android_log_write(ANDROID_LOG_FATAL, "MOZ_CRASH", aStr);
-# else
-    ssize_t ret = write(STDERR_FILENO, aStr, strlen(aStr) + 1);
-# endif
-    (void)ret; // Ignore failures; we're already crashing anyway.
-#endif
-}
-
-/* -------------------------------------------------------------------------- */
-
-#if defined(XP_WIN)
-
-static void* sVectoredExceptionHandler = nullptr;
-
-/*
- * We can only handle one exception. To guard against races and reentrancy,
- * we set this value the first time we enter the exception handler and never
- * touch it again.
- */
-static mozilla::Atomic<bool> sHandlingException(false);
-
-static long __stdcall
-VectoredExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
-{
-    EXCEPTION_RECORD* ExceptionRecord = ExceptionInfo->ExceptionRecord;
-
-    // We only handle one kind of exception; ignore all others.
-    if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
-        // Make absolutely sure we can only get here once.
-        if (sHandlingException.compareExchange(false, true)) {
-            // Restore the previous handler. We're going to forward to it
-            // anyway, and if we crash while doing so we don't want to hang.
-            MOZ_ALWAYS_TRUE(RemoveVectoredExceptionHandler(sVectoredExceptionHandler));
-
-            // Get the address that the offending code tried to access.
-            uintptr_t address = uintptr_t(ExceptionRecord->ExceptionInformation[1]);
-
-            // If the faulting address is in one of our protected regions, we
-            // want to annotate the crash to make it stand out from the crowd.
-            if (sProtectedRegions.isProtected(address)) {
-                ReportCrashIfDebug("Hit MOZ_CRASH(Tried to access a protected region!)\n");
-                MOZ_CRASH_ANNOTATE("Tried to access a protected region!");
-            }
-        }
-    }
-
-    // Forward to the previous handler which may be a debugger,
-    // the crash reporter or something else entirely.
-    return EXCEPTION_CONTINUE_SEARCH;
-}
-
-bool
-MemoryProtectionExceptionHandler::install()
-{
-    MOZ_ASSERT(!sExceptionHandlerInstalled);
-
-    // If the exception handler is disabled, report success anyway.
-    if (MemoryProtectionExceptionHandler::isDisabled())
-        return true;
-
-    // Install our new exception handler.
-    sVectoredExceptionHandler = AddVectoredExceptionHandler(/* FirstHandler = */ true,
-                                                            VectoredExceptionHandler);
-
-    sExceptionHandlerInstalled = sVectoredExceptionHandler != nullptr;
-    return sExceptionHandlerInstalled;
-}
-
-void
-MemoryProtectionExceptionHandler::uninstall()
-{
-    if (sExceptionHandlerInstalled) {
-        MOZ_ASSERT(!sHandlingException);
-
-        // Restore the previous exception handler.
-        MOZ_ALWAYS_TRUE(RemoveVectoredExceptionHandler(sVectoredExceptionHandler));
-
-        sExceptionHandlerInstalled = false;
-    }
-}
-
-#elif defined(XP_LINUX)
-
-static struct sigaction sPrevSEGVHandler = {};
-
-/*
- * We can only handle one exception. To guard against races and reentrancy,
- * we set this value the first time we enter the exception handler and never
- * touch it again.
- */
-static mozilla::Atomic<bool> sHandlingException(false);
-
-static void
-UnixExceptionHandler(int signum, siginfo_t* info, void* context)
-{
-    // Make absolutely sure we can only get here once.
-    if (sHandlingException.compareExchange(false, true)) {
-        // Restore the previous handler. We're going to forward to it
-        // anyway, and if we crash while doing so we don't want to hang.
-        MOZ_ALWAYS_FALSE(sigaction(SIGSEGV, &sPrevSEGVHandler, nullptr));
-
-        MOZ_ASSERT(signum == SIGSEGV && info->si_signo == SIGSEGV);
-
-        if (info->si_code == SEGV_ACCERR) {
-            // Get the address that the offending code tried to access.
-            uintptr_t address = uintptr_t(info->si_addr);
-
-            // If the faulting address is in one of our protected regions, we
-            // want to annotate the crash to make it stand out from the crowd.
-            if (sProtectedRegions.isProtected(address)) {
-                ReportCrashIfDebug("Hit MOZ_CRASH(Tried to access a protected region!)\n");
-                MOZ_CRASH_ANNOTATE("Tried to access a protected region!");
-            }
-        }
-    }
-
-    // Forward to the previous handler which may be a debugger,
-    // the crash reporter or something else entirely.
-    if (sPrevSEGVHandler.sa_flags & SA_SIGINFO)
-        sPrevSEGVHandler.sa_sigaction(signum, info, context);
-    else if (sPrevSEGVHandler.sa_handler == SIG_DFL || sPrevSEGVHandler.sa_handler == SIG_IGN)
-        raise(signum);
-    else
-        sPrevSEGVHandler.sa_handler(signum);
-}
-
-bool
-MemoryProtectionExceptionHandler::install()
-{
-    MOZ_ASSERT(!sExceptionHandlerInstalled);
-
-    // If the exception handler is disabled, report success anyway.
-    if (MemoryProtectionExceptionHandler::isDisabled())
-        return true;
-
-    // Install our new exception handler and save the previous one.
-    struct sigaction faultHandler = {};
-    faultHandler.sa_flags = SA_SIGINFO;
-    faultHandler.sa_sigaction = UnixExceptionHandler;
-    sigemptyset(&faultHandler.sa_mask);
-    sExceptionHandlerInstalled = !sigaction(SIGSEGV, &faultHandler, &sPrevSEGVHandler);
-
-    return sExceptionHandlerInstalled;
-}
-
-void
-MemoryProtectionExceptionHandler::uninstall()
-{
-    if (sExceptionHandlerInstalled) {
-        MOZ_ASSERT(!sHandlingException);
-
-        // Restore the previous exception handler.
-        MOZ_ALWAYS_FALSE(sigaction(SIGSEGV, &sPrevSEGVHandler, nullptr));
-
-        sExceptionHandlerInstalled = false;
-    }
-}
-
-#elif defined(XP_DARWIN)
-
-/*
- * The fact that we need to be able to forward to other exception handlers
- * makes this code much more complicated. The forwarding logic and the
- * structures required to make it work are heavily based on the code at
- * www.ravenbrook.com/project/mps/prototype/2013-06-24/machtest/machtest/main.c
- */
-
-/* -------------------------------------------------------------------------- */
-/*                Begin Mach definitions and helper functions                 */
-/* -------------------------------------------------------------------------- */
-
-/*
- * These are the message IDs associated with each exception type.
- * We'll be using sIDRequest64, but we need the others for forwarding.
- */
-static const mach_msg_id_t sIDRequest32 = 2401;
-static const mach_msg_id_t sIDRequestState32 = 2402;
-static const mach_msg_id_t sIDRequestStateIdentity32 = 2403;
-
-static const mach_msg_id_t sIDRequest64 = 2405;
-static const mach_msg_id_t sIDRequestState64 = 2406;
-static const mach_msg_id_t sIDRequestStateIdentity64 = 2407;
-
-/*
- * Each message ID has an associated Mach message structure.
- * We use the preprocessor to make defining them a little less arduous.
- */
-# define REQUEST_HEADER_FIELDS\
-    mach_msg_header_t header;
-
-# define REQUEST_IDENTITY_FIELDS\
-    mach_msg_body_t msgh_body;\
-    mach_msg_port_descriptor_t thread;\
-    mach_msg_port_descriptor_t task;
-
-# define REQUEST_GENERAL_FIELDS(bits)\
-    NDR_record_t NDR;\
-    exception_type_t exception;\
-    mach_msg_type_number_t code_count;\
-    int##bits##_t code[2];
-
-# define REQUEST_STATE_FIELDS\
-    int flavor;\
-    mach_msg_type_number_t old_state_count;\
-    natural_t old_state[THREAD_STATE_MAX];
-
-# define REQUEST_TRAILER_FIELDS\
-    mach_msg_trailer_t trailer;
-
-# define EXCEPTION_REQUEST(bits)\
-    struct ExceptionRequest##bits\
-    {\
-        REQUEST_HEADER_FIELDS\
-        REQUEST_IDENTITY_FIELDS\
-        REQUEST_GENERAL_FIELDS(bits)\
-        REQUEST_TRAILER_FIELDS\
-    };\
-
-# define EXCEPTION_REQUEST_STATE(bits)\
-    struct ExceptionRequestState##bits\
-    {\
-        REQUEST_HEADER_FIELDS\
-        REQUEST_GENERAL_FIELDS(bits)\
-        REQUEST_STATE_FIELDS\
-        REQUEST_TRAILER_FIELDS\
-    };\
-
-# define EXCEPTION_REQUEST_STATE_IDENTITY(bits)\
-    struct ExceptionRequestStateIdentity##bits\
-    {\
-        REQUEST_HEADER_FIELDS\
-        REQUEST_IDENTITY_FIELDS\
-        REQUEST_GENERAL_FIELDS(bits)\
-        REQUEST_STATE_FIELDS\
-        REQUEST_TRAILER_FIELDS\
-    };\
-
-/* This is needed because not all fields are naturally aligned on 64-bit. */
-# ifdef  __MigPackStructs
-#  pragma pack(4)
-# endif
-
-EXCEPTION_REQUEST(32)
-EXCEPTION_REQUEST(64)
-EXCEPTION_REQUEST_STATE(32)
-EXCEPTION_REQUEST_STATE(64)
-EXCEPTION_REQUEST_STATE_IDENTITY(32)
-EXCEPTION_REQUEST_STATE_IDENTITY(64)
-
-/* We use this as a common base when forwarding to the previous handler. */
-union ExceptionRequestUnion {
-    mach_msg_header_t header;
-    ExceptionRequest32 r32;
-    ExceptionRequest64 r64;
-    ExceptionRequestState32 rs32;
-    ExceptionRequestState64 rs64;
-    ExceptionRequestStateIdentity32 rsi32;
-    ExceptionRequestStateIdentity64 rsi64;
-};
-
-/* This isn't really a full Mach message, but it's all we need to send. */
-struct ExceptionReply
-{
-    mach_msg_header_t header;
-    NDR_record_t NDR;
-    kern_return_t RetCode;
-};
-
-# ifdef  __MigPackStructs
-#  pragma pack()
-# endif
-
-# undef EXCEPTION_REQUEST_STATE_IDENTITY
-# undef EXCEPTION_REQUEST_STATE
-# undef EXCEPTION_REQUEST
-# undef REQUEST_STATE_FIELDS
-# undef REQUEST_GENERAL_FIELDS
-# undef REQUEST_IDENTITY_FIELDS
-# undef REQUEST_HEADER_FIELDS
-
-/*
- * The exception handler we're forwarding to may not have the same behavior
- * or thread state flavor as what we're using. These macros help populate
- * the fields of the message we're about to send to the previous handler.
- */
-# define COPY_REQUEST_COMMON(bits, id)\
-    dst.header = src.header;\
-    dst.header.msgh_id = id;\
-    dst.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(dst) - sizeof(dst.trailer));\
-    dst.NDR = src.NDR;\
-    dst.exception = src.exception;\
-    dst.code_count = src.code_count;\
-    dst.code[0] = int##bits##_t(src.code[0]);\
-    dst.code[1] = int##bits##_t(src.code[1]);
-
-# define COPY_REQUEST_IDENTITY\
-    dst.msgh_body = src.msgh_body;\
-    dst.thread = src.thread;\
-    dst.task = src.task;
-
-# define COPY_REQUEST_STATE(flavor, stateCount, state)\
-    mach_msg_size_t stateSize = stateCount * sizeof(natural_t);\
-    dst.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(dst) - sizeof(dst.trailer) -\
-                                                        sizeof(dst.old_state) + stateSize);\
-    dst.flavor = flavor;\
-    dst.old_state_count = stateCount;\
-    memcpy(dst.old_state, state, stateSize);
-
-# define COPY_EXCEPTION_REQUEST(bits)\
-    static void\
-    CopyExceptionRequest##bits(ExceptionRequest64& src,\
-                               ExceptionRequest##bits& dst)\
-    {\
-        COPY_REQUEST_COMMON(bits, sIDRequest##bits)\
-        COPY_REQUEST_IDENTITY\
-    }
-
-# define COPY_EXCEPTION_REQUEST_STATE(bits)\
-    static void\
-    CopyExceptionRequestState##bits(ExceptionRequest64& src,\
-                                    ExceptionRequestState##bits& dst,\
-                                    thread_state_flavor_t flavor,\
-                                    mach_msg_type_number_t stateCount,\
-                                    thread_state_t state)\
-    {\
-        COPY_REQUEST_COMMON(bits, sIDRequestState##bits)\
-        COPY_REQUEST_STATE(flavor, stateCount, state)\
-    }
-
-# define COPY_EXCEPTION_REQUEST_STATE_IDENTITY(bits)\
-    static void\
-    CopyExceptionRequestStateIdentity##bits(ExceptionRequest64& src,\
-                                            ExceptionRequestStateIdentity##bits& dst,\
-                                            thread_state_flavor_t flavor,\
-                                            mach_msg_type_number_t stateCount,\
-                                            thread_state_t state)\
-    {\
-        COPY_REQUEST_COMMON(bits, sIDRequestStateIdentity##bits)\
-        COPY_REQUEST_IDENTITY\
-        COPY_REQUEST_STATE(flavor, stateCount, state)\
-    }
-
-COPY_EXCEPTION_REQUEST(32)
-COPY_EXCEPTION_REQUEST_STATE(32)
-COPY_EXCEPTION_REQUEST_STATE_IDENTITY(32)
-COPY_EXCEPTION_REQUEST(64)
-COPY_EXCEPTION_REQUEST_STATE(64)
-COPY_EXCEPTION_REQUEST_STATE_IDENTITY(64)
-
-# undef COPY_EXCEPTION_REQUEST_STATE_IDENTITY
-# undef COPY_EXCEPTION_REQUEST_STATE
-# undef COPY_EXCEPTION_REQUEST
-# undef COPY_REQUEST_STATE
-# undef COPY_REQUEST_IDENTITY
-# undef COPY_REQUEST_COMMON
-
-/* -------------------------------------------------------------------------- */
-/*                 End Mach definitions and helper functions                  */
-/* -------------------------------------------------------------------------- */
-
-/* Every Mach exception handler is parameterized by these four properties. */
-struct MachExceptionParameters
-{
-    exception_mask_t mask;
-    mach_port_t port;
-    exception_behavior_t behavior;
-    thread_state_flavor_t flavor;
-};
-
-struct ExceptionHandlerState
-{
-    MachExceptionParameters current;
-    MachExceptionParameters previous;
-
-    /* Each Mach exception handler runs in its own thread. */
-    Thread handlerThread;
-};
-
-/* This choice of ID is arbitrary, but must not match our exception ID. */
-static const mach_msg_id_t sIDQuit = 42;
-
-static ExceptionHandlerState sMachExceptionState;
-
-/*
- * The meat of our exception handler. This thread waits for an exception
- * message, annotates the exception if needed, then forwards it to the
- * previously installed handler (which will likely terminate the process).
- */
-static void
-MachExceptionHandler()
-{
-    kern_return_t ret;
-    MachExceptionParameters& current = sMachExceptionState.current;
-    MachExceptionParameters& previous = sMachExceptionState.previous;
-
-    // We use the simplest kind of 64-bit exception message here.
-    ExceptionRequest64 request = {};
-    request.header.msgh_local_port = current.port;
-    request.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(request));
-    ret = mach_msg(&request.header, MACH_RCV_MSG, 0, request.header.msgh_size,
-                   current.port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-
-    // Restore the previous handler. We're going to forward to it
-    // anyway, and if we crash while doing so we don't want to hang.
-    task_set_exception_ports(mach_task_self(), previous.mask, previous.port,
-                             previous.behavior, previous.flavor);
-
-    // If we failed even receiving the message, just give up.
-    if (ret != MACH_MSG_SUCCESS)
-        MOZ_CRASH("MachExceptionHandler: mach_msg failed to receive a message!");
-
-    // Terminate the thread if we're shutting down.
-    if (request.header.msgh_id == sIDQuit)
-        return;
-
-    // The only other valid message ID is the one associated with the
-    // EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES behavior we chose.
-    if (request.header.msgh_id != sIDRequest64)
-        MOZ_CRASH("MachExceptionHandler: Unexpected Message ID!");
-
-    // Make sure we can understand the exception we received.
-    if (request.exception != EXC_BAD_ACCESS || request.code_count != 2)
-        MOZ_CRASH("MachExceptionHandler: Unexpected exception type!");
-
-    // Get the address that the offending code tried to access.
-    uintptr_t address = uintptr_t(request.code[1]);
-
-    // If the faulting address is inside one of our protected regions, we
-    // want to annotate the crash to make it stand out from the crowd.
-    if (sProtectedRegions.isProtected(address)) {
-        ReportCrashIfDebug("Hit MOZ_CRASH(Tried to access a protected region!)\n");
-        MOZ_CRASH_ANNOTATE("Tried to access a protected region!");
-    }
-
-    // Forward to the previous handler which may be a debugger, the unix
-    // signal handler, the crash reporter or something else entirely.
-    if (previous.port != MACH_PORT_NULL) {
-        mach_msg_type_number_t stateCount;
-        thread_state_data_t state;
-        if ((uint32_t(previous.behavior) & ~MACH_EXCEPTION_CODES) != EXCEPTION_DEFAULT) {
-            // If the previous handler requested thread state, get it here.
-            stateCount = THREAD_STATE_MAX;
-            ret = thread_get_state(request.thread.name, previous.flavor, state, &stateCount);
-            if (ret != KERN_SUCCESS)
-                MOZ_CRASH("MachExceptionHandler: Could not get the thread state to forward!");
-        }
-
-        // Depending on the behavior of the previous handler, the forwarded
-        // exception message will have a different set of fields.
-        // Of particular note is that exception handlers that lack
-        // MACH_EXCEPTION_CODES will get 32-bit fields even on 64-bit
-        // systems. It appears that OSX simply truncates these fields.
-        ExceptionRequestUnion forward;
-        switch (uint32_t(previous.behavior)) {
-          case EXCEPTION_DEFAULT:
-             CopyExceptionRequest32(request, forward.r32);
-             break;
-          case EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES:
-             CopyExceptionRequest64(request, forward.r64);
-             break;
-          case EXCEPTION_STATE:
-             CopyExceptionRequestState32(request, forward.rs32,
-                                         previous.flavor, stateCount, state);
-             break;
-          case EXCEPTION_STATE | MACH_EXCEPTION_CODES:
-             CopyExceptionRequestState64(request, forward.rs64,
-                                         previous.flavor, stateCount, state);
-             break;
-          case EXCEPTION_STATE_IDENTITY:
-             CopyExceptionRequestStateIdentity32(request, forward.rsi32,
-                                                 previous.flavor, stateCount, state);
-             break;
-          case EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES:
-             CopyExceptionRequestStateIdentity64(request, forward.rsi64,
-                                                 previous.flavor, stateCount, state);
-             break;
-          default:
-             MOZ_CRASH("MachExceptionHandler: Unknown previous handler behavior!");
-        }
-
-        // Forward the generated message to the old port. The local and remote
-        // port fields *and their rights* are swapped on arrival, so we need to
-        // swap them back first.
-        forward.header.msgh_bits = (request.header.msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
-            MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(request.header.msgh_bits),
-                           MACH_MSGH_BITS_REMOTE(request.header.msgh_bits));
-        forward.header.msgh_local_port = forward.header.msgh_remote_port;
-        forward.header.msgh_remote_port = previous.port;
-        ret = mach_msg(&forward.header, MACH_SEND_MSG, forward.header.msgh_size, 0,
-                       MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-        if (ret != MACH_MSG_SUCCESS)
-            MOZ_CRASH("MachExceptionHandler: Failed to forward to the previous handler!");
-    } else {
-        // There was no previous task-level exception handler, so defer to the
-        // host level one instead. We set the return code to KERN_FAILURE to
-        // indicate that we did not handle the exception.
-        // The reply message ID is always the request ID + 100.
-        ExceptionReply reply = {};
-        reply.header.msgh_bits =
-            MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.header.msgh_bits), 0);
-        reply.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(reply));
-        reply.header.msgh_remote_port = request.header.msgh_remote_port;
-        reply.header.msgh_local_port = MACH_PORT_NULL;
-        reply.header.msgh_id = request.header.msgh_id + 100;
-        reply.NDR = request.NDR;
-        reply.RetCode = KERN_FAILURE;
-        ret = mach_msg(&reply.header, MACH_SEND_MSG, reply.header.msgh_size, 0,
-                       MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-        if (ret != MACH_MSG_SUCCESS)
-            MOZ_CRASH("MachExceptionHandler: Failed to forward to the host level!");
-    }
-}
-
-static void
-TerminateMachExceptionHandlerThread()
-{
-    // Send a simple quit message to the exception handler thread.
-    mach_msg_header_t msg;
-    msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
-    msg.msgh_size = static_cast<mach_msg_size_t>(sizeof(msg));
-    msg.msgh_remote_port = sMachExceptionState.current.port;
-    msg.msgh_local_port = MACH_PORT_NULL;
-    msg.msgh_reserved = 0;
-    msg.msgh_id = sIDQuit;
-    kern_return_t ret = mach_msg(&msg, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
-                                 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-
-    if (ret == MACH_MSG_SUCCESS)
-        sMachExceptionState.handlerThread.join();
-    else
-        MOZ_CRASH("MachExceptionHandler: Handler thread failed to terminate!");
-}
-
-bool
-MemoryProtectionExceptionHandler::install()
-{
-    MOZ_ASSERT(!sExceptionHandlerInstalled);
-
-    // If the exception handler is disabled, report success anyway.
-    if (MemoryProtectionExceptionHandler::isDisabled())
-        return true;
-
-    kern_return_t ret;
-    mach_port_t task = mach_task_self();
-
-    // Allocate a new exception port with receive rights.
-    sMachExceptionState.current = {};
-    MachExceptionParameters& current = sMachExceptionState.current;
-    ret = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &current.port);
-    if (ret != KERN_SUCCESS)
-        return false;
-
-    // Give the new port send rights as well.
-    ret = mach_port_insert_right(task, current.port, current.port, MACH_MSG_TYPE_MAKE_SEND);
-    if (ret != KERN_SUCCESS) {
-        mach_port_deallocate(task, current.port);
-        current = {};
-        return false;
-    }
-
-    // Start the thread that will receive the messages from our exception port.
-    if (!sMachExceptionState.handlerThread.init(MachExceptionHandler)) {
-        mach_port_deallocate(task, current.port);
-        current = {};
-        return false;
-    }
-
-    // Set the other properties of our new exception handler.
-    current.mask = EXC_MASK_BAD_ACCESS;
-    current.behavior = exception_behavior_t(EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES);
-    current.flavor = THREAD_STATE_NONE;
-
-    // Tell the task to use our exception handler, and save the previous one.
-    sMachExceptionState.previous = {};
-    MachExceptionParameters& previous = sMachExceptionState.previous;
-    mach_msg_type_number_t previousCount = 1;
-    ret = task_swap_exception_ports(task, current.mask, current.port, current.behavior,
-                                    current.flavor, &previous.mask, &previousCount,
-                                    &previous.port, &previous.behavior, &previous.flavor);
-    if (ret != KERN_SUCCESS) {
-        TerminateMachExceptionHandlerThread();
-        mach_port_deallocate(task, current.port);
-        previous = {};
-        current = {};
-        return false;
-    }
-
-    // We should have info on the previous exception handler, even if it's null.
-    MOZ_ASSERT(previousCount == 1);
-
-    sExceptionHandlerInstalled = true;
-    return sExceptionHandlerInstalled;
-}
-
-void
-MemoryProtectionExceptionHandler::uninstall()
-{
-    if (sExceptionHandlerInstalled) {
-        mach_port_t task = mach_task_self();
-
-        // Restore the previous exception handler.
-        MachExceptionParameters& previous = sMachExceptionState.previous;
-        task_set_exception_ports(task, previous.mask, previous.port,
-                                 previous.behavior, previous.flavor);
-
-        TerminateMachExceptionHandlerThread();
-
-        // Release the Mach IPC port we used.
-        mach_port_deallocate(task, sMachExceptionState.current.port);
-
-        sMachExceptionState.current = {};
-        sMachExceptionState.previous = {};
-
-        sExceptionHandlerInstalled = false;
-    }
-}
-
-#else
-
-#error "This platform is not supported!"
-
-#endif
-
-} /* namespace js */
deleted file mode 100644
--- a/js/src/ds/MemoryProtectionExceptionHandler.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ds_MemoryProtectionExceptionHandler_h
-#define ds_MemoryProtectionExceptionHandler_h
-
-namespace js {
-
-/*
- * This structure allows you to annotate crashes resulting from unauthorized
- * access to protected memory in regions of interest, to make them stand out
- * from other heap corruption crashes.
- */
-
-struct MemoryProtectionExceptionHandler
-{
-    /* Installs the exception handler; called early during initialization. */
-    static bool install();
-
-    /* If the exception handler is disabled, it won't be installed. */
-    static bool isDisabled();
-
-    /*
-     * Marks a region of memory as important; if something tries to access this
-     * region in an unauthorized way (e.g. writing to read-only memory),
-     * the resulting crash will be annotated to stand out from other random
-     * heap corruption.
-     */
-    static void addRegion(void* addr, size_t size);
-
-    /* Removes a previously added region. */
-    static void removeRegion(void* addr);
-
-    /* Uninstalls the exception handler; called late during shutdown. */
-    static void uninstall();
-};
-
-} /* namespace js */
-
-#endif /* ds_MemoryProtectionExceptionHandler_h */
--- a/js/src/ds/PageProtectingVector.h
+++ b/js/src/ds/PageProtectingVector.h
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ds_PageProtectingVector_h
 #define ds_PageProtectingVector_h
 
 #include "mozilla/Vector.h"
 
-#include "ds/MemoryProtectionExceptionHandler.h"
 #include "gc/Memory.h"
 
 namespace js {
 
 /*
  * PageProtectingVector is a vector that can only grow or be cleared, and marks
  * all of its fully used memory pages as read-only. It can be used to detect
  * heap corruption in important buffers, since anything that tries to write
@@ -54,32 +53,23 @@ class PageProtectingVector final
      * the whole page). As a result, if |unprotectedBytes >= pageSize|, we know
      * we can protect at least one more page, and |unprotectedBytes & ~pageMask|
      * is always the number of additional bytes we can protect. Put another way,
      * |offsetToPage + protectedBytes + unprotectedBytes == vector.length()|
      * always holds, and if |protectedBytes != 0| then |unprotectedBytes >= 0|.
      */
     intptr_t unprotectedBytes;
 
-    /*
-     * The size in bytes that a buffer needs to be before its pages will be
-     * protected. This is intended to reduce churn for small vectors while
-     * still offering protection when they grow large enough.
-     */
-    size_t protectionLowerBound;
-
     bool protectionEnabled;
     bool regionUnprotected;
 
     void updateOffsetToPage() {
         unprotectedBytes += offsetToPage;
         offsetToPage = (pageSize - (uintptr_t(vector.begin()) & pageMask)) & pageMask;
         unprotectedBytes -= offsetToPage;
-        protectionEnabled = vector.capacity() >= protectionLowerBound &&
-                            vector.capacity() >= pageSize + offsetToPage;
     }
 
     void protect() {
         MOZ_ASSERT(!regionUnprotected);
         if (protectionEnabled && unprotectedBytes >= intptr_t(pageSize)) {
             size_t toProtect = size_t(unprotectedBytes) & ~pageMask;
             uintptr_t addr = uintptr_t(vector.begin()) + offsetToPage + protectedBytes;
             gc::MakePagesReadOnly(reinterpret_cast<void*>(addr), toProtect);
@@ -96,27 +86,19 @@ class PageProtectingVector final
             gc::UnprotectPages(reinterpret_cast<void*>(addr), protectedBytes);
             unprotectedBytes += protectedBytes;
             protectedBytes = 0;
         }
     }
 
     void protectNewBuffer() {
         updateOffsetToPage();
-        if (protectionEnabled)
-            MemoryProtectionExceptionHandler::addRegion(vector.begin(), vector.capacity());
         protect();
     }
 
-    void unprotectOldBuffer() {
-        if (protectionEnabled)
-            MemoryProtectionExceptionHandler::removeRegion(vector.begin());
-        unprotect();
-    }
-
     bool anyProtected(size_t first, size_t last) {
         return last >= offsetToPage && first < offsetToPage + protectedBytes;
     }
 
     void setContainingRegion(size_t first, size_t last, uintptr_t* addr, size_t* size) {
         if (first < offsetToPage)
             first = offsetToPage;
         if (last > offsetToPage + protectedBytes - 1)
@@ -138,17 +120,17 @@ class PageProtectingVector final
     {
         PageProtectingVector* vector;
 
       public:
         AutoUnprotect() : vector(nullptr) {};
 
         void emplace(PageProtectingVector* holder) {
             vector = holder;
-            vector->unprotectOldBuffer();
+            vector->unprotect();
         }
 
         explicit AutoUnprotect(PageProtectingVector* holder) {
             emplace(holder);
         }
 
         ~AutoUnprotect() {
             if (vector)
@@ -159,32 +141,33 @@ class PageProtectingVector final
   public:
     explicit PageProtectingVector(AllocPolicy policy = AllocPolicy())
       : vector(policy),
         pageSize(gc::SystemPageSize()),
         pageMask(pageSize - 1),
         offsetToPage(0),
         protectedBytes(0),
         unprotectedBytes(0),
-        protectionLowerBound(0),
         protectionEnabled(false),
-        regionUnprotected(false) { protectNewBuffer(); }
+        regionUnprotected(false) { updateOffsetToPage(); }
 
-    ~PageProtectingVector() { unprotectOldBuffer(); }
+    ~PageProtectingVector() { unprotect(); }
 
-    /*
-     * Sets the lower bound on the size, in bytes, that this vector's underlying
-     * capacity has to be before its used pages will be protected.
-     */
-    void setLowerBoundForProtection(size_t bytes) {
-        if (protectionLowerBound != bytes) {
-            unprotectOldBuffer();
-            protectionLowerBound = bytes;
-            protectNewBuffer();
-        }
+    /* Enable protection for the entire buffer. */
+    void enableProtection() {
+        MOZ_ASSERT(!protectionEnabled);
+        protectionEnabled = true;
+        protectNewBuffer();
+    }
+
+    /* Disable protection for the entire buffer. */
+    void disableProtection() {
+        MOZ_ASSERT(protectionEnabled);
+        unprotect();
+        protectionEnabled = false;
     }
 
     /*
      * Disable protection on the smallest number of pages containing
      * both |firstByteOffset| and |lastByteOffset|.
      */
     void unprotectRegion(size_t firstByteOffset, size_t lastByteOffset) {
         MOZ_ASSERT(!regionUnprotected);
--- a/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
+++ b/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
@@ -82,18 +82,16 @@ namespace jit {
             if (MOZ_UNLIKELY(!m_buffer.append(reinterpret_cast<unsigned char*>(&value), size)))
                 oomDetected();
         }
 
     public:
         AssemblerBuffer()
             : m_oom(false)
         {
-            // Provide memory protection once the buffer starts to get big.
-            m_buffer.setLowerBoundForProtection(32 * 1024);
         }
 
         void ensureSpace(size_t space)
         {
             if (MOZ_UNLIKELY(!m_buffer.reserve(m_buffer.length() + space)))
                 oomDetected();
         }
 
@@ -136,16 +134,19 @@ namespace jit {
             return m_oom;
         }
 
         const unsigned char* buffer() const {
             MOZ_ASSERT(!m_oom);
             return m_buffer.begin();
         }
 
+        void enableBufferProtection() { m_buffer.enableProtection(); }
+        void disableBufferProtection() { m_buffer.disableProtection(); }
+
         void unprotectDataRegion(size_t firstByteOffset, size_t lastByteOffset) {
             m_buffer.unprotectRegion(firstByteOffset, lastByteOffset);
         }
         void reprotectDataRegion(size_t firstByteOffset, size_t lastByteOffset) {
             m_buffer.reprotectRegion(firstByteOffset, lastByteOffset);
         }
 
     protected:
--- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h
@@ -3846,16 +3846,19 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
     {
         memcpy(buffer, m_formatter.buffer(), size());
     }
     MOZ_MUST_USE bool appendBuffer(const BaseAssembler& other)
     {
         return m_formatter.append(other.m_formatter.buffer(), other.size());
     }
 
+    void enableBufferProtection() { m_formatter.enableBufferProtection(); }
+    void disableBufferProtection() { m_formatter.disableBufferProtection(); }
+
     void unprotectDataRegion(size_t firstByteOffset, size_t lastByteOffset) {
         m_formatter.unprotectDataRegion(firstByteOffset, lastByteOffset);
     }
     void reprotectDataRegion(size_t firstByteOffset, size_t lastByteOffset) {
         m_formatter.reprotectDataRegion(firstByteOffset, lastByteOffset);
     }
 
   protected:
@@ -5124,16 +5127,19 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
         unsigned char* data() { return m_buffer.data(); }
 
         MOZ_MUST_USE bool append(const unsigned char* values, size_t size)
         {
             return m_buffer.append(values, size);
         }
 
+        void enableBufferProtection() { m_buffer.enableBufferProtection(); }
+        void disableBufferProtection() { m_buffer.disableBufferProtection(); }
+
         void unprotectDataRegion(size_t firstByteOffset, size_t lastByteOffset) {
             m_buffer.unprotectDataRegion(firstByteOffset, lastByteOffset);
         }
         void reprotectDataRegion(size_t firstByteOffset, size_t lastByteOffset) {
             m_buffer.reprotectDataRegion(firstByteOffset, lastByteOffset);
         }
 
     private:
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -189,17 +189,16 @@ UNIFIED_SOURCES += [
     'builtin/SIMD.cpp',
     'builtin/SymbolObject.cpp',
     'builtin/TestingFunctions.cpp',
     'builtin/TypedObject.cpp',
     'builtin/WeakMapObject.cpp',
     'builtin/WeakSetObject.cpp',
     'devtools/sharkctl.cpp',
     'ds/LifoAlloc.cpp',
-    'ds/MemoryProtectionExceptionHandler.cpp',
     'frontend/BytecodeCompiler.cpp',
     'frontend/BytecodeEmitter.cpp',
     'frontend/FoldConstants.cpp',
     'frontend/NameFunctions.cpp',
     'frontend/ParseNode.cpp',
     'frontend/TokenStream.cpp',
     'gc/Allocator.cpp',
     'gc/Barrier.cpp',
--- a/js/src/vm/Initialization.cpp
+++ b/js/src/vm/Initialization.cpp
@@ -10,17 +10,16 @@
 
 #include "mozilla/Assertions.h"
 
 #include <ctype.h>
 
 #include "jstypes.h"
 
 #include "builtin/AtomicsObject.h"
-#include "ds/MemoryProtectionExceptionHandler.h"
 #include "gc/Statistics.h"
 #include "jit/ExecutableAllocator.h"
 #include "jit/Ion.h"
 #include "js/Utility.h"
 #if ENABLE_INTL_API
 #include "unicode/uclean.h"
 #include "unicode/utypes.h"
 #endif // ENABLE_INTL_API
@@ -96,18 +95,16 @@ JS::detail::InitWithFailureDiagnostic(bo
 
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     RETURN_IF_FAIL(js::oom::InitThreadType());
     js::oom::SetThreadType(js::oom::THREAD_TYPE_MAIN);
 #endif
 
     js::jit::ExecutableAllocator::initStatic();
 
-    MOZ_ALWAYS_TRUE(js::MemoryProtectionExceptionHandler::install());
-
     RETURN_IF_FAIL(js::jit::InitializeIon());
 
     js::DateTimeInfo::init();
 
 #if EXPOSE_INTL_API
     UErrorCode err = U_ZERO_ERROR;
     u_init(&err);
     if (U_FAILURE(err))
@@ -143,18 +140,16 @@ JS_ShutDown(void)
 
     js::DestroyHelperThreadsState();
 
 #ifdef JS_TRACE_LOGGING
     js::DestroyTraceLoggerThreadState();
     js::DestroyTraceLoggerGraphState();
 #endif
 
-    js::MemoryProtectionExceptionHandler::uninstall();
-
     // The only difficult-to-address reason for the restriction that you can't
     // call JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ
     // NowInit initialization code, which uses PR_CallOnce to initialize the
     // PRMJ_Now subsystem.  (For reinitialization to be permitted, we'd need to
     // "reset" the called-once status -- doable, but more trouble than it's
     // worth now.)  Initializing that subsystem from JS_Init eliminates the
     // problem, but initialization can take a comparatively long time (15ms or
     // so), so we really don't want to do it in JS_Init, and we really do want