Bug 1031529 part 2 - Remove JS_THREADSAFE #ifdefs everywhere. r=bhackett
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 24 Jul 2014 11:56:43 +0200
changeset 218895 a0dd5a83ba367e022caa857e7c76de66bf2e9d5e
parent 218894 35038c3324ee08b29924059da9b117940e740bd7
child 218896 6426fef52f51d751b6adb80053f6bebbc9cc67d4
push id583
push userbhearsum@mozilla.com
push dateMon, 24 Nov 2014 19:04:58 +0000
treeherdermozilla-release@c107e74250f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1031529
milestone34.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 1031529 part 2 - Remove JS_THREADSAFE #ifdefs everywhere. r=bhackett
js/public/Principals.h
js/src/builtin/TestingFunctions.cpp
js/src/gc/ForkJoinNursery.h
js/src/gc/GCRuntime.h
js/src/gc/RootMarking.cpp
js/src/jit/AsmJS.cpp
js/src/jit/AsmJSSignalHandlers.cpp
js/src/jit/CompileWrappers.cpp
js/src/jit/CompileWrappers.h
js/src/jit/Ion.cpp
js/src/jit/IonMacroAssembler.cpp
js/src/jit/PerfSpewer.cpp
js/src/jit/arm/Simulator-arm.cpp
js/src/jit/mips/Simulator-mips.cpp
js/src/jit/shared/CodeGenerator-x86-shared.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsgc.cpp
js/src/jslock.h
js/src/jspubtd.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/prmjtime.cpp
js/src/prmjtime.h
js/src/shell/js.cpp
js/src/vm/ForkJoin.cpp
js/src/vm/ForkJoin.h
js/src/vm/HelperThreads.cpp
js/src/vm/HelperThreads.h
js/src/vm/Monitor.cpp
js/src/vm/Monitor.h
js/src/vm/PosixNSPR.h
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/SPSProfiler.cpp
js/src/vm/SPSProfiler.h
js/src/vm/SelfHosting.cpp
js/src/vm/ThreadPool.cpp
js/src/vm/TraceLogging.cpp
js/src/vm/TraceLogging.h
js/xpconnect/src/XPCShellImpl.cpp
--- a/js/public/Principals.h
+++ b/js/public/Principals.h
@@ -12,21 +12,17 @@
 #include "mozilla/Atomics.h"
 
 #include <stdint.h>
 
 #include "jspubtd.h"
 
 struct JSPrincipals {
     /* Don't call "destroy"; use reference counting macros below. */
-#ifdef JS_THREADSAFE
     mozilla::Atomic<int32_t> refcount;
-#else
-    int32_t refcount;
-#endif
 
 #ifdef JS_DEBUG
     /* A helper to facilitate principals debugging. */
     uint32_t    debugToken;
 #endif
 
     void setDebugToken(uint32_t token) {
 # ifdef JS_DEBUG
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -118,21 +118,17 @@ GetBuildConfiguration(JSContext *cx, uns
 #ifdef JS_GC_ZEAL
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "has-gczeal", value))
         return false;
 
-#ifdef JS_THREADSAFE
     value = BooleanValue(true);
-#else
-    value = BooleanValue(false);
-#endif
     if (!JS_SetProperty(cx, info, "threadsafe", value))
         return false;
 
 #ifdef JS_MORE_DETERMINISTIC
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
@@ -1600,24 +1596,20 @@ Neuter(JSContext *cx, unsigned argc, jsv
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 HelperThreadCount(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-#ifdef JS_THREADSAFE
     if (CanUseExtraThreads())
         args.rval().setInt32(HelperThreadState().threadCount);
     else
         args.rval().setInt32(0);
-#else
-    args.rval().setInt32(0);
-#endif
     return true;
 }
 
 static bool
 TimesAccessed(JSContext *cx, unsigned argc, jsval *vp)
 {
     static int32_t accessed = 0;
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/gc/ForkJoinNursery.h
+++ b/js/src/gc/ForkJoinNursery.h
@@ -8,19 +8,16 @@
 #ifndef gc_ForkJoinNursery_h
 #define gc_ForkJoinNursery_h
 
 #ifdef JSGC_FJGENERATIONAL
 
 #ifndef JSGC_GENERATIONAL
 #error "JSGC_GENERATIONAL is required for the ForkJoinNursery"
 #endif
-#ifndef JS_THREADSAFE
-#error "JS_THREADSAFE is required for the ForkJoinNursery"
-#endif
 #ifndef JS_ION
 #error "JS_ION is required for the ForkJoinNursery"
 #endif
 
 #include "jsalloc.h"
 #include "jspubtd.h"
 
 #include "gc/Heap.h"
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -81,32 +81,28 @@ struct ConservativeGCData
         uintptr_t       words[JS_HOWMANY(sizeof(jmp_buf), sizeof(uintptr_t))];
     } registerSnapshot;
 
     ConservativeGCData() {
         mozilla::PodZero(this);
     }
 
     ~ConservativeGCData() {
-#ifdef JS_THREADSAFE
         /*
          * The conservative GC scanner should be disabled when the thread leaves
          * the last request.
          */
         JS_ASSERT(!hasStackToScan());
-#endif
     }
 
     MOZ_NEVER_INLINE void recordStackTop();
 
-#ifdef JS_THREADSAFE
     void updateForRequestEnd() {
         nativeStackTop = nullptr;
     }
-#endif
 
     bool hasStackToScan() const {
         return !!nativeStackTop;
     }
 };
 
 template<typename F>
 struct Callback {
@@ -188,61 +184,49 @@ class GCRuntime
 
     size_t maxBytesAllocated() { return maxBytes; }
     size_t maxMallocBytesAllocated() { return maxBytes; }
 
   public:
     // Internal public interface
     js::gc::State state() { return incrementalState; }
     void recordNativeStackTop();
-#ifdef JS_THREADSAFE
     void notifyRequestEnd() { conservativeGC.updateForRequestEnd(); }
-#endif
     bool isBackgroundSweeping() { return helperState.isBackgroundSweeping(); }
     void waitBackgroundSweepEnd() { helperState.waitBackgroundSweepEnd(); }
     void waitBackgroundSweepOrAllocEnd() { helperState.waitBackgroundSweepOrAllocEnd(); }
     void startBackgroundAllocationIfIdle() { helperState.startBackgroundAllocationIfIdle(); }
     void freeLater(void *p) { helperState.freeLater(p); }
 
 #ifdef DEBUG
 
     bool onBackgroundThread() { return helperState.onBackgroundThread(); }
 
     bool currentThreadOwnsGCLock() {
-#ifdef JS_THREADSAFE
         return lockOwner == PR_GetCurrentThread();
-#else
-        return true;
-#endif
     }
 
 #endif // DEBUG
 
-#ifdef JS_THREADSAFE
     void assertCanLock() {
         JS_ASSERT(!currentThreadOwnsGCLock());
     }
-#endif
 
     void lockGC() {
-#ifdef JS_THREADSAFE
         PR_Lock(lock);
         JS_ASSERT(!lockOwner);
 #ifdef DEBUG
         lockOwner = PR_GetCurrentThread();
 #endif
-#endif
     }
 
     void unlockGC() {
-#ifdef JS_THREADSAFE
         JS_ASSERT(lockOwner == PR_GetCurrentThread());
         lockOwner = nullptr;
         PR_Unlock(lock);
-#endif
     }
 
 #ifdef DEBUG
     bool isAllocAllowed() { return noGCOrAllocationCheck == 0; }
     void disallowAlloc() { ++noGCOrAllocationCheck; }
     void allowAlloc() {
         JS_ASSERT(!isAllocAllowed());
         --noGCOrAllocationCheck;
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -341,19 +341,17 @@ gc::GCRuntime::markConservativeStackRoot
         return;
     }
 
     if (incrementalState == MARK_ROOTS)
         rt->mainThread.gcSavedRoots.clearAndFree();
 #endif
 
     if (!conservativeGC.hasStackToScan()) {
-#ifdef JS_THREADSAFE
         JS_ASSERT(!rt->requestDepth);
-#endif
         return;
     }
 
     uintptr_t *stackMin, *stackEnd;
 #if JS_STACK_GROWTH_DIRECTION > 0
     stackMin = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
     stackEnd = conservativeGC.nativeStackTop;
 #else
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -5482,18 +5482,16 @@ CheckFunctionsSequential(ModuleCompiler 
     }
 
     if (!CheckAllFunctionsDefined(m))
         return false;
 
     return true;
 }
 
-#ifdef JS_THREADSAFE
-
 // Currently, only one asm.js parallel compilation is allowed at a time.
 // This RAII class attempts to claim this parallel compilation using atomic ops
 // on the helper thread state's asmJSCompilationInProgress.
 class ParallelCompilationGuard
 {
     bool parallelState_;
   public:
     ParallelCompilationGuard() : parallelState_(false) {}
@@ -5734,17 +5732,16 @@ CheckFunctionsParallel(ModuleCompiler &m
             return m.failOffset(func->srcBegin(), "allocation failure during compilation");
         }
 
         // Otherwise, the error occurred on the main thread and was already reported.
         return false;
     }
     return true;
 }
-#endif // JS_THREADSAFE
 
 static bool
 CheckFuncPtrTable(ModuleCompiler &m, ParseNode *var)
 {
     if (!IsDefinition(var))
         return m.fail(var, "function-pointer table name must be unique");
 
     ParseNode *arrayLiteral = MaybeDefinitionInitializer(var);
@@ -6822,23 +6819,18 @@ CheckModule(ExclusiveContext *cx, AsmJSP
     if (!CheckPrecedingStatements(m, stmtList))
         return false;
 
     if (!CheckModuleGlobals(m))
         return false;
 
     m.startFunctionBodies();
 
-#ifdef JS_THREADSAFE
     if (!CheckFunctionsParallel(m))
         return false;
-#else
-    if (!CheckFunctionsSequential(m))
-        return false;
-#endif
 
     m.finishFunctionBodies();
 
     if (!CheckFuncPtrTables(m))
         return false;
 
     if (!CheckModuleReturn(m))
         return false;
@@ -6888,20 +6880,18 @@ EstablishPreconditions(ExclusiveContext 
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
 
     if (parser.pc->isGenerator())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by generator context");
 
     if (parser.pc->isArrowFunction())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by arrow function context");
 
-#ifdef JS_THREADSAFE
     if (ParallelCompilationEnabled(cx))
         EnsureHelperThreadsInitialized(cx);
-#endif
 
     return true;
 }
 
 static bool
 NoExceptionPending(ExclusiveContext *cx)
 {
     return !cx->isJSContext() || !cx->asJSContext()->isExceptionPending();
--- a/js/src/jit/AsmJSSignalHandlers.cpp
+++ b/js/src/jit/AsmJSSignalHandlers.cpp
@@ -769,17 +769,16 @@ AsmJSMachExceptionHandler::AsmJSMachExce
   : installed_(false),
     thread_(nullptr),
     port_(MACH_PORT_NULL)
 {}
 
 void
 AsmJSMachExceptionHandler::uninstall()
 {
-#ifdef JS_THREADSAFE
     if (installed_) {
         thread_port_t thread = mach_thread_self();
         kern_return_t kret = thread_set_exception_ports(thread,
                                                         EXC_MASK_BAD_ACCESS,
                                                         MACH_PORT_NULL,
                                                         EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
                                                         THREAD_STATE_NONE);
         mach_port_deallocate(mach_task_self(), thread);
@@ -807,25 +806,21 @@ AsmJSMachExceptionHandler::uninstall()
         PR_JoinThread(thread_);
         thread_ = nullptr;
     }
     if (port_ != MACH_PORT_NULL) {
         DebugOnly<kern_return_t> kret = mach_port_destroy(mach_task_self(), port_);
         JS_ASSERT(kret == KERN_SUCCESS);
         port_ = MACH_PORT_NULL;
     }
-#else
-    JS_ASSERT(!installed_);
-#endif
 }
 
 bool
 AsmJSMachExceptionHandler::install(JSRuntime *rt)
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(!installed());
     kern_return_t kret;
     mach_port_t thread;
 
     // Get a port which can send and receive data.
     kret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port_);
     if (kret != KERN_SUCCESS)
         goto error;
@@ -855,19 +850,16 @@ AsmJSMachExceptionHandler::install(JSRun
         goto error;
 
     installed_ = true;
     return true;
 
   error:
     uninstall();
     return false;
-#else
-    return false;
-#endif
 }
 
 #else  // If not Windows or Mac, assume Unix
 
 // Be very cautious and default to not handling; we don't want to accidentally
 // silence real crashes from real bugs.
 static bool
 HandleSignal(int signum, siginfo_t *info, void *ctx)
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -73,23 +73,21 @@ CompileRuntime::addressOfGCZeal()
 #endif
 
 const void *
 CompileRuntime::addressOfInterrupt()
 {
     return &runtime()->interrupt;
 }
 
-#ifdef JS_THREADSAFE
 const void *
 CompileRuntime::addressOfInterruptPar()
 {
     return &runtime()->interruptPar;
 }
-#endif
 
 const void *
 CompileRuntime::addressOfThreadPool()
 {
     return &runtime()->threadPool;
 }
 
 const JitRuntime *
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -48,20 +48,17 @@ class CompileRuntime
     // &GetIonContext()->runtime->nativeIterCache.last
     const void *addressOfLastCachedNativeIterator();
 
 #ifdef JS_GC_ZEAL
     const void *addressOfGCZeal();
 #endif
 
     const void *addressOfInterrupt();
-
-#ifdef JS_THREADSAFE
     const void *addressOfInterruptPar();
-#endif
 
     const void *addressOfThreadPool();
 
     const JitRuntime *jitRuntime();
 
     // Compilation does not occur off thread when the SPS profiler is enabled.
     SPSProfiler &spsProfiler();
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -226,40 +226,36 @@ JitRuntime::initialize(JSContext *cx)
                 return false;
         }
 
         IonSpew(IonSpew_Codegen, "# Emitting bailout handler");
         bailoutHandler_ = generateBailoutHandler(cx, SequentialExecution);
         if (!bailoutHandler_)
             return false;
 
-#ifdef JS_THREADSAFE
         IonSpew(IonSpew_Codegen, "# Emitting parallel bailout handler");
         parallelBailoutHandler_ = generateBailoutHandler(cx, ParallelExecution);
         if (!parallelBailoutHandler_)
             return false;
-#endif
 
         IonSpew(IonSpew_Codegen, "# Emitting invalidator");
         invalidator_ = generateInvalidator(cx);
         if (!invalidator_)
             return false;
     }
 
     IonSpew(IonSpew_Codegen, "# Emitting sequential arguments rectifier");
     argumentsRectifier_ = generateArgumentsRectifier(cx, SequentialExecution, &argumentsRectifierReturnAddr_);
     if (!argumentsRectifier_)
         return false;
 
-#ifdef JS_THREADSAFE
     IonSpew(IonSpew_Codegen, "# Emitting parallel arguments rectifier");
     parallelArgumentsRectifier_ = generateArgumentsRectifier(cx, ParallelExecution, nullptr);
     if (!parallelArgumentsRectifier_)
         return false;
-#endif
 
     IonSpew(IonSpew_Codegen, "# Emitting EnterJIT sequence");
     enterJIT_ = generateEnterJIT(cx, EnterJitOptimized);
     if (!enterJIT_)
         return false;
 
     IonSpew(IonSpew_Codegen, "# Emitting EnterBaselineJIT sequence");
     enterBaselineJIT_ = generateEnterJIT(cx, EnterJitBaseline);
@@ -360,23 +356,21 @@ JitRuntime::ensureIonCodeProtected(JSRun
 }
 
 bool
 JitRuntime::handleAccessViolation(JSRuntime *rt, void *faultingAddress)
 {
     if (!rt->signalHandlersInstalled() || !ionAlloc_ || !ionAlloc_->codeContains((char *) faultingAddress))
         return false;
 
-#ifdef JS_THREADSAFE
     // All places where the interrupt lock is taken must either ensure that Ion
     // code memory won't be accessed within, or call ensureIonCodeAccessible to
     // render the memory safe for accessing. Otherwise taking the lock below
     // will deadlock the process.
     JS_ASSERT(!rt->currentThreadOwnsInterruptLock());
-#endif
 
     // Taking this lock is necessary to prevent the interrupting thread from marking
     // the memory as inaccessible while we are patching backedges. This will cause us
     // to SEGV while still inside the signal handler, and the process will terminate.
     JSRuntime::AutoLockForInterrupt lock(rt);
 
     // Ion code in the runtime faulted after it was made inaccessible. Reset
     // the code privileges and patch all loop backedges to perform an interrupt
@@ -504,23 +498,21 @@ bool
 JitCompartment::ensureIonStubsExist(JSContext *cx)
 {
     if (!stringConcatStub_) {
         stringConcatStub_ = generateStringConcatStub(cx, SequentialExecution);
         if (!stringConcatStub_)
             return false;
     }
 
-#ifdef JS_THREADSAFE
     if (!parallelStringConcatStub_) {
         parallelStringConcatStub_ = generateStringConcatStub(cx, ParallelExecution);
         if (!parallelStringConcatStub_)
             return false;
     }
-#endif
 
     return true;
 }
 
 bool
 JitCompartment::notifyOfActiveParallelEntryScript(JSContext *cx, HandleScript script)
 {
     // Fast path. The isParallelEntryScript bit guarantees that the script is
@@ -572,28 +564,26 @@ jit::FinishOffThreadBuilder(IonBuilder *
     // explicitly destroyed).
     js_delete(builder->backgroundCodegen());
     js_delete(builder->alloc().lifoAlloc());
 }
 
 static inline void
 FinishAllOffThreadCompilations(JSCompartment *comp)
 {
-#ifdef JS_THREADSAFE
     AutoLockHelperThreadState lock;
     GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
 
     for (size_t i = 0; i < finished.length(); i++) {
         IonBuilder *builder = finished[i];
         if (builder->compartment == CompileCompartment::get(comp)) {
             FinishOffThreadBuilder(builder);
             HelperThreadState().remove(finished, &i);
         }
     }
-#endif
 }
 
 /* static */ void
 JitRuntime::Mark(JSTracer *trc)
 {
     JS_ASSERT(!trc->runtime()->isHeapMinorCollecting());
     Zone *zone = trc->runtime()->atomsCompartment()->zone();
     for (gc::ZoneCellIterUnderGC i(zone, gc::FINALIZE_JITCODE); !i.done(); i.next()) {
@@ -1724,17 +1714,16 @@ CompileBackEnd(MIRGenerator *mir)
         return nullptr;
 
     return GenerateCode(mir, lir);
 }
 
 void
 AttachFinishedCompilations(JSContext *cx)
 {
-#ifdef JS_THREADSAFE
     JitCompartment *ion = cx->compartment()->jitCompartment();
     if (!ion)
         return;
 
     types::AutoEnterAnalysis enterTypes(cx);
     AutoLockHelperThreadState lock;
 
     GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
@@ -1783,36 +1772,31 @@ AttachFinishedCompilations(JSContext *cx
                 // nondeterministic time. It's not OK to throw a catchable
                 // exception from there.
                 cx->clearPendingException();
             }
         }
 
         FinishOffThreadBuilder(builder);
     }
-#endif
 }
 
 static const size_t BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
 
 static inline bool
 OffThreadCompilationAvailable(JSContext *cx)
 {
-#ifdef JS_THREADSAFE
     // Even if off thread compilation is enabled, compilation must still occur
     // on the main thread in some cases.
     //
     // Require cpuCount > 1 so that Ion compilation jobs and main-thread
     // execution are not competing for the same resources.
     return cx->runtime()->canUseOffthreadIonCompilation()
         && HelperThreadState().cpuCount > 1
         && CanUseExtraThreads();
-#else
-    return false;
-#endif
 }
 
 static void
 TrackAllProperties(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->hasSingletonType());
 
     for (Shape::Range<NoGC> range(obj->lastProperty()); !range.empty(); range.popFront())
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -969,22 +969,18 @@ MacroAssembler::loadStringChar(Register 
     load8ZeroExtend(BaseIndex(output, index, TimesOne), output);
 
     bind(&done);
 }
 
 void
 MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail)
 {
-#ifdef JS_THREADSAFE
     movePtr(ImmPtr(GetIonContext()->runtime->addressOfInterruptPar()), tempReg);
     branch32(Assembler::NonZero, Address(tempReg, 0), Imm32(0), fail);
-#else
-    MOZ_ASSUME_UNREACHABLE("JSRuntime::interruptPar doesn't exist on non-threadsafe builds.");
-#endif
 }
 
 // Save an exit frame (which must be aligned to the stack pointer) to
 // PerThreadData::jitTop of the main thread.
 void
 MacroAssembler::linkExitFrame()
 {
     AbsoluteAddress jitTop(GetIonContext()->runtime->addressOfJitTop());
--- a/js/src/jit/PerfSpewer.cpp
+++ b/js/src/jit/PerfSpewer.cpp
@@ -13,16 +13,18 @@
 #ifdef JS_ION_PERF
 # include "jit/IonSpewer.h"
 # include "jit/LinearScan.h"
 # include "jit/LIR.h"
 # include "jit/MIR.h"
 # include "jit/MIRGraph.h"
 #endif
 
+#include "jslock.h"
+
 // perf expects its data to be in a file /tmp/perf-PID.map, but for Android
 // and B2G the map files are written to /data/local/tmp/perf-PID.map
 //
 // Except that Android 4.3 no longer allows the browser to write to /data/local/tmp/
 // so also try /sdcard/.
 
 #ifndef PERF_SPEW_DIR
 # if defined(__ANDROID__)
@@ -43,20 +45,17 @@ using namespace js::jit;
 #ifdef JS_ION_PERF
 
 static uint32_t PerfMode = 0;
 
 static bool PerfChecked = false;
 
 static FILE *PerfFilePtr = nullptr;
 
-#ifdef JS_THREADSAFE
-# include "jslock.h"
 static PRLock *PerfMutex;
-#endif
 
 static bool
 openPerfMap(const char *dir)
 {
     const ssize_t bufferSize = 256;
     char filenameBuffer[bufferSize];
 
     if (snprintf(filenameBuffer, bufferSize, "%sperf-%d.map", dir, getpid()) >= bufferSize)
@@ -90,21 +89,19 @@ js::jit::CheckPerf() {
             fprintf(stderr, "Use IONPERF=block to record at basic block granularity\n");
             fprintf(stderr, "\n");
             fprintf(stderr, "Be advised that using IONPERF will cause all scripts\n");
             fprintf(stderr, "to be leaked.\n");
             exit(0);
         }
 
         if (PerfMode != PERF_MODE_NONE) {
-#ifdef JS_THREADSAFE
             PerfMutex = PR_NewLock();
             if (!PerfMutex)
                 MOZ_CRASH();
-#endif
 
             if (openPerfMap(PERF_SPEW_DIR)) {
                 PerfChecked = true;
                 return;
             }
 
 #if defined(__ANDROID__)
             if (openPerfMap(PERF_SPEW_DIR_2)) {
@@ -132,32 +129,28 @@ js::jit::PerfFuncEnabled() {
 }
 
 static bool
 lockPerfMap(void)
 {
     if (!PerfEnabled())
         return false;
 
-#ifdef JS_THREADSAFE
     PR_Lock(PerfMutex);
-#endif
 
     JS_ASSERT(PerfFilePtr);
     return true;
 }
 
 static void
 unlockPerfMap()
 {
     JS_ASSERT(PerfFilePtr);
     fflush(PerfFilePtr);
-#ifdef JS_THREADSAFE
     PR_Unlock(PerfMutex);
-#endif
 }
 
 uint32_t PerfSpewer::nextFunctionIndex = 0;
 
 bool
 PerfSpewer::startBasicBlock(MBasicBlock *blk,
                             MacroAssembler &masm)
 {
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -380,69 +380,57 @@ class SimulatorRuntime
   public:
     SimulatorRuntime()
       : redirection_(nullptr),
         lock_(nullptr),
         lockOwner_(nullptr)
     {}
     ~SimulatorRuntime();
     bool init() {
-#ifdef JS_THREADSAFE
         lock_ = PR_NewLock();
         if (!lock_)
             return false;
-#endif
         if (!icache_.init())
             return false;
         return true;
     }
     ICacheMap &icache() {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-#endif
         return icache_;
     }
     Redirection *redirection() const {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-#endif
         return redirection_;
     }
     void setRedirection(js::jit::Redirection *redirection) {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-#endif
         redirection_ = redirection;
     }
 };
 
 class AutoLockSimulatorRuntime
 {
   protected:
     SimulatorRuntime *srt_;
 
   public:
     AutoLockSimulatorRuntime(SimulatorRuntime *srt)
       : srt_(srt)
     {
-#ifdef JS_THREADSAFE
         PR_Lock(srt_->lock_);
         MOZ_ASSERT(!srt_->lockOwner_);
 #ifdef DEBUG
         srt_->lockOwner_ = PR_GetCurrentThread();
 #endif
-#endif
     }
 
     ~AutoLockSimulatorRuntime() {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(srt_->lockOwner_ == PR_GetCurrentThread());
         srt_->lockOwner_ = nullptr;
         PR_Unlock(srt_->lock_);
-#endif
     }
 };
 
 bool Simulator::ICacheCheckingEnabled = false;
 
 int64_t Simulator::StopSimAt = -1L;
 
 SimulatorRuntime *
@@ -1259,20 +1247,18 @@ Simulator::RedirectNativeFunction(void *
 SimulatorRuntime::~SimulatorRuntime()
 {
     Redirection *r = redirection_;
     while (r) {
         Redirection *next = r->next_;
         js_delete(r);
         r = next;
     }
-#ifdef JS_THREADSAFE
     if (lock_)
         PR_DestroyLock(lock_);
-#endif
 }
 
 // Sets the register in the architecture state. It will also deal with updating
 // Simulator internal state for special registers such as PC.
 void
 Simulator::set_register(int reg, int32_t value)
 {
     MOZ_ASSERT(reg >= 0 && reg < num_registers);
--- a/js/src/jit/mips/Simulator-mips.cpp
+++ b/js/src/jit/mips/Simulator-mips.cpp
@@ -514,68 +514,56 @@ class SimulatorRuntime
 
   public:
     SimulatorRuntime()
       : redirection_(nullptr),
         lock_(nullptr),
         lockOwner_(nullptr) {}
     ~SimulatorRuntime();
     bool init() {
-#ifdef JS_THREADSAFE
         lock_ = PR_NewLock();
         if (!lock_)
             return false;
-#endif
         if (!icache_.init())
             return false;
         return true;
     }
     ICacheMap &icache() {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-#endif
         return icache_;
     }
     Redirection *redirection() const {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-#endif
         return redirection_;
     }
     void setRedirection(js::jit::Redirection *redirection) {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
-#endif
         redirection_ = redirection;
     }
 };
 
 class AutoLockSimulatorRuntime
 {
   protected:
     SimulatorRuntime *srt_;
 
   public:
     AutoLockSimulatorRuntime(SimulatorRuntime *srt)
         : srt_(srt) {
-#ifdef JS_THREADSAFE
         PR_Lock(srt_->lock_);
         MOZ_ASSERT(!srt_->lockOwner_);
 #ifdef DEBUG
         srt_->lockOwner_ = PR_GetCurrentThread();
 #endif
-#endif
     }
 
     ~AutoLockSimulatorRuntime() {
-#ifdef JS_THREADSAFE
         MOZ_ASSERT(srt_->lockOwner_ == PR_GetCurrentThread());
         srt_->lockOwner_ = nullptr;
         PR_Unlock(srt_->lock_);
-#endif
     }
 };
 
 bool Simulator::ICacheCheckingEnabled = false;
 
 int Simulator::StopSimAt = -1;
 
 SimulatorRuntime *
@@ -1410,20 +1398,18 @@ Simulator::RedirectNativeFunction(void *
 SimulatorRuntime::~SimulatorRuntime()
 {
     Redirection *r = redirection_;
     while (r) {
         Redirection *next = r->next_;
         js_delete(r);
         r = next;
     }
-#ifdef JS_THREADSAFE
     if (lock_)
         PR_DestroyLock(lock_);
-#endif
 }
 
 // Get the active Simulator for the current thread.
 Simulator *
 Simulator::Current()
 {
     PerThreadData *pt = TlsPerThreadData.get();
     Simulator *sim = pt->simulator();
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -2066,17 +2066,16 @@ CodeGeneratorX86Shared::visitForkJoinGet
 
     masm.call(gen->jitRuntime()->forkJoinGetSliceStub());
     return true;
 }
 
 JitCode *
 JitRuntime::generateForkJoinGetSliceStub(JSContext *cx)
 {
-#ifdef JS_THREADSAFE
     MacroAssembler masm(cx);
 
     // We need two fixed temps. We need to fix eax for cmpxchg, and edx for
     // div.
     Register cxReg = ForkJoinGetSliceReg_cx, worker = cxReg;
     Register pool = ForkJoinGetSliceReg_temp0;
     Register bounds = ForkJoinGetSliceReg_temp1;
     Register output = ForkJoinGetSliceReg_output;
@@ -2215,15 +2214,12 @@ JitRuntime::generateForkJoinGetSliceStub
     Linker linker(masm);
     JitCode *code = linker.newCode<NoGC>(cx, JSC::OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "ForkJoinGetSliceStub");
 #endif
 
     return code;
-#else
-    return nullptr;
-#endif // JS_THREADSAFE
 }
 
 } // namespace jit
 } // namespace js
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -613,19 +613,17 @@ JS_ShutDown(void)
         // Gecko is too buggy to assert this just yet.
         fprintf(stderr,
                 "WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
                 "and everything alive inside it, that is) AT JS_ShutDown "
                 "TIME.  FIX THIS!\n");
     }
 #endif
 
-#ifdef JS_THREADSAFE
     HelperThreadState().finish();
-#endif
 
     PRMJ_NowShutdown();
 
 #if EXPOSE_INTL_API
     u_cleanup();
 #endif // EXPOSE_INTL_API
 
     jsInitState = ShutDown;
@@ -694,17 +692,16 @@ JS_GetRuntimePrivate(JSRuntime *rt)
 }
 
 JS_PUBLIC_API(void)
 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
 {
     rt->data = data;
 }
 
-#ifdef JS_THREADSAFE
 static void
 StartRequest(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime();
     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
 
     if (rt->requestDepth) {
         rt->requestDepth++;
@@ -725,46 +722,37 @@ StopRequest(JSContext *cx)
     if (rt->requestDepth != 1) {
         rt->requestDepth--;
     } else {
         rt->gc.notifyRequestEnd();
         rt->requestDepth = 0;
         rt->triggerActivityCallback(false);
     }
 }
-#endif /* JS_THREADSAFE */
 
 JS_PUBLIC_API(void)
 JS_BeginRequest(JSContext *cx)
 {
-#ifdef JS_THREADSAFE
     cx->outstandingRequests++;
     StartRequest(cx);
-#endif
 }
 
 JS_PUBLIC_API(void)
 JS_EndRequest(JSContext *cx)
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(cx->outstandingRequests != 0);
     cx->outstandingRequests--;
     StopRequest(cx);
-#endif
 }
 
 JS_PUBLIC_API(bool)
 JS_IsInRequest(JSRuntime *rt)
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
     return rt->requestDepth != 0;
-#else
-    return false;
-#endif
 }
 
 JS_PUBLIC_API(void)
 JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback, void *data)
 {
     rt->cxCallback = cxCallback;
     rt->cxCallbackData = data;
 }
@@ -4561,23 +4549,21 @@ JS::CanCompileOffThread(JSContext *cx, c
     // These are heuristics which the caller may choose to ignore (e.g., for
     // testing purposes).
     if (!options.forceAsync) {
         // Compiling off the main thread inolves creating a new Zone and other
         // significant overheads.  Don't bother if the script is tiny.
         if (length < TINY_LENGTH)
             return false;
 
-#ifdef JS_THREADSAFE
         // If the parsing task would have to wait for GC to complete, it'll probably
         // be faster to just start it synchronously on the main thread unless the
         // script is huge.
         if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
             return false;
-#endif // JS_THREADSAFE
     }
 
     return cx->runtime()->canUseParallelParsing() && CanUseExtraThreads();
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options,
                      const jschar *chars, size_t length,
@@ -4585,32 +4571,28 @@ JS::CompileOffThread(JSContext *cx, cons
 {
     JS_ASSERT(CanCompileOffThread(cx, options, length));
     return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData);
 }
 
 JS_PUBLIC_API(JSScript *)
 JS::FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token)
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
 
     if (maybecx) {
         RootedScript script(maybecx);
         {
             AutoLastFrameCheck lfc(maybecx);
             script = HelperThreadState().finishParseTask(maybecx, rt, token);
         }
         return script;
     } else {
         return HelperThreadState().finishParseTask(maybecx, rt, token);
     }
-#else
-    MOZ_CRASH("Off thread compilation is not available.");
-#endif
 }
 
 JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext *cx, JS::HandleObject obj, const char *ascii,
                  size_t length, const JS::CompileOptions &options, MutableHandleScript script)
 {
     return Compile(cx, obj, options, ascii, length, script);
 }
@@ -6223,21 +6205,17 @@ JS_PUBLIC_API(bool)
 JS_IsStopIteration(jsval v)
 {
     return v.isObject() && v.toObject().is<StopIterationObject>();
 }
 
 JS_PUBLIC_API(intptr_t)
 JS_GetCurrentThread()
 {
-#ifdef JS_THREADSAFE
     return reinterpret_cast<intptr_t>(PR_GetCurrentThread());
-#else
-    return 0;
-#endif
 }
 
 extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
 JS_AbortIfWrongThread(JSRuntime *rt)
 {
     if (!CurrentThreadCanAccessRuntime(rt))
         MOZ_CRASH();
     if (!js::TlsPerThreadData.get()->associatedWith(rt))
@@ -6492,38 +6470,27 @@ UnhideScriptedCaller(JSContext *cx)
     Activation *act = cx->runtime()->mainThread.activation();
     if (!act)
         return;
     act->unhideScriptedCaller();
 }
 
 } /* namespace JS */
 
-#ifdef JS_THREADSAFE
 static PRStatus
 CallOnce(void *func)
 {
     JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
     return init() ? PR_SUCCESS : PR_FAILURE;
 }
-#endif
 
 JS_PUBLIC_API(bool)
 JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
 {
-#ifdef JS_THREADSAFE
     return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
-#else
-    if (!*once) {
-        *once = true;
-        return func();
-    } else {
-        return true;
-    }
-#endif
 }
 
 AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
   : down(ContextFriendFields::get(cx)->autoGCRooters),
     tag_(tag),
     stackTop(&ContextFriendFields::get(cx)->autoGCRooters)
 {
     JS_ASSERT(this != *stackTop);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -36,17 +36,17 @@
 
 /************************************************************************/
 
 namespace JS {
 
 class Latin1CharsZ;
 class TwoByteChars;
 
-#if defined JS_THREADSAFE && defined JS_DEBUG
+#ifdef JS_DEBUG
 
 class JS_PUBLIC_API(AutoCheckRequestDepth)
 {
     JSContext *cx;
   public:
     explicit AutoCheckRequestDepth(JSContext *cx);
     explicit AutoCheckRequestDepth(js::ContextFriendFields *cx);
     ~AutoCheckRequestDepth();
@@ -55,17 +55,17 @@ class JS_PUBLIC_API(AutoCheckRequestDept
 # define CHECK_REQUEST(cx) \
     JS::AutoCheckRequestDepth _autoCheckRequestDepth(cx)
 
 #else
 
 # define CHECK_REQUEST(cx) \
     ((void) 0)
 
-#endif /* JS_THREADSAFE && JS_DEBUG */
+#endif /* JS_DEBUG */
 
 #ifdef JS_DEBUG
 /*
  * Assert that we're not doing GC on cx, that we're in a request as
  * needed, and that the compartments for cx and v are correct.
  * Also check that GC would be safe at this point.
  */
 JS_PUBLIC_API(void)
@@ -1339,32 +1339,32 @@ class JSAutoRequest
 };
 
 class JSAutoCheckRequest
 {
   public:
     explicit JSAutoCheckRequest(JSContext *cx
                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     {
-#if defined JS_THREADSAFE && defined JS_DEBUG
+#ifdef JS_DEBUG
         mContext = cx;
         JS_ASSERT(JS_IsInRequest(JS_GetRuntime(cx)));
 #endif
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     ~JSAutoCheckRequest() {
-#if defined JS_THREADSAFE && defined JS_DEBUG
+#ifdef JS_DEBUG
         JS_ASSERT(JS_IsInRequest(JS_GetRuntime(mContext)));
 #endif
     }
 
 
   private:
-#if defined JS_THREADSAFE && defined JS_DEBUG
+#ifdef JS_DEBUG
     JSContext *mContext;
 #endif
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 extern JS_PUBLIC_API(void)
 JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback, void *data);
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -186,29 +186,26 @@ js::NewContext(JSRuntime *rt, size_t sta
     /*
      * If cx is the first context on this runtime, initialize well-known atoms,
      * keywords, numbers, strings and self-hosted scripts. If one of these
      * steps should fail, the runtime will be left in a partially initialized
      * state, with zeroes and nulls stored in the default-initialized remainder
      * of the struct.
      */
     if (!rt->haveCreatedContext) {
-#ifdef JS_THREADSAFE
         JS_BeginRequest(cx);
-#endif
         bool ok = rt->initializeAtoms(cx);
         if (ok)
             ok = rt->initSelfHosting(cx);
 
         if (ok && !rt->parentRuntime)
             ok = rt->transformToPermanentAtoms();
 
-#ifdef JS_THREADSAFE
         JS_EndRequest(cx);
-#endif
+
         if (!ok) {
             DestroyContext(cx, DCM_NEW_FAILED);
             return nullptr;
         }
 
         rt->haveCreatedContext = true;
     }
 
@@ -222,20 +219,18 @@ js::NewContext(JSRuntime *rt, size_t sta
 }
 
 void
 js::DestroyContext(JSContext *cx, DestroyContextMode mode)
 {
     JSRuntime *rt = cx->runtime();
     JS_AbortIfWrongThread(rt);
 
-#ifdef JS_THREADSAFE
     if (cx->outstandingRequests != 0)
         MOZ_CRASH();
-#endif
 
     cx->checkNoGCRooters();
 
     if (mode != DCM_NEW_FAILED) {
         if (JSContextCallback cxCallback = rt->cxCallback) {
             /*
              * JSCONTEXT_DESTROY callback is not allowed to fail and must
              * return true.
@@ -974,36 +969,34 @@ js_GetErrorMessage(void *userRef, const 
     if (errorNumber > 0 && errorNumber < JSErr_Limit)
         return &js_ErrorFormatString[errorNumber];
     return nullptr;
 }
 
 bool
 js::InvokeInterruptCallback(JSContext *cx)
 {
-    JS_ASSERT_REQUEST_DEPTH(cx);
+    JS_ASSERT(cx->runtime()->requestDepth >= 1);
 
     JSRuntime *rt = cx->runtime();
     JS_ASSERT(rt->interrupt);
 
     // Reset the callback counter first, then run GC and yield. If another
     // thread is racing us here we will accumulate another callback request
     // which will be serviced at the next opportunity.
     rt->interrupt = false;
 
     // IonMonkey sets its stack limit to UINTPTR_MAX to trigger interrupt
     // callbacks.
     rt->resetJitStackLimit();
 
     js::gc::GCIfNeeded(cx);
 
 #ifdef JS_ION
-#ifdef JS_THREADSAFE
     rt->interruptPar = false;
-#endif
 
     // A worker thread may have requested an interrupt after finishing an Ion
     // compilation.
     jit::AttachFinishedCompilations(cx);
 #endif
 
     // Important: Additional callbacks can occur inside the callback handler
     // if it re-enters the JS engine. The embedding must ensure that the
@@ -1109,19 +1102,17 @@ JSContext::JSContext(JSRuntime *rt)
     resolvingList(nullptr),
     generatingError(false),
     savedFrameChains_(),
     defaultCompartmentObject_(nullptr),
     cycleDetectorSet(MOZ_THIS_IN_INITIALIZER_LIST()),
     errorReporter(nullptr),
     data(nullptr),
     data2(nullptr),
-#ifdef JS_THREADSAFE
     outstandingRequests(0),
-#endif
     iterValue(MagicValue(JS_NO_ITER_VALUE)),
     jitIsBroken(false),
 #ifdef MOZ_TRACE_JSCALLS
     functionCallback(nullptr),
 #endif
     innermostGenerator_(nullptr)
 {
     JS_ASSERT(static_cast<ContextFriendFields*>(this) ==
@@ -1340,17 +1331,17 @@ JSContext::findVersion() const
         return script->getVersion();
 
     if (compartment() && compartment()->options().version() != JSVERSION_UNKNOWN)
         return compartment()->options().version();
 
     return runtime()->defaultVersion();
 }
 
-#if defined JS_THREADSAFE && defined DEBUG
+#ifdef DEBUG
 
 JS::AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
     : cx(cx)
 {
     JS_ASSERT(cx->runtime()->requestDepth || cx->runtime()->isHeapBusy());
     JS_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
     cx->runtime()->checkRequestDepth++;
 }
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -483,21 +483,19 @@ struct JSContext : public js::ExclusiveC
     }
 
     JS::ContextOptions &options() {
         return options_;
     }
 
     js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
 
-#ifdef JS_THREADSAFE
     unsigned            outstandingRequests;/* number of JS_BeginRequest calls
                                                without the corresponding
                                                JS_EndRequest. */
-#endif
 
     /* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
     js::Value           iterValue;
 
     bool jitIsBroken;
 
     void updateJITEnabled();
 
@@ -780,22 +778,16 @@ js_ReportValueErrorFlags(JSContext *cx, 
                                     spindex, v, fallback, arg1, nullptr))
 
 #define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2)     \
     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
                                     spindex, v, fallback, arg1, arg2))
 
 extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
 
-#ifdef JS_THREADSAFE
-# define JS_ASSERT_REQUEST_DEPTH(cx)  JS_ASSERT((cx)->runtime()->requestDepth >= 1)
-#else
-# define JS_ASSERT_REQUEST_DEPTH(cx)  ((void) 0)
-#endif
-
 namespace js {
 
 /*
  * Invoke the interrupt callback and return false if the current execution
  * is to be terminated.
  */
 bool
 InvokeInterruptCallback(JSContext *cx);
@@ -813,17 +805,17 @@ HandleExecutionInterrupt(JSContext *cx);
  *
  * If this returns true, the caller can continue; if false, the caller must
  * break out of its loop. This happens if, for example, the user clicks "Stop
  * script" on the slow script dialog; treat it as an uncatchable error.
  */
 inline bool
 CheckForInterrupt(JSContext *cx)
 {
-    JS_ASSERT_REQUEST_DEPTH(cx);
+    MOZ_ASSERT(cx->runtime()->requestDepth >= 1);
     return !cx->runtime()->interrupt || InvokeInterruptCallback(cx);
 }
 
 /************************************************************************/
 
 class AutoStringVector : public AutoVectorRooter<JSString *>
 {
   public:
@@ -1023,17 +1015,16 @@ bool intrinsic_ObjectIsOpaqueTypedObject
 bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_TypeDescrIsSimpleType(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp);
 
 class AutoLockForExclusiveAccess
 {
-#ifdef JS_THREADSAFE
     JSRuntime *runtime;
 
     void init(JSRuntime *rt) {
         runtime = rt;
         if (runtime->numExclusiveThreads) {
             runtime->assertCanLock(ExclusiveAccessLock);
             PR_Lock(runtime->exclusiveAccessLock);
 #ifdef DEBUG
@@ -1059,29 +1050,16 @@ class AutoLockForExclusiveAccess
             JS_ASSERT(runtime->exclusiveAccessOwner == PR_GetCurrentThread());
             runtime->exclusiveAccessOwner = nullptr;
             PR_Unlock(runtime->exclusiveAccessLock);
         } else {
             JS_ASSERT(runtime->mainThreadHasExclusiveAccess);
             runtime->mainThreadHasExclusiveAccess = false;
         }
     }
-#else // JS_THREADSAFE
-  public:
-    AutoLockForExclusiveAccess(ExclusiveContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
-        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-    }
-    AutoLockForExclusiveAccess(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
-        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-    }
-    ~AutoLockForExclusiveAccess() {
-        // An empty destructor is needed to avoid warnings from clang about
-        // unused local variables of this type.
-    }
-#endif // JS_THREADSAFE
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 } /* namespace js */
 
 #ifdef _MSC_VER
 #pragma warning(pop)
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -829,23 +829,21 @@ js::DumpHeapComplete(JSRuntime *rt, FILE
 }
 
 JS_FRIEND_API(const JSStructuredCloneCallbacks *)
 js::GetContextStructuredCloneCallbacks(JSContext *cx)
 {
     return cx->runtime()->structuredCloneCallbacks;
 }
 
-#ifdef JS_THREADSAFE
 JS_FRIEND_API(bool)
 js::ContextHasOutstandingRequests(const JSContext *cx)
 {
     return cx->outstandingRequests > 0;
 }
-#endif
 
 JS_FRIEND_API(void)
 js::SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg)
 {
     rt->activityCallback = cb;
     rt->activityCallbackArg = arg;
 }
 
@@ -1204,21 +1202,17 @@ js::ReportErrorWithId(JSContext *cx, con
         return;
     JS_ReportError(cx, msg, bytes.ptr());
 }
 
 #ifdef DEBUG
 JS_PUBLIC_API(bool)
 js::IsInRequest(JSContext *cx)
 {
-#ifdef JS_THREADSAFE
     return !!cx->runtime()->requestDepth;
-#else
-    return true;
-#endif
 }
 #endif
 
 #ifdef JSGC_GENERATIONAL
 JS_FRIEND_API(void)
 JS_StoreObjectPostBarrierCallback(JSContext* cx,
                                   void (*callback)(JSTracer *trc, JSObject *key, void *data),
                                   JSObject *key, void *data)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1050,20 +1050,18 @@ JS_FRIEND_API(size_t)
 GetPCCountScriptCount(JSContext *cx);
 
 JS_FRIEND_API(JSString *)
 GetPCCountScriptSummary(JSContext *cx, size_t script);
 
 JS_FRIEND_API(JSString *)
 GetPCCountScriptContents(JSContext *cx, size_t script);
 
-#ifdef JS_THREADSAFE
 JS_FRIEND_API(bool)
 ContextHasOutstandingRequests(const JSContext *cx);
-#endif
 
 typedef void
 (* ActivityCallback)(void *arg, bool active);
 
 /*
  * Sets a callback that is run whenever the runtime goes idle - the
  * last active request ceases - and begins activity - when it was
  * idle and a request begins.
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1276,21 +1276,19 @@ GCRuntime::initZeal()
 /* Lifetime for type sets attached to scripts containing observed types. */
 static const int64_t JIT_SCRIPT_RELEASE_TYPES_INTERVAL = 60 * 1000 * 1000;
 
 bool
 GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
 {
     InitMemorySubsystem();
 
-#ifdef JS_THREADSAFE
     lock = PR_NewLock();
     if (!lock)
         return false;
-#endif
 
     if (!chunkSet.init(INITIAL_CHUNK_CAPACITY))
         return false;
 
     if (!rootsHash.init(256))
         return false;
 
     if (!helperState.init())
@@ -1333,21 +1331,19 @@ GCRuntime::init(uint32_t maxbytes, uint3
         return false;
 
     return true;
 }
 
 void
 GCRuntime::recordNativeStackTop()
 {
-#ifdef JS_THREADSAFE
     /* Record the stack top here only if we are called from a request. */
     if (!rt->requestDepth)
         return;
-#endif
     conservativeGC.recordStackTop();
 }
 
 void
 GCRuntime::finish()
 {
     /*
      * Wait until the background finalization stops and the helper thread
@@ -1381,22 +1377,20 @@ GCRuntime::finish()
 
     expireAndFreeChunkPool(true);
 
     if (rootsHash.initialized())
         rootsHash.clear();
 
     FinishPersistentRootedChains(rt);
 
-#ifdef JS_THREADSAFE
     if (lock) {
         PR_DestroyLock(lock);
         lock = nullptr;
     }
-#endif
 
     FinishTrace();
 }
 
 void
 js::gc::FinishPersistentRootedChains(JSRuntime *rt)
 {
     /* The lists of persistent roots are stored on the shadow runtime. */
@@ -1855,17 +1849,16 @@ ArenaLists::allocateFromArenaInline(Zone
      * thread will have a distinct ArenaLists.  Therefore, whenever we
      * fall through to pickChunk() we must be sure that we are holding
      * a lock.
      */
 
     AutoLockGC maybeLock;
 
     bool backgroundFinalizationIsRunning = false;
-#ifdef JS_THREADSAFE
     ArenaLists::BackgroundFinalizeState *bfs = &backgroundFinalizeState[thingKind];
     if (*bfs != BFS_DONE) {
         /*
          * We cannot search the arena list for free things while background
          * finalization runs and can modify it at any moment. So we always
          * allocate a new arena in that case.
          */
         JSRuntime *rt = zone->runtimeFromAnyThread();
@@ -1874,17 +1867,16 @@ ArenaLists::allocateFromArenaInline(Zone
             backgroundFinalizationIsRunning = true;
         } else if (*bfs == BFS_JUST_FINISHED) {
             /* See comments before BackgroundFinalizeState definition. */
             *bfs = BFS_DONE;
         } else {
             JS_ASSERT(*bfs == BFS_DONE);
         }
     }
-#endif /* JS_THREADSAFE */
 
     ArenaHeader *aheader;
     ArenaList *al = &arenaLists[thingKind];
     if (!backgroundFinalizationIsRunning && (aheader = al->arenaAfterCursor())) {
         /*
          * Normally, the empty arenas are returned to the chunk
          * and should not be present on the list. In parallel
          * execution, however, we keep empty arenas in the arena
@@ -2021,20 +2013,17 @@ ArenaLists::queueForForegroundSweep(Free
     arenaListsToSweep[thingKind] = arenaLists[thingKind].head();
     arenaLists[thingKind].clear();
 }
 
 inline void
 ArenaLists::queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind)
 {
     JS_ASSERT(IsBackgroundFinalized(thingKind));
-
-#ifdef JS_THREADSAFE
     JS_ASSERT(!fop->runtime()->gc.isBackgroundSweeping());
-#endif
 
     ArenaList *al = &arenaLists[thingKind];
     if (al->isEmpty()) {
         JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE);
         return;
     }
 
     /*
@@ -2195,20 +2184,18 @@ ArenaLists::refillFreeList(ThreadSafeCon
     JS_ASSERT_IF(cx->isJSContext(), !cx->asJSContext()->runtime()->isHeapBusy());
 
     Zone *zone = cx->allocator()->zone_;
 
     bool runGC = cx->allowGC() && allowGC &&
                  cx->asJSContext()->runtime()->gc.incrementalState != NO_INCREMENTAL &&
                  zone->usage.gcBytes() > zone->gcTriggerBytes;
 
-#ifdef JS_THREADSAFE
     JS_ASSERT_IF(cx->isJSContext() && allowGC,
                  !cx->asJSContext()->runtime()->currentThreadHasExclusiveAccess());
-#endif
 
     for (;;) {
         if (MOZ_UNLIKELY(runGC)) {
             if (void *thing = RunLastDitchGC(cx->asJSContext(), zone, thingKind))
                 return thing;
         }
 
         AutoMaybeStartBackgroundAllocation maybeStartBackgroundAllocation;
@@ -2228,17 +2215,16 @@ ArenaLists::refillFreeList(ThreadSafeCon
                 if (MOZ_LIKELY(!!thing))
                     return thing;
                 if (secondAttempt)
                     break;
 
                 cx->asJSContext()->runtime()->gc.waitBackgroundSweepEnd();
             }
         } else {
-#ifdef JS_THREADSAFE
             /*
              * If we're off the main thread, we try to allocate once and
              * return whatever value we get. If we aren't in a ForkJoin
              * session (i.e. we are in a helper thread async with the main
              * thread), we need to first ensure the main thread is not in a GC
              * session.
              */
             mozilla::Maybe<AutoLockHelperThreadState> lock;
@@ -2248,19 +2234,16 @@ ArenaLists::refillFreeList(ThreadSafeCon
                 while (rt->isHeapBusy())
                     HelperThreadState().wait(GlobalHelperThreadState::PRODUCER);
             }
 
             void *thing = cx->allocator()->arenas.allocateFromArenaInline(zone, thingKind,
                                                                           maybeStartBackgroundAllocation);
             if (thing)
                 return thing;
-#else
-            MOZ_CRASH();
-#endif
         }
 
         if (!cx->allowGC() || !allowGC)
             return nullptr;
 
         /*
          * We failed to allocate. Run the GC if we haven't done it already.
          * Otherwise report OOM.
@@ -2635,83 +2618,73 @@ GCRuntime::sweepBackgroundThings(bool on
     }
 
     sweepingZones = nullptr;
 }
 
 void
 GCRuntime::assertBackgroundSweepingFinished()
 {
-#if defined(JS_THREADSAFE) && defined(DEBUG)
+#ifdef DEBUG
     JS_ASSERT(!sweepingZones);
     for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
         for (unsigned i = 0; i < FINALIZE_LIMIT; ++i) {
             JS_ASSERT(!zone->allocator.arenas.arenaListsToSweep[i]);
             JS_ASSERT(zone->allocator.arenas.doneBackgroundFinalize(AllocKind(i)));
         }
     }
 #endif
 }
 
-#ifdef JS_THREADSAFE
 unsigned
 js::GetCPUCount()
 {
     static unsigned ncpus = 0;
     if (ncpus == 0) {
 # ifdef XP_WIN
         SYSTEM_INFO sysinfo;
         GetSystemInfo(&sysinfo);
         ncpus = unsigned(sysinfo.dwNumberOfProcessors);
 # else
         long n = sysconf(_SC_NPROCESSORS_ONLN);
         ncpus = (n > 0) ? unsigned(n) : 1;
 # endif
     }
     return ncpus;
 }
-#endif /* JS_THREADSAFE */
 
 bool
 GCHelperState::init()
 {
-#ifdef JS_THREADSAFE
     if (!(done = PR_NewCondVar(rt->gc.lock)))
         return false;
 
     if (CanUseExtraThreads()) {
         backgroundAllocation = (GetCPUCount() >= 2);
         HelperThreadState().ensureInitialized();
     } else {
         backgroundAllocation = false;
     }
-#else
-    backgroundAllocation = false;
-#endif /* JS_THREADSAFE */
 
     return true;
 }
 
 void
 GCHelperState::finish()
 {
     if (!rt->gc.lock) {
         JS_ASSERT(state_ == IDLE);
         return;
     }
 
-#ifdef JS_THREADSAFE
     // Wait for any lingering background sweeping to finish.
     waitBackgroundSweepEnd();
 
     if (done)
         PR_DestroyCondVar(done);
-#else
-    MOZ_CRASH();
-#endif /* JS_THREADSAFE */
 }
 
 GCHelperState::State
 GCHelperState::state()
 {
     JS_ASSERT(rt->gc.currentThreadOwnsGCLock());
     return state_;
 }
@@ -2721,48 +2694,39 @@ GCHelperState::setState(State state)
 {
     JS_ASSERT(rt->gc.currentThreadOwnsGCLock());
     state_ = state;
 }
 
 void
 GCHelperState::startBackgroundThread(State newState)
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(!thread && state() == IDLE && newState != IDLE);
     setState(newState);
 
     if (!HelperThreadState().gcHelperWorklist().append(this))
         CrashAtUnhandlableOOM("Could not add to pending GC helpers list");
     HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
-#else
-    MOZ_CRASH();
-#endif
 }
 
 void
 GCHelperState::waitForBackgroundThread()
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
 
     rt->gc.lockOwner = nullptr;
     PR_WaitCondVar(done, PR_INTERVAL_NO_TIMEOUT);
 #ifdef DEBUG
     rt->gc.lockOwner = PR_GetCurrentThread();
 #endif
-#else
-    MOZ_CRASH();
-#endif
 }
 
 void
 GCHelperState::work()
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(CanUseExtraThreads());
 
     AutoLockGC lock(rt);
 
     JS_ASSERT(!thread);
     thread = PR_GetCurrentThread();
 
     TraceLogger *logger = TraceLoggerForCurrentThread();
@@ -2803,42 +2767,36 @@ GCHelperState::work()
       case CANCEL_ALLOCATION:
         break;
     }
 
     setState(IDLE);
     thread = nullptr;
 
     PR_NotifyAllCondVar(done);
-#else
-    MOZ_CRASH();
-#endif
 }
 
 void
 GCHelperState::startBackgroundSweep(bool shouldShrink)
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(CanUseExtraThreads());
 
     AutoLockHelperThreadState helperLock;
     AutoLockGC lock(rt);
     JS_ASSERT(state() == IDLE);
     JS_ASSERT(!sweepFlag);
     sweepFlag = true;
     shrinkFlag = shouldShrink;
     startBackgroundThread(SWEEPING);
-#endif /* JS_THREADSAFE */
 }
 
 /* Must be called with the GC lock taken. */
 void
 GCHelperState::startBackgroundShrink()
 {
-#ifdef JS_THREADSAFE
     JS_ASSERT(CanUseExtraThreads());
     switch (state()) {
       case IDLE:
         JS_ASSERT(!sweepFlag);
         shrinkFlag = true;
         startBackgroundThread(SWEEPING);
         break;
       case SWEEPING:
@@ -2847,53 +2805,46 @@ GCHelperState::startBackgroundShrink()
       case ALLOCATING:
       case CANCEL_ALLOCATION:
         /*
          * If we have started background allocation there is nothing to
          * shrink.
          */
         break;
     }
-#endif /* JS_THREADSAFE */
 }
 
 void
 GCHelperState::waitBackgroundSweepEnd()
 {
-#ifdef JS_THREADSAFE
     AutoLockGC lock(rt);
     while (state() == SWEEPING)
         waitForBackgroundThread();
     if (rt->gc.incrementalState == NO_INCREMENTAL)
         rt->gc.assertBackgroundSweepingFinished();
-#endif /* JS_THREADSAFE */
 }
 
 void
 GCHelperState::waitBackgroundSweepOrAllocEnd()
 {
-#ifdef JS_THREADSAFE
     AutoLockGC lock(rt);
     if (state() == ALLOCATING)
         setState(CANCEL_ALLOCATION);
     while (state() == SWEEPING || state() == CANCEL_ALLOCATION)
         waitForBackgroundThread();
     if (rt->gc.incrementalState == NO_INCREMENTAL)
         rt->gc.assertBackgroundSweepingFinished();
-#endif /* JS_THREADSAFE */
 }
 
 /* Must be called with the GC lock taken. */
 inline void
 GCHelperState::startBackgroundAllocationIfIdle()
 {
-#ifdef JS_THREADSAFE
     if (state_ == IDLE)
         startBackgroundThread(ALLOCATING);
-#endif /* JS_THREADSAFE */
 }
 
 void
 GCHelperState::replenishAndFreeLater(void *ptr)
 {
     JS_ASSERT(freeCursor == freeCursorEnd);
     do {
         if (freeCursor && !freeVector.append(freeCursorEnd - FREE_ARRAY_LENGTH))
@@ -2905,17 +2856,16 @@ GCHelperState::replenishAndFreeLater(voi
         }
         freeCursorEnd = freeCursor + FREE_ARRAY_LENGTH;
         *freeCursor++ = ptr;
         return;
     } while (false);
     js_free(ptr);
 }
 
-#ifdef JS_THREADSAFE
 /* Must be called with the GC lock taken. */
 void
 GCHelperState::doSweep()
 {
     if (sweepFlag) {
         sweepFlag = false;
         AutoUnlockGC unlock(rt);
 
@@ -2945,26 +2895,21 @@ GCHelperState::doSweep()
      * ExpireChunksAndArenas(rt, false) was running, so we recheck the flag
      * afterwards.
      */
     if (!shrinking && shrinkFlag) {
         shrinkFlag = false;
         rt->gc.expireChunksAndArenas(true);
     }
 }
-#endif /* JS_THREADSAFE */
 
 bool
 GCHelperState::onBackgroundThread()
 {
-#ifdef JS_THREADSAFE
     return PR_GetCurrentThread() == thread;
-#else
-    return false;
-#endif
 }
 
 bool
 GCRuntime::releaseObservedTypes()
 {
     bool releaseTypes = false;
 
 #ifdef JS_GC_ZEAL
@@ -4335,19 +4280,17 @@ GCRuntime::beginSweepPhase(bool lastGC)
      */
 
     JS_ASSERT(!abortSweepAfterCurrentGroup);
 
     computeNonIncrementalMarkingForValidation();
 
     gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
 
-#ifdef JS_THREADSAFE
     sweepOnBackgroundThread = !lastGC && !TraceEnabled() && CanUseExtraThreads();
-#endif
 
 #ifdef DEBUG
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
         JS_ASSERT(!c->gcIncomingGrayPointers);
         for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
             if (e.front().key().kind != CrossCompartmentKey::StringWrapper)
                 AssertNotOnGrayList(&e.front().value().get().toObject());
         }
@@ -4626,41 +4569,33 @@ AutoTraceSession::AutoTraceSession(JSRun
     // the exclusive access lock. To avoid deadlocking when we try to acquire
     // this lock during GC and the other thread is waiting, make sure we hold
     // the exclusive access lock during GC sessions.
     JS_ASSERT(rt->currentThreadHasExclusiveAccess());
 
     if (rt->exclusiveThreadsPresent()) {
         // Lock the helper thread state when changing the heap state in the
         // presence of exclusive threads, to avoid racing with refillFreeList.
-#ifdef JS_THREADSAFE
         AutoLockHelperThreadState lock;
         rt->gc.heapState = heapState;
-#else
-        MOZ_CRASH();
-#endif
     } else {
         rt->gc.heapState = heapState;
     }
 }
 
 AutoTraceSession::~AutoTraceSession()
 {
     JS_ASSERT(runtime->isHeapBusy());
 
     if (runtime->exclusiveThreadsPresent()) {
-#ifdef JS_THREADSAFE
         AutoLockHelperThreadState lock;
         runtime->gc.heapState = prevState;
 
         // Notify any helper threads waiting for the trace session to end.
         HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
-#else
-        MOZ_CRASH();
-#endif
     } else {
         runtime->gc.heapState = prevState;
     }
 }
 
 AutoCopyFreeListToArenas::AutoCopyFreeListToArenas(JSRuntime *rt, ZoneSelector selector)
   : runtime(rt),
     selector(selector)
@@ -5193,20 +5128,18 @@ GCRuntime::collect(bool incremental, int
     /* GC shouldn't be running in parallel execution mode */
     MOZ_ASSERT(!InParallelSection());
 
     JS_AbortIfWrongThread(rt);
 
     /* If we attempt to invoke the GC while we are running in the GC, assert. */
     MOZ_ASSERT(!rt->isHeapBusy());
 
-#ifdef JS_THREADSAFE
     /* The engine never locks across anything that could GC. */
     MOZ_ASSERT(!rt->currentThreadHasExclusiveAccess());
-#endif
 
     if (rt->mainThread.suppressGC)
         return;
 
     TraceLogger *logger = TraceLoggerForMainThread(rt);
     AutoTraceLog logGC(logger, TraceLogger::GC);
 
 #ifdef JS_GC_ZEAL
@@ -5254,21 +5187,18 @@ GCRuntime::collect(bool incremental, int
          * If we reset an existing GC, we need to start a new one. Also, we
          * repeat GCs that happen during shutdown (the gcShouldCleanUpEverything
          * case) until we can be sure that no additional garbage is created
          * (which typically happens if roots are dropped during finalizers).
          */
         repeat = (poked && cleanUpEverything) || wasReset;
     } while (repeat);
 
-    if (incrementalState == NO_INCREMENTAL) {
-#ifdef JS_THREADSAFE
+    if (incrementalState == NO_INCREMENTAL)
         EnqueuePendingParseTasksAfterGC(rt);
-#endif
-    }
 }
 
 void
 js::GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason)
 {
     rt->gc.collect(false, SliceBudget::Unlimited, gckind, reason);
 }
 
@@ -5366,21 +5296,17 @@ JS::ShrinkGCBuffers(JSRuntime *rt)
 
 void
 GCRuntime::shrinkBuffers()
 {
     AutoLockHelperThreadState helperLock;
     AutoLockGC lock(rt);
     JS_ASSERT(!rt->isHeapBusy());
 
-#ifdef JS_THREADSAFE
     helperState.startBackgroundShrink();
-#else
-    expireChunksAndArenas(true);
-#endif
 }
 
 void
 js::MinorGC(JSRuntime *rt, JS::gcreason::Reason reason)
 {
     rt->gc.minorGC(reason);
 }
 
@@ -5781,23 +5707,22 @@ ArenaLists::adoptArenas(JSRuntime *rt, A
     // The other parallel threads have all completed now, and GC
     // should be inactive, but still take the lock as a kind of read
     // fence.
     AutoLockGC lock(rt);
 
     fromArenaLists->purge();
 
     for (size_t thingKind = 0; thingKind != FINALIZE_LIMIT; thingKind++) {
-#ifdef JS_THREADSAFE
         // When we enter a parallel section, we join the background
         // thread, and we do not run GC while in the parallel section,
         // so no finalizer should be active!
         normalizeBackgroundFinalizeState(AllocKind(thingKind));
         fromArenaLists->normalizeBackgroundFinalizeState(AllocKind(thingKind));
-#endif
+
         ArenaList *fromList = &fromArenaLists->arenaLists[thingKind];
         ArenaList *toList = &arenaLists[thingKind];
         fromList->check();
         toList->check();
         ArenaHeader *next;
         for (ArenaHeader *fromHeader = fromList->head(); fromHeader; fromHeader = next) {
             // Copy fromHeader->next before releasing/reinserting.
             next = fromHeader->next;
--- a/js/src/jslock.h
+++ b/js/src/jslock.h
@@ -2,32 +2,22 @@
  * 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 jslock_h
 #define jslock_h
 
-#ifdef JS_THREADSAFE
-
 #ifdef JS_POSIX_NSPR
 
 #include "vm/PosixNSPR.h"
 
 #else /* JS_POSIX_NSPR */
 
 # include "prcvar.h"
 # include "prinit.h"
 # include "prlock.h"
 # include "prthread.h"
 
 #endif
 
-#else  /* JS_THREADSAFE */
-
-typedef struct PRThread PRThread;
-typedef struct PRCondVar PRCondVar;
-typedef struct PRLock PRLock;
-
-#endif /* JS_THREADSAFE */
-
 #endif /* jslock_h */
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -139,21 +139,17 @@ struct JSRuntime;
 struct JSSecurityCallbacks;
 struct JSStructuredCloneCallbacks;
 struct JSStructuredCloneReader;
 struct JSStructuredCloneWriter;
 class JS_PUBLIC_API(JSTracer);
 
 class JSFlatString;
 
-#ifdef JS_THREADSAFE
 typedef struct PRCallOnceType   JSCallOnceType;
-#else
-typedef bool                    JSCallOnceType;
-#endif
 typedef bool                    (*JSInitCallback)(void);
 
 /*
  * Generic trace operation that calls JS_CallTracer on each traceable thing
  * stored in data.
  */
 typedef void
 (* JSTraceDataOp)(JSTracer *trc, void *data);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1644,24 +1644,20 @@ ScriptSource::setSourceCopy(ExclusiveCon
     // helper threads:
     //  - If we are on a helper thread, there must be another helper thread to
     //    execute our compression task.
     //  - If we are on the main thread, there must be at least two helper
     //    threads since at most one helper thread can be blocking on the main
     //    thread (see HelperThreadState::canStartParseTask) which would cause a
     //    deadlock if there wasn't a second helper thread that could make
     //    progress on our compression task.
-#if defined(JS_THREADSAFE)
     bool canCompressOffThread =
         HelperThreadState().cpuCount > 1 &&
         HelperThreadState().threadCount >= 2 &&
         CanUseExtraThreads();
-#else
-    bool canCompressOffThread = false;
-#endif
     const size_t TINY_SCRIPT = 256;
     const size_t HUGE_SCRIPT = 5 * 1024 * 1024;
     if (TINY_SCRIPT <= srcBuf.length() && srcBuf.length() < HUGE_SCRIPT && canCompressOffThread) {
         task->ss = this;
         if (!StartOffThreadCompression(cx, task))
             return false;
     } else if (!ensureOwnsSource(cx)) {
         return false;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -9,19 +9,17 @@
 #ifndef jsscript_h
 #define jsscript_h
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/UniquePtr.h"
 
 #include "jsatom.h"
-#ifdef JS_THREADSAFE
 #include "jslock.h"
-#endif
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jstypes.h"
 
 #include "gc/Barrier.h"
 #include "gc/Rooting.h"
 #include "jit/IonCode.h"
 #include "vm/Shape.h"
--- a/js/src/prmjtime.cpp
+++ b/js/src/prmjtime.cpp
@@ -28,19 +28,17 @@
 #if _MSC_VER >= 1400
 #define NS_HAVE_INVALID_PARAMETER_HANDLER 1
 #endif
 #ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
 #include <crtdbg.h>   /* for _CrtSetReportMode */
 #include <stdlib.h>   /* for _set_invalid_parameter_handler */
 #endif
 
-#ifdef JS_THREADSAFE
 #include "prinit.h"
-#endif
 
 #endif
 
 #ifdef XP_UNIX
 
 #ifdef _SVID_GETTOD   /* Defined only on Solaris, see Solaris <sys/types.h> */
 extern int gettimeofday(struct timeval *tv);
 #endif
@@ -86,19 +84,17 @@ FileTimeToUnixMicroseconds(const FILETIM
 
 struct CalibrationData {
     double freq;         /* The performance counter frequency */
     double offset;       /* The low res 'epoch' */
     double timer_offset; /* The high res 'epoch' */
 
     bool calibrated;
 
-#ifdef JS_THREADSAFE
     CRITICAL_SECTION data_lock;
-#endif
 };
 
 static CalibrationData calibration = { 0 };
 
 static void
 NowCalibrate()
 {
     MOZ_ASSERT(calibration.freq > 0);
@@ -135,46 +131,35 @@ PRMJ_NowInit()
     // Windows XP or later. Also, the frequency is fixed so we only have to
     // query it once.
     LARGE_INTEGER liFreq;
     DebugOnly<BOOL> res = QueryPerformanceFrequency(&liFreq);
     MOZ_ASSERT(res);
     calibration.freq = double(liFreq.QuadPart);
     MOZ_ASSERT(calibration.freq > 0.0);
 
-#ifdef JS_THREADSAFE
     InitializeCriticalSectionAndSpinCount(&calibration.data_lock, DataLockSpinCount);
-#endif
 
     // Windows 8 has a new API function we can use.
     if (HMODULE h = GetModuleHandle("kernel32.dll")) {
         pGetSystemTimePreciseAsFileTime =
             (void (WINAPI *)(LPFILETIME))GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
     }
 }
 
-#ifdef JS_THREADSAFE
 void
 PRMJ_NowShutdown()
 {
     DeleteCriticalSection(&calibration.data_lock);
 }
 
 #define MUTEX_LOCK(m) EnterCriticalSection(m)
 #define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
 #define MUTEX_SETSPINCOUNT(m, c) SetCriticalSectionSpinCount((m),(c))
 
-#else
-
-#define MUTEX_LOCK(m)
-#define MUTEX_UNLOCK(m)
-#define MUTEX_SETSPINCOUNT(m, c)
-
-#endif
-
 // Please see bug 363258 for why the win32 timing code is so complex.
 int64_t
 PRMJ_Now()
 {
     if (pGetSystemTimePreciseAsFileTime) {
         // Windows 8 has a new API function that does all the work.
         FILETIME ft;
         pGetSystemTimePreciseAsFileTime(&ft);
--- a/js/src/prmjtime.h
+++ b/js/src/prmjtime.h
@@ -39,17 +39,17 @@ PRMJ_Now();
 extern void
 PRMJ_NowInit();
 #else
 inline void
 PRMJ_NowInit() {}
 #endif
 
 /* Release the resources associated with PRMJ_Now; don't call PRMJ_Now again */
-#if defined(JS_THREADSAFE) && defined(XP_WIN)
+#ifdef XP_WIN
 extern void
 PRMJ_NowShutdown();
 #else
 inline void
 PRMJ_NowShutdown() {}
 #endif
 
 /* Format a time value into a buffer. Same semantics as strftime() */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -35,19 +35,17 @@
 # include <unistd.h>
 #endif
 
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jsfun.h"
-#ifdef JS_THREADSAFE
 #include "jslock.h"
-#endif
 #include "jsobj.h"
 #include "jsprf.h"
 #include "jsscript.h"
 #include "jstypes.h"
 #include "jsutil.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
@@ -144,32 +142,24 @@ static bool
 ScheduleWatchdog(JSRuntime *rt, double t);
 
 static void
 CancelExecution(JSRuntime *rt);
 
 /*
  * Watchdog thread state.
  */
-#ifdef JS_THREADSAFE
-
 static PRLock *gWatchdogLock = nullptr;
 static PRCondVar *gWatchdogWakeup = nullptr;
 static PRThread *gWatchdogThread = nullptr;
 static bool gWatchdogHasTimeout = false;
 static int64_t gWatchdogTimeout = 0;
 
 static PRCondVar *gSleepWakeup = nullptr;
 
-#else
-
-static JSRuntime *gRuntime = nullptr;
-
-#endif
-
 static int gExitCode = 0;
 static bool gQuitting = false;
 static bool gGotError = false;
 static FILE *gErrFile = nullptr;
 static FILE *gOutFile = nullptr;
 
 static bool reportWarnings = true;
 static bool compileOnly = false;
@@ -2790,17 +2780,16 @@ EvalInFrame(JSContext *cx, unsigned argc
     bool ok = !!frame.evaluateUCInStackFrame(cx, chars.start().get(), chars.length(),
                                              fpscript->filename(),
                                              JS_PCToLineNumber(cx, fpscript,
                                                                fi.pc()),
                                              MutableHandleValue::fromMarkedLocation(vp));
     return ok;
 }
 
-#ifdef JS_THREADSAFE
 struct WorkerInput
 {
     JSRuntime *runtime;
     jschar *chars;
     size_t length;
 
     WorkerInput(JSRuntime *runtime, jschar *chars, size_t length)
       : runtime(runtime), chars(chars), length(length)
@@ -2889,17 +2878,16 @@ EvalInWorker(JSContext *cx, unsigned arg
 
     PRThread *thread = PR_CreateThread(PR_USER_THREAD, WorkerMain, input,
                                        PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
     if (!thread || !workerThreads.append(thread))
         return false;
 
     return true;
 }
-#endif
 
 static bool
 ShapeOf(JSContext *cx, unsigned argc, JS::Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (!args.get(0).isObject()) {
         JS_ReportError(cx, "shapeOf: object expected");
         return false;
@@ -3030,18 +3018,16 @@ Resolver(JSContext *cx, unsigned argc, j
     if (!result)
         return false;
 
     JS_SetReservedSlot(result, 0, ObjectValue(*referent));
     args.rval().setObject(*result);
     return true;
 }
 
-#ifdef JS_THREADSAFE
-
 /*
  * Check that t1 comes strictly before t2. The function correctly deals with
  * wrap-around between t2 and t1 assuming that t2 and t1 stays within INT32_MAX
  * from each other. We use MAX_TIMEOUT_INTERVAL to enforce this restriction.
  */
 static bool
 IsBefore(int64_t t1, int64_t t2)
 {
@@ -3199,100 +3185,25 @@ ScheduleWatchdog(JSRuntime *rt, double t
          PR_NotifyCondVar(gWatchdogWakeup);
     }
     gWatchdogHasTimeout = true;
     gWatchdogTimeout = timeout;
     PR_Unlock(gWatchdogLock);
     return true;
 }
 
-#else /* !JS_THREADSAFE */
-
-#ifdef XP_WIN
-static HANDLE gTimerHandle = 0;
-
-VOID CALLBACK
-TimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
-{
-    CancelExecution((JSRuntime *) lpParameter);
-}
-
-#else
-
-static void
-AlarmHandler(int sig)
-{
-    CancelExecution(gRuntime);
-}
-
-#endif
-
-static bool
-InitWatchdog(JSRuntime *rt)
-{
-    gRuntime = rt;
-    return true;
-}
-
-static void
-KillWatchdog()
-{
-    ScheduleWatchdog(gRuntime, -1);
-}
-
-static bool
-ScheduleWatchdog(JSRuntime *rt, double t)
-{
-#ifdef XP_WIN
-    if (gTimerHandle) {
-        DeleteTimerQueueTimer(nullptr, gTimerHandle, nullptr);
-        gTimerHandle = 0;
-    }
-    if (t > 0 &&
-        !CreateTimerQueueTimer(&gTimerHandle,
-                               nullptr,
-                               (WAITORTIMERCALLBACK)TimerCallback,
-                               rt,
-                               DWORD(ceil(t * 1000.0)),
-                               0,
-                               WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE)) {
-        gTimerHandle = 0;
-        return false;
-    }
-#else
-    /* FIXME: use setitimer when available for sub-second resolution. */
-    if (t <= 0) {
-        alarm(0);
-        signal(SIGALRM, nullptr);
-    } else {
-        signal(SIGALRM, AlarmHandler); /* set the Alarm signal capture */
-        alarm(ceil(t));
-    }
-#endif
-    return true;
-}
-
-#endif /* !JS_THREADSAFE */
-
 static void
 CancelExecution(JSRuntime *rt)
 {
     gServiceInterrupt = true;
     JS_RequestInterruptCallback(rt);
 
     if (!gInterruptFunc.ref().get().isNull()) {
         static const char msg[] = "Script runs for too long, terminating.\n";
-#if defined(XP_UNIX) && !defined(JS_THREADSAFE)
-        /* It is not safe to call fputs from signals. */
-        /* Dummy assignment avoids GCC warning on "attribute warn_unused_result" */
-        ssize_t dummy = write(2, msg, sizeof(msg) - 1);
-        (void)dummy;
-#else
         fputs(msg, stderr);
-#endif
     }
 }
 
 static bool
 SetTimeoutValue(JSContext *cx, double t)
 {
     /* NB: The next condition also filter out NaNs. */
     if (!(t <= MAX_TIMEOUT_INTERVAL)) {
@@ -3583,18 +3494,16 @@ SyntaxParse(JSContext *cx, unsigned argc
         JS_ASSERT(cx->runtime()->hadOutOfMemory);
         return false;
     }
 
     args.rval().setBoolean(succeeded);
     return true;
 }
 
-#ifdef JS_THREADSAFE
-
 class OffThreadState {
   public:
     enum State {
         IDLE,           /* ready to work; no token, no source */
         COMPILING,      /* working; no token, have source */
         DONE            /* compilation done: have token and source */
     };
 
@@ -3777,18 +3686,16 @@ runOffThreadScript(JSContext *cx, unsign
 
     RootedScript script(cx, JS::FinishOffThreadScript(cx, cx->runtime(), token));
     if (!script)
         return false;
 
     return JS_ExecuteScript(cx, cx->global(), script, args.rval());
 }
 
-#endif // JS_THREADSAFE
-
 struct FreeOnReturn
 {
     JSContext *cx;
     const char *ptr;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     explicit FreeOnReturn(JSContext *cx, const char *ptr = nullptr
                  MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@@ -4702,42 +4609,38 @@ static const JSFunctionSpecWithHelp shel
 "  if (s == '' && !o) return new o with eager standard classes\n"
 "  if (s == 'lazy' && !o) return new o with lazy standard classes"),
 
     JS_FN_HELP("evalInFrame", EvalInFrame, 2, 0,
 "evalInFrame(n,str,save)",
 "  Evaluate 'str' in the nth up frame.\n"
 "  If 'save' (default false), save the frame chain."),
 
-#ifdef JS_THREADSAFE
     JS_FN_HELP("evalInWorker", EvalInWorker, 1, 0,
 "evalInWorker(str)",
 "  Evaluate 'str' in a separate thread with its own runtime.\n"),
-#endif
 
     JS_FN_HELP("shapeOf", ShapeOf, 1, 0,
 "shapeOf(obj)",
 "  Get the shape of obj (an implementation detail)."),
 
     JS_FN_HELP("resolver", Resolver, 1, 0,
 "resolver(src[, proto])",
 "  Create object with resolve hook that copies properties\n"
 "  from src. If proto is omitted, use Object.prototype."),
 
 #ifdef DEBUG
     JS_FN_HELP("arrayInfo", js_ArrayInfo, 1, 0,
 "arrayInfo(a1, a2, ...)",
 "  Report statistics about arrays."),
 #endif
 
-#ifdef JS_THREADSAFE
     JS_FN_HELP("sleep", Sleep_fn, 1, 0,
 "sleep(dt)",
 "  Sleep for dt seconds."),
-#endif
 
     JS_FN_HELP("snarf", Snarf, 1, 0,
 "snarf(filename, [\"binary\"])",
 "  Read filename into returned string. Filename is relative to the current\n"
                "  working directory."),
 
     JS_FN_HELP("read", Snarf, 1, 0,
 "read(filename, [\"binary\"])",
@@ -4755,17 +4658,16 @@ static const JSFunctionSpecWithHelp shel
     JS_FN_HELP("parse", Parse, 1, 0,
 "parse(code)",
 "  Parses a string, potentially throwing."),
 
     JS_FN_HELP("syntaxParse", SyntaxParse, 1, 0,
 "syntaxParse(code)",
 "  Check the syntax of a string, returning success value"),
 
-#ifdef JS_THREADSAFE
     JS_FN_HELP("offThreadCompileScript", OffThreadCompileScript, 1, 0,
 "offThreadCompileScript(code[, options])",
 "  Compile |code| on a helper thread. To wait for the compilation to finish\n"
 "  and run the code, call |runOffThreadScript|. If present, |options| may\n"
 "  have properties saying how the code should be compiled:\n"
 "      noScriptRval: use the no-script-rval compiler option (default: false)\n"
 "      fileName: filename for error messages and debug info\n"
 "      lineNumber: starting line number for error messages and debug info\n"
@@ -4778,18 +4680,16 @@ static const JSFunctionSpecWithHelp shel
 "         Debugger.Source.prototype.elementAttributeName returns.\n"),
 
     JS_FN_HELP("runOffThreadScript", runOffThreadScript, 0, 0,
 "runOffThreadScript()",
 "  Wait for off-thread compilation to complete. If an error occurred,\n"
 "  throw the appropriate exception; otherwise, run the script and return\n"
 "  its value."),
 
-#endif
-
     JS_FN_HELP("timeout", Timeout, 1, 0,
 "timeout([seconds], [func])",
 "  Get/Set the limit in seconds for the execution time for the current context.\n"
 "  A negative value (default) means that the execution time is unlimited.\n"
 "  If a second argument is provided, it will be invoked when the timer elapses.\n"
 "  Calling this function will replace any callback set by |setInterruptCallback|.\n"),
 
     JS_FN_HELP("interruptIf", InterruptIf, 1, 0,
@@ -5737,41 +5637,20 @@ ShellBuildId(JS::BuildIdCharVector *buil
 static JS::AsmJSCacheOps asmJSCacheOps = {
     ShellOpenAsmJSCacheEntryForRead,
     ShellCloseAsmJSCacheEntryForRead,
     ShellOpenAsmJSCacheEntryForWrite,
     ShellCloseAsmJSCacheEntryForWrite,
     ShellBuildId
 };
 
-/*
- * Avoid a reentrancy hazard.
- *
- * The non-JS_THREADSAFE shell uses a signal handler to implement timeout().
- * The JS engine is not really reentrant, but JS_RequestInterruptCallback
- * is mostly safe--the only danger is that we might interrupt JS_NewContext or
- * JS_DestroyContext while the context list is being modified. Therefore we
- * disable the signal handler around calls to those functions.
- */
-#ifdef JS_THREADSAFE
-# define WITH_SIGNALS_DISABLED(x)  x
-#else
-# define WITH_SIGNALS_DISABLED(x)                                               \
-    JS_BEGIN_MACRO                                                              \
-        ScheduleWatchdog(gRuntime, -1);                                         \
-        x;                                                                      \
-        ScheduleWatchdog(gRuntime, gTimeoutInterval);                           \
-    JS_END_MACRO
-#endif
-
 static JSContext *
 NewContext(JSRuntime *rt)
 {
-    JSContext *cx;
-    WITH_SIGNALS_DISABLED(cx = JS_NewContext(rt, gStackChunkSize));
+    JSContext *cx = JS_NewContext(rt, gStackChunkSize);
     if (!cx)
         return nullptr;
 
     JSShellContextData *data = NewContextData();
     if (!data) {
         DestroyContext(cx, false);
         return nullptr;
     }
@@ -5785,17 +5664,17 @@ static void
 DestroyContext(JSContext *cx, bool withGC)
 {
     // Don't use GetContextData as |data| could be a nullptr in the case of
     // destroying a context precisely because we couldn't create its private
     // data.
     JSShellContextData *data = (JSShellContextData *) JS_GetContextPrivate(cx);
     JS_SetContextPrivate(cx, nullptr);
     free(data);
-    WITH_SIGNALS_DISABLED(withGC ? JS_DestroyContext(cx) : JS_DestroyContextNoGC(cx));
+    withGC ? JS_DestroyContext(cx) : JS_DestroyContextNoGC(cx);
 }
 
 static JSObject *
 NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options,
                 JSPrincipals *principals)
 {
     RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, principals,
                                              JS::DontFireOnNewGlobalHook, options));
@@ -6073,19 +5952,17 @@ SetRuntimeOptions(JSRuntime *rt, const O
 
     bool offthreadCompilation = true;
     if (const char *str = op.getStringOption("ion-offthread-compile")) {
         if (strcmp(str, "off") == 0)
             offthreadCompilation = false;
         else if (strcmp(str, "on") != 0)
             return OptionFailure("ion-offthread-compile", str);
     }
-#ifdef JS_THREADSAFE
     rt->setOffthreadIonCompilationEnabled(offthreadCompilation);
-#endif
 
     if (op.getStringOption("ion-parallel-compile")) {
         fprintf(stderr, "--ion-parallel-compile is deprecated. Please use --ion-offthread-compile instead.\n");
         return false;
     }
 
 #endif // JS_ION
 
@@ -6253,20 +6130,18 @@ main(int argc, char **argv, char **envp)
                                "parallel.")
 #ifdef DEBUG
         || !op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit")
 #endif
         || !op.addOptionalStringArg("script", "A script to execute (after all options)")
         || !op.addOptionalMultiStringArg("scriptArgs",
                                          "String arguments to bind as |scriptArgs| in the "
                                          "shell's global")
-#ifdef JS_THREADSAFE
         || !op.addIntOption('\0', "thread-count", "COUNT", "Use COUNT auxiliary threads "
                             "(default: # of cores - 1)", -1)
-#endif
         || !op.addBoolOption('\0', "ion", "Enable IonMonkey (default)")
         || !op.addBoolOption('\0', "no-ion", "Disable IonMonkey")
         || !op.addBoolOption('\0', "no-asmjs", "Disable asm.js compilation")
         || !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
         || !op.addStringOption('\0', "ion-scalar-replacement", "on/off",
                                "Scalar Replacement (default: off, on to enable)")
         || !op.addStringOption('\0', "ion-gvn", "[mode]",
                                "Specify Ion global value numbering:\n"
@@ -6393,23 +6268,21 @@ main(int argc, char **argv, char **envp)
     }
 #endif
 
 #endif // DEBUG
 
     if (op.getBoolOption("no-threads"))
         js::DisableExtraThreads();
 
-#ifdef JS_THREADSAFE
     // The fake thread count must be set before initializing the Runtime,
     // which spins up the thread pool.
     int32_t threadCount = op.getIntOption("thread-count");
     if (threadCount >= 0)
         SetFakeCPUCount(threadCount);
-#endif /* JS_THREADSAFE */
 
     // Start the engine.
     if (!JS_Init())
         return 1;
 
     size_t nurseryBytes = JS::DefaultNurseryBytes;
 #ifdef JSGC_GENERATIONAL
     nurseryBytes = op.getIntOption("nursery-size") * 1024L * 1024L;
@@ -6441,20 +6314,18 @@ main(int argc, char **argv, char **envp)
     JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks);
     JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
 
     JS_SetInterruptCallback(rt, ShellInterruptCallback);
     JS::SetAsmJSCacheOps(rt, &asmJSCacheOps);
 
     JS_SetNativeStackQuota(rt, gMaxStackSize);
 
-#ifdef JS_THREADSAFE
     if (!offThreadState.init())
         return 1;
-#endif
 
     if (!InitWatchdog(rt))
         return 1;
 
     cx = NewContext(rt);
     if (!cx)
         return 1;
 
@@ -6471,21 +6342,19 @@ main(int argc, char **argv, char **envp)
 #endif
 
     DestroyContext(cx, true);
 
     KillWatchdog();
 
     gInterruptFunc.destroy();
 
-#ifdef JS_THREADSAFE
     MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
     for (size_t i = 0; i < workerThreads.length(); i++)
         PR_JoinThread(workerThreads[i]);
-#endif
 
 #ifdef JSGC_GENERATIONAL
     if (!noggc.empty())
         noggc.destroy();
 #endif
 
     JS_DestroyRuntime(rt);
     JS_ShutDown();
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -14,48 +14,44 @@
 
 #include "mozilla/ThreadLocal.h"
 
 #include "jscntxt.h"
 #include "jslock.h"
 #include "jsprf.h"
 
 #include "builtin/TypedObject.h"
+#include "jit/BaselineJIT.h"
+#include "vm/Monitor.h"
 
-#ifdef JS_THREADSAFE
-# include "jit/BaselineJIT.h"
-# include "vm/Monitor.h"
-#endif
-
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
 # include "jit/JitCommon.h"
 # include "jit/RematerializedFrame.h"
 # ifdef FORKJOIN_SPEW
 #  include "jit/Ion.h"
 #  include "jit/JitCompartment.h"
 #  include "jit/MIR.h"
 #  include "jit/MIRGraph.h"
 # endif
-#endif // THREADSAFE && ION
+#endif // JS_ION
 
 #include "gc/ForkJoinNursery-inl.h"
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 using namespace js::parallel;
 using namespace js::jit;
 
 using mozilla::ThreadLocal;
 
 ///////////////////////////////////////////////////////////////////////////
 // Degenerate configurations
 //
-// When JS_THREADSAFE or JS_ION is not defined, we simply run the
-// |func| callback sequentially.  We also forego the feedback
-// altogether.
+// When JS_ION is not defined, we simply run the |func| callback
+// sequentially.  We also forego the feedback altogether.
 
 static bool
 ExecuteSequentially(JSContext *cx_, HandleValue funVal, uint16_t *sliceStart,
                     uint16_t sliceEnd);
 
 static bool
 ForkJoinSequentially(JSContext *cx, CallArgs &args)
 {
@@ -63,17 +59,17 @@ ForkJoinSequentially(JSContext *cx, Call
     uint16_t sliceStart = uint16_t(args[1].toInt32());
     uint16_t sliceEnd = uint16_t(args[2].toInt32());
     if (!ExecuteSequentially(cx, argZero, &sliceStart, sliceEnd))
         return false;
     MOZ_ASSERT(sliceStart == sliceEnd);
     return true;
 }
 
-#if !defined(JS_THREADSAFE) || !defined(JS_ION)
+#if !defined(JS_ION)
 bool
 js::ForkJoin(JSContext *cx, CallArgs &args)
 {
     return ForkJoinSequentially(cx, args);
 }
 
 JSContext *
 ForkJoinContext::acquireJSContext()
@@ -171,17 +167,17 @@ static bool
 intrinsic_ClearThreadLocalArenasPar(ForkJoinContext *cx, unsigned argc, Value *vp)
 {
     return true;
 }
 
 JS_JITINFO_NATIVE_PARALLEL(js::intrinsic_ClearThreadLocalArenasInfo,
                            intrinsic_ClearThreadLocalArenasPar);
 
-#endif // !JS_THREADSAFE || !JS_ION
+#endif // !JS_ION
 
 ///////////////////////////////////////////////////////////////////////////
 // All configurations
 //
 // Some code that is shared between degenerate and parallel configurations.
 
 static bool
 ExecuteSequentially(JSContext *cx, HandleValue funVal, uint16_t *sliceStart,
@@ -212,20 +208,20 @@ ForkJoinContext::initializeTls()
             return false;
     }
     return true;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Parallel configurations
 //
-// The remainder of this file is specific to cases where both
-// JS_THREADSAFE and JS_ION are enabled.
+// The remainder of this file is specific to cases where
+// JS_ION is enabled.
 
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
 
 ///////////////////////////////////////////////////////////////////////////
 // Class Declarations and Function Prototypes
 
 namespace js {
 
 // When writing tests, it is often useful to specify different modes
 // of operation.
@@ -2467,9 +2463,9 @@ intrinsic_ClearThreadLocalArenasPar(Fork
 {
     cx->allocator()->arenas.wipeDuringParallelExecution(cx->runtime());
     return true;
 }
 
 JS_JITINFO_NATIVE_PARALLEL(js::intrinsic_ClearThreadLocalArenasInfo,
                            intrinsic_ClearThreadLocalArenasPar);
 
-#endif // JS_THREADSAFE && JS_ION
+#endif // JS_ION
--- a/js/src/vm/ForkJoin.h
+++ b/js/src/vm/ForkJoin.h
@@ -518,33 +518,33 @@ class ForkJoinContext : public ThreadSaf
 // that want to access that data will also acquire the lock, which is
 // generally not the case. For example, the lock is used in the IC
 // code to allow us to atomically patch up the dispatch table, but we
 // must be aware that other threads may be reading from the table even
 // as we write to it (though they cannot be writing, since they must
 // hold the lock to write).
 class LockedJSContext
 {
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
     ForkJoinContext *cx_;
 #endif
     JSContext *jscx_;
 
   public:
     explicit LockedJSContext(ForkJoinContext *cx)
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
       : cx_(cx),
         jscx_(cx->acquireJSContext())
 #else
       : jscx_(nullptr)
 #endif
     { }
 
     ~LockedJSContext() {
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
         cx_->releaseJSContext();
 #endif
     }
 
     operator JSContext *() { return jscx_; }
     JSContext *operator->() { return jscx_; }
 };
 
@@ -586,17 +586,17 @@ enum ExecutionStatus {
 enum SpewChannel {
     SpewOps,
     SpewCompile,
     SpewBailouts,
     SpewGC,
     NumSpewChannels
 };
 
-#if defined(FORKJOIN_SPEW) && defined(JS_THREADSAFE) && defined(JS_ION)
+#if defined(FORKJOIN_SPEW) && defined(JS_ION)
 
 bool SpewEnabled(SpewChannel channel);
 void Spew(SpewChannel channel, const char *fmt, ...);
 void SpewVA(SpewChannel channel, const char *fmt, va_list args);
 void SpewBeginOp(JSContext *cx, const char *name);
 void SpewBailout(uint32_t count, HandleScript script, jsbytecode *pc,
                  ParallelBailoutCause cause);
 ExecutionStatus SpewEndOp(ExecutionStatus status);
@@ -614,17 +614,17 @@ static inline void SpewBailout(uint32_t 
                                jsbytecode *pc, ParallelBailoutCause cause) {}
 static inline ExecutionStatus SpewEndOp(ExecutionStatus status) { return status; }
 static inline void SpewBeginCompile(HandleScript script) { }
 #ifdef JS_ION
 static inline jit::MethodStatus SpewEndCompile(jit::MethodStatus status) { return status; }
 static inline void SpewMIR(jit::MDefinition *mir, const char *fmt, ...) { }
 #endif
 
-#endif // FORKJOIN_SPEW && JS_THREADSAFE && JS_ION
+#endif // FORKJOIN_SPEW && JS_ION
 
 } // namespace parallel
 } // namespace js
 
 /* static */ inline js::ForkJoinContext *
 js::ForkJoinContext::current()
 {
     return tlsForkJoinContext.get();
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -1,18 +1,16 @@
 /* -*- 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 "vm/HelperThreads.h"
 
-#ifdef JS_THREADSAFE
-
 #include "mozilla/DebugOnly.h"
 
 #include "jsnativestack.h"
 #include "prmjtime.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "jit/IonBuilder.h"
 #include "vm/Debugger.h"
@@ -1241,79 +1239,8 @@ HelperThread::threadLoop()
         else if (HelperThreadState().canStartCompressionTask())
             handleCompressionWorkload();
         else if (HelperThreadState().canStartGCHelperTask())
             handleGCHelperWorkload();
         else
             MOZ_CRASH("No task to perform");
     }
 }
-
-#else /* JS_THREADSAFE */
-
-using namespace js;
-
-#ifdef JS_ION
-
-bool
-js::StartOffThreadAsmJSCompile(ExclusiveContext *cx, AsmJSParallelTask *asmData)
-{
-    MOZ_CRASH("Off thread compilation not available in non-THREADSAFE builds");
-}
-
-bool
-js::StartOffThreadIonCompile(JSContext *cx, jit::IonBuilder *builder)
-{
-    MOZ_CRASH("Off thread compilation not available in non-THREADSAFE builds");
-}
-
-#endif // JS_ION
-
-void
-js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script)
-{
-}
-
-void
-js::CancelOffThreadParses(JSRuntime *rt)
-{
-}
-
-bool
-js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &options,
-                              const jschar *chars, size_t length,
-                              JS::OffThreadCompileCallback callback, void *callbackData)
-{
-    MOZ_CRASH("Off thread compilation not available in non-THREADSAFE builds");
-}
-
-bool
-js::StartOffThreadCompression(ExclusiveContext *cx, SourceCompressionTask *task)
-{
-    MOZ_CRASH("Off thread compression not available");
-}
-
-bool
-SourceCompressionTask::complete()
-{
-    JS_ASSERT(!ss);
-    return true;
-}
-
-frontend::CompileError &
-ExclusiveContext::addPendingCompileError()
-{
-    MOZ_CRASH("Off thread compilation not available.");
-}
-
-void
-ExclusiveContext::addPendingOverRecursed()
-{
-    MOZ_CRASH("Off thread compilation not available.");
-}
-
-void
-js::PauseCurrentHelperThread()
-{
-    MOZ_CRASH("Off thread compilation not available.");
-}
-
-#endif /* JS_THREADSAFE */
--- a/js/src/vm/HelperThreads.h
+++ b/js/src/vm/HelperThreads.h
@@ -26,18 +26,16 @@ namespace js {
 
 struct HelperThread;
 struct AsmJSParallelTask;
 struct ParseTask;
 namespace jit {
   class IonBuilder;
 }
 
-#ifdef JS_THREADSAFE
-
 // Per-process state for off thread work items.
 class GlobalHelperThreadState
 {
   public:
     // Number of CPUs to treat this machine as having when creating threads.
     // May be accessed without locking.
     size_t cpuCount;
 
@@ -98,19 +96,19 @@ class GlobalHelperThreadState
     GlobalHelperThreadState();
 
     void ensureInitialized();
     void finish();
 
     void lock();
     void unlock();
 
-# ifdef DEBUG
+#ifdef DEBUG
     bool isLocked();
-# endif
+#endif
 
     enum CondVar {
         // For notifying threads waiting for work that they may be able to make progress.
         CONSUMER,
 
         // For notifying threads doing work that they may be able to make progress.
         PRODUCER,
 
@@ -216,19 +214,19 @@ class GlobalHelperThreadState
 
   private:
 
     /*
      * Lock protecting all mutable shared state accessed by helper threads, and
      * used by all condition variables.
      */
     PRLock *helperLock;
-# ifdef DEBUG
+#ifdef DEBUG
     PRThread *lockOwner;
-# endif
+#endif
 
     /* Condvars for threads waiting/notifying each other. */
     PRCondVar *consumerWakeup;
     PRCondVar *producerWakeup;
     PRCondVar *pauseWakeup;
 
     PRCondVar *whichWakeup(CondVar which) {
         switch (which) {
@@ -304,18 +302,16 @@ struct HelperThread
     void handleParseWorkload();
     void handleCompressionWorkload();
     void handleGCHelperWorkload();
 
     static void ThreadMain(void *arg);
     void threadLoop();
 };
 
-#endif /* JS_THREADSAFE */
-
 /* Methods for interacting with helper threads. */
 
 // Initialize helper threads unless already initialized.
 void
 EnsureHelperThreadsInitialized(ExclusiveContext *cx);
 
 // This allows the JS shell to override GetCPUCount() when passed the
 // --thread-count=N option.
@@ -371,55 +367,43 @@ EnqueuePendingParseTasksAfterGC(JSRuntim
 /* Start a compression job for the specified token. */
 bool
 StartOffThreadCompression(ExclusiveContext *cx, SourceCompressionTask *task);
 
 class AutoLockHelperThreadState
 {
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
-#ifdef JS_THREADSAFE
   public:
     explicit AutoLockHelperThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         HelperThreadState().lock();
     }
 
     ~AutoLockHelperThreadState() {
         HelperThreadState().unlock();
     }
-#else
-  public:
-    AutoLockHelperThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
-    {
-        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-    }
-#endif
 };
 
 class AutoUnlockHelperThreadState
 {
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
   public:
 
     explicit AutoUnlockHelperThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-#ifdef JS_THREADSAFE
         HelperThreadState().unlock();
-#endif
     }
 
     ~AutoUnlockHelperThreadState()
     {
-#ifdef JS_THREADSAFE
         HelperThreadState().lock();
-#endif
     }
 };
 
 #ifdef JS_ION
 struct AsmJSParallelTask
 {
     JSRuntime *runtime;     // Associated runtime.
     LifoAlloc lifo;         // Provider of all heap memory used for compilation.
@@ -484,35 +468,31 @@ struct ParseTask
 
     bool runtimeMatches(JSRuntime *rt) {
         return exclusiveContextGlobal->runtimeFromAnyThread() == rt;
     }
 
     ~ParseTask();
 };
 
-#ifdef JS_THREADSAFE
 // Return whether, if a new parse task was started, it would need to wait for
 // an in-progress GC to complete before starting.
 extern bool
 OffThreadParsingMustWaitForGC(JSRuntime *rt);
-#endif
 
 // Compression tasks are allocated on the stack by their triggering thread,
 // which will block on the compression completing as the task goes out of scope
 // to ensure it completes at the required time.
 struct SourceCompressionTask
 {
     friend class ScriptSource;
     friend struct HelperThread;
 
-#ifdef JS_THREADSAFE
     // Thread performing the compression.
     HelperThread *helperThread;
-#endif
 
   private:
     // Context from the triggering thread. Don't use this off thread!
     ExclusiveContext *cx;
 
     ScriptSource *ss;
 
     // Atomic flag to indicate to a helper thread that it should abort
@@ -526,23 +506,19 @@ struct SourceCompressionTask
         Success
     } result;
     void *compressed;
     size_t compressedBytes;
     HashNumber compressedHash;
 
   public:
     explicit SourceCompressionTask(ExclusiveContext *cx)
-      : cx(cx), ss(nullptr), abort_(false),
+      : helperThread(nullptr), cx(cx), ss(nullptr), abort_(false),
         result(OOM), compressed(nullptr), compressedBytes(0), compressedHash(0)
-    {
-#ifdef JS_THREADSAFE
-        helperThread = nullptr;
-#endif
-    }
+    {}
 
     ~SourceCompressionTask()
     {
         complete();
     }
 
     ResultType work();
     bool complete();
--- a/js/src/vm/Monitor.cpp
+++ b/js/src/vm/Monitor.cpp
@@ -6,20 +6,18 @@
 
 #include "vm/Monitor.h"
 
 using namespace js;
 
 bool
 Monitor::init()
 {
-#ifdef JS_THREADSAFE
     lock_ = PR_NewLock();
     if (!lock_)
         return false;
 
     condVar_ = PR_NewCondVar(lock_);
     if (!condVar_)
         return false;
-#endif
 
     return true;
 }
--- a/js/src/vm/Monitor.h
+++ b/js/src/vm/Monitor.h
@@ -2,19 +2,17 @@
  * 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 vm_Monitor_h
 #define vm_Monitor_h
 
-#ifdef JS_THREADSAFE
 #include "mozilla/DebugOnly.h"
-#endif
 
 #include <stddef.h>
 
 #include "jslock.h"
 
 #include "js/Utility.h"
 
 namespace js {
@@ -35,128 +33,90 @@ class Monitor
 
   public:
     Monitor()
       : lock_(nullptr),
         condVar_(nullptr)
     { }
 
     ~Monitor() {
-#ifdef JS_THREADSAFE
         if (lock_)
             PR_DestroyLock(lock_);
         if (condVar_)
             PR_DestroyCondVar(condVar_);
-#endif
     }
 
     bool init();
 };
 
 class AutoLockMonitor
 {
   private:
-#ifdef JS_THREADSAFE
     Monitor &monitor;
-#endif
 
   public:
     explicit AutoLockMonitor(Monitor &monitor)
-#ifdef JS_THREADSAFE
       : monitor(monitor)
     {
         PR_Lock(monitor.lock_);
     }
-#else
-    {}
-#endif
 
     ~AutoLockMonitor() {
-#ifdef JS_THREADSAFE
         PR_Unlock(monitor.lock_);
-#endif
     }
 
     bool isFor(Monitor &other) const {
-#ifdef JS_THREADSAFE
         return monitor.lock_ == other.lock_;
-#else
-        return true;
-#endif
     }
 
     void wait(PRCondVar *condVar) {
-#ifdef JS_THREADSAFE
         mozilla::DebugOnly<PRStatus> status =
           PR_WaitCondVar(condVar, PR_INTERVAL_NO_TIMEOUT);
         MOZ_ASSERT(status == PR_SUCCESS);
-#endif
     }
 
     void wait() {
-#ifdef JS_THREADSAFE
         wait(monitor.condVar_);
-#endif
     }
 
     void notify(PRCondVar *condVar) {
-#ifdef JS_THREADSAFE
         mozilla::DebugOnly<PRStatus> status = PR_NotifyCondVar(condVar);
         MOZ_ASSERT(status == PR_SUCCESS);
-#endif
     }
 
     void notify() {
-#ifdef JS_THREADSAFE
         notify(monitor.condVar_);
-#endif
     }
 
     void notifyAll(PRCondVar *condVar) {
-#ifdef JS_THREADSAFE
         mozilla::DebugOnly<PRStatus> status = PR_NotifyAllCondVar(monitor.condVar_);
         MOZ_ASSERT(status == PR_SUCCESS);
-#endif
     }
 
     void notifyAll() {
-#ifdef JS_THREADSAFE
         notifyAll(monitor.condVar_);
-#endif
     }
 };
 
 class AutoUnlockMonitor
 {
   private:
-#ifdef JS_THREADSAFE
     Monitor &monitor;
-#endif
 
   public:
     explicit AutoUnlockMonitor(Monitor &monitor)
-#ifdef JS_THREADSAFE
       : monitor(monitor)
     {
         PR_Unlock(monitor.lock_);
     }
-#else
-    {}
-#endif
 
     ~AutoUnlockMonitor() {
-#ifdef JS_THREADSAFE
         PR_Lock(monitor.lock_);
-#endif
     }
 
     bool isFor(Monitor &other) const {
-#ifdef JS_THREADSAFE
         return monitor.lock_ == other.lock_;
-#else
-        return true;
-#endif
     }
 };
 
 } // namespace js
 
 #endif /* vm_Monitor_h */
--- a/js/src/vm/PosixNSPR.h
+++ b/js/src/vm/PosixNSPR.h
@@ -4,20 +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 vm_PosixNSPR_h
 #define vm_PosixNSPR_h
 
 #ifdef JS_POSIX_NSPR
 
-#ifndef JS_THREADSAFE
-#error "This file must not be included in non-threadsafe mode"
-#endif
-
 #include <pthread.h>
 #include <stdint.h>
 
 namespace nspr {
 class Thread;
 class Lock;
 class CondVar;
 };
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -52,22 +52,17 @@ using mozilla::NegativeInfinity;
 using mozilla::PodZero;
 using mozilla::PodArrayZero;
 using mozilla::PositiveInfinity;
 using mozilla::ThreadLocal;
 using JS::GenericNaN;
 using JS::DoubleNaNValue;
 
 /* static */ ThreadLocal<PerThreadData*> js::TlsPerThreadData;
-
-#ifdef JS_THREADSAFE
 /* static */ Atomic<size_t> JSRuntime::liveRuntimesCount;
-#else
-/* static */ size_t JSRuntime::liveRuntimesCount;
-#endif
 
 namespace js {
     bool gCanUseExtraThreads = true;
 };
 
 void
 js::DisableExtraThreads()
 {
@@ -132,58 +127,48 @@ JSRuntime::JSRuntime(JSRuntime *parentRu
   : JS::shadow::Runtime(
 #ifdef JSGC_GENERATIONAL
         &gc.storeBuffer
 #endif
     ),
     mainThread(this),
     parentRuntime(parentRuntime),
     interrupt(false),
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
     interruptPar(false),
 #endif
     handlingSignal(false),
     interruptCallback(nullptr),
-#ifdef JS_THREADSAFE
     interruptLock(nullptr),
     interruptLockOwner(nullptr),
     exclusiveAccessLock(nullptr),
     exclusiveAccessOwner(nullptr),
     mainThreadHasExclusiveAccess(false),
     numExclusiveThreads(0),
-#else
-    interruptLockTaken(false),
-#endif
     numCompartments(0),
     localeCallbacks(nullptr),
     defaultLocale(nullptr),
     defaultVersion_(JSVERSION_DEFAULT),
-#ifdef JS_THREADSAFE
     ownerThread_(nullptr),
-#endif
     tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     freeLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     execAlloc_(nullptr),
     jitRuntime_(nullptr),
     selfHostingGlobal_(nullptr),
     nativeStackBase(0),
     cxCallback(nullptr),
     destroyCompartmentCallback(nullptr),
     destroyZoneCallback(nullptr),
     sweepZoneCallback(nullptr),
     compartmentNameCallback(nullptr),
     activityCallback(nullptr),
     activityCallbackArg(nullptr),
-#ifdef JS_THREADSAFE
     requestDepth(0),
-# ifdef DEBUG
+#ifdef DEBUG
     checkRequestDepth(0),
-# endif
-#endif
-#ifdef DEBUG
     activeContext(nullptr),
 #endif
     gc(thisFromCtor()),
     gcInitialized(false),
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     simulatorRuntime_(nullptr),
 #endif
     scriptAndCountsVector(nullptr),
@@ -276,27 +261,25 @@ SignalBasedTriggersDisabled()
   // Don't bother trying to cache the getenv lookup; this should be called
   // infrequently.
   return !!getenv("JS_DISABLE_SLOW_SCRIPT_SIGNALS") || !!getenv("JS_NO_SIGNALS");
 }
 
 bool
 JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
 {
-#ifdef JS_THREADSAFE
     ownerThread_ = PR_GetCurrentThread();
 
     interruptLock = PR_NewLock();
     if (!interruptLock)
         return false;
 
     exclusiveAccessLock = PR_NewLock();
     if (!exclusiveAccessLock)
         return false;
-#endif
 
     if (!mainThread.init())
         return false;
 
     js::TlsPerThreadData.set(&mainThread);
 
     if (!threadPool.init())
         return false;
@@ -410,29 +393,27 @@ JSRuntime::~JSRuntime()
     }
 
     /*
      * Clear the self-hosted global and delete self-hosted classes *after*
      * GC, as finalizers for objects check for clasp->finalize during GC.
      */
     finishSelfHosting();
 
-#ifdef JS_THREADSAFE
     JS_ASSERT(!exclusiveAccessOwner);
     if (exclusiveAccessLock)
         PR_DestroyLock(exclusiveAccessLock);
 
     // Avoid bogus asserts during teardown.
     JS_ASSERT(!numExclusiveThreads);
     mainThreadHasExclusiveAccess = true;
 
     JS_ASSERT(!interruptLockOwner);
     if (interruptLock)
         PR_DestroyLock(interruptLock);
-#endif
 
     /*
      * Even though all objects in the compartment are dead, we may have keep
      * some filenames around because of gcKeepAtoms.
      */
     FreeScriptData(this);
 
 #ifdef DEBUG
@@ -474,19 +455,17 @@ JSRuntime::~JSRuntime()
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     js::jit::DestroySimulatorRuntime(simulatorRuntime_);
 #endif
 
     DebugOnly<size_t> oldCount = liveRuntimesCount--;
     JS_ASSERT(oldCount > 0);
 
-#ifdef JS_THREADSAFE
     js::TlsPerThreadData.set(nullptr);
-#endif
 }
 
 void
 NewObjectCache::clearNurseryObjects(JSRuntime *rt)
 {
 #ifdef JSGC_GENERATIONAL
     for (unsigned i = 0; i < mozilla::ArrayLength(entries); ++i) {
         Entry &e = entries[i];
@@ -579,19 +558,17 @@ JSRuntime::requestInterrupt(InterruptMod
      * into a weird state where interrupt is stuck at 0 but jitStackLimit is
      * MAXADDR.
      */
     mainThread.setJitStackLimit(-1);
 
     interrupt = true;
 
 #ifdef JS_ION
-#ifdef JS_THREADSAFE
     RequestInterruptForForkJoin(this, mode);
-#endif
 
     /*
      * asm.js and normal Ion code optionally use memory protection and signal
      * handlers to halt running code.
      */
     if (canUseSignalHandlers()) {
         RequestInterruptForAsmJSCode(this, mode);
         jit::RequestInterruptForIonCode(this, mode);
@@ -749,18 +726,16 @@ JSRuntime::onOutOfMemoryCanGC(void *p, s
 
 bool
 JSRuntime::activeGCInAtomsZone()
 {
     Zone *zone = atomsCompartment_->zone();
     return zone->needsBarrier() || zone->isGCScheduled() || zone->wasGCStarted();
 }
 
-#ifdef JS_THREADSAFE
-
 void
 JSRuntime::setUsedByExclusiveThread(Zone *zone)
 {
     JS_ASSERT(!zone->usedByExclusiveThread);
     zone->usedByExclusiveThread = true;
     numExclusiveThreads++;
 }
 
@@ -790,60 +765,40 @@ js::CurrentThreadCanAccessZone(Zone *zon
     }
 
     // Only zones in use by an exclusive thread can be used off the main thread
     // or outside of PJS. We don't keep track of which thread owns such zones
     // though, so this check is imperfect.
     return zone->usedByExclusiveThread;
 }
 
-#else // JS_THREADSAFE
-
-bool
-js::CurrentThreadCanAccessRuntime(JSRuntime *rt)
-{
-    return true;
-}
-
-bool
-js::CurrentThreadCanAccessZone(Zone *zone)
-{
-    return true;
-}
-
-#endif // JS_THREADSAFE
-
 #ifdef DEBUG
 
 void
 JSRuntime::assertCanLock(RuntimeLock which)
 {
-#ifdef JS_THREADSAFE
     // In the switch below, each case falls through to the one below it. None
     // of the runtime locks are reentrant, and when multiple locks are acquired
     // it must be done in the order below.
     switch (which) {
       case ExclusiveAccessLock:
         JS_ASSERT(exclusiveAccessOwner != PR_GetCurrentThread());
       case HelperThreadStateLock:
         JS_ASSERT(!HelperThreadState().isLocked());
       case InterruptLock:
         JS_ASSERT(!currentThreadOwnsInterruptLock());
       case GCLock:
         gc.assertCanLock();
         break;
       default:
         MOZ_CRASH();
     }
-#endif // JS_THREADSAFE
 }
 
 void
 js::AssertCurrentThreadCanLock(RuntimeLock which)
 {
-#ifdef JS_THREADSAFE
     PerThreadData *pt = TlsPerThreadData.get();
     if (pt && pt->runtime_)
         pt->runtime_->assertCanLock(which);
-#endif
 }
 
 #endif // DEBUG
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -715,17 +715,17 @@ struct JSRuntime : public JS::shadow::Ru
     JSRuntime *parentRuntime;
 
     /*
      * If true, we've been asked to call the interrupt callback as soon as
      * possible.
      */
     mozilla::Atomic<bool, mozilla::Relaxed> interrupt;
 
-#if defined(JS_THREADSAFE) && defined(JS_ION)
+#ifdef JS_ION
     /*
      * If non-zero, ForkJoin should service an interrupt. This is a separate
      * flag from |interrupt| because we cannot use the mprotect trick with PJS
      * code and ignore the TriggerCallbackAnyThreadDontStopIon trigger.
      */
     mozilla::Atomic<bool, mozilla::Relaxed> interruptPar;
 #endif
 
@@ -740,60 +740,42 @@ struct JSRuntime : public JS::shadow::Ru
     void assertCanLock(js::RuntimeLock which) {}
 #endif
 
   private:
     /*
      * Lock taken when triggering an interrupt from another thread.
      * Protects all data that is touched in this process.
      */
-#ifdef JS_THREADSAFE
     PRLock *interruptLock;
     PRThread *interruptLockOwner;
-#else
-    bool interruptLockTaken;
-#endif // JS_THREADSAFE
+
   public:
-
     class AutoLockForInterrupt {
         JSRuntime *rt;
       public:
         explicit AutoLockForInterrupt(JSRuntime *rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : rt(rt) {
             MOZ_GUARD_OBJECT_NOTIFIER_INIT;
             rt->assertCanLock(js::InterruptLock);
-#ifdef JS_THREADSAFE
             PR_Lock(rt->interruptLock);
             rt->interruptLockOwner = PR_GetCurrentThread();
-#else
-            rt->interruptLockTaken = true;
-#endif // JS_THREADSAFE
         }
         ~AutoLockForInterrupt() {
             JS_ASSERT(rt->currentThreadOwnsInterruptLock());
-#ifdef JS_THREADSAFE
             rt->interruptLockOwner = nullptr;
             PR_Unlock(rt->interruptLock);
-#else
-            rt->interruptLockTaken = false;
-#endif // JS_THREADSAFE
         }
 
         MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     };
 
     bool currentThreadOwnsInterruptLock() {
-#if defined(JS_THREADSAFE)
         return interruptLockOwner == PR_GetCurrentThread();
-#else
-        return interruptLockTaken;
-#endif
     }
 
-#ifdef JS_THREADSAFE
-
   private:
     /*
      * Lock taken when using per-runtime or per-zone data that could otherwise
      * be accessed simultaneously by both the main thread and another thread
      * with an ExclusiveContext.
      *
      * Locking this only occurs if there is actually a thread other than the
      * main thread with an ExclusiveContext which could access such data.
@@ -806,56 +788,44 @@ struct JSRuntime : public JS::shadow::Ru
     size_t numExclusiveThreads;
 
     friend class js::AutoLockForExclusiveAccess;
 
   public:
     void setUsedByExclusiveThread(JS::Zone *zone);
     void clearUsedByExclusiveThread(JS::Zone *zone);
 
-#endif // JS_THREADSAFE
-
 #ifdef DEBUG
     bool currentThreadHasExclusiveAccess() {
-#ifdef JS_THREADSAFE
         return (!numExclusiveThreads && mainThreadHasExclusiveAccess) ||
                exclusiveAccessOwner == PR_GetCurrentThread();
-#else
-        return true;
-#endif
     }
 #endif // DEBUG
 
     bool exclusiveThreadsPresent() const {
-#ifdef JS_THREADSAFE
         return numExclusiveThreads > 0;
-#else
-        return false;
-#endif
     }
 
     /* How many compartments there are across all zones. */
     size_t              numCompartments;
 
     /* Locale-specific callbacks for string conversion. */
     JSLocaleCallbacks *localeCallbacks;
 
     /* Default locale for Internationalization API */
     char *defaultLocale;
 
     /* Default JSVersion. */
     JSVersion defaultVersion_;
 
-#ifdef JS_THREADSAFE
   private:
     /* See comment for JS_AbortIfWrongThread in jsapi.h. */
     void *ownerThread_;
     friend bool js::CurrentThreadCanAccessRuntime(JSRuntime *rt);
   public:
-#endif
 
     /* Temporary arena pool used while compiling and decompiling. */
     static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
     js::LifoAlloc tempLifoAlloc;
 
     /*
      * Free LIFO blocks are transferred to this allocator before being freed on
      * the background GC thread.
@@ -965,26 +935,22 @@ struct JSRuntime : public JS::shadow::Ru
 
     /* Call this to get the name of a compartment. */
     JSCompartmentNameCallback compartmentNameCallback;
 
     js::ActivityCallback  activityCallback;
     void                 *activityCallbackArg;
     void triggerActivityCallback(bool active);
 
-#ifdef JS_THREADSAFE
     /* The request depth for this thread. */
     unsigned            requestDepth;
 
-# ifdef DEBUG
+#ifdef DEBUG
     unsigned            checkRequestDepth;
-# endif
-#endif
 
-#ifdef DEBUG
     /*
      * To help embedders enforce their invariants, we allow them to specify in
      * advance which JSContext should be passed to JSAPI calls. If this is set
      * to a non-null value, the assertSameCompartment machinery does double-
      * duty (in debug builds) to verify that it matches the cx being used.
      */
     JSContext          *activeContext;
 #endif
@@ -1312,21 +1278,17 @@ struct JSRuntime : public JS::shadow::Ru
 
     js::CTypesActivityCallback  ctypesActivityCallback;
 
     // Non-zero if this is a ForkJoin warmup execution.  See
     // js::ForkJoin() for more information.
     uint32_t forkJoinWarmup;
 
   private:
-#ifdef JS_THREADSAFE
     static mozilla::Atomic<size_t> liveRuntimesCount;
-#else
-    static size_t liveRuntimesCount;
-#endif
 
   public:
     static bool hasLiveRuntimes() {
         return liveRuntimesCount > 0;
     }
 
     JSRuntime(JSRuntime *parentRuntime);
     ~JSRuntime();
@@ -1390,31 +1352,23 @@ struct JSRuntime : public JS::shadow::Ru
   public:
 
     // Note: these values may be toggled dynamically (in response to about:config
     // prefs changing).
     void setOffthreadIonCompilationEnabled(bool value) {
         offthreadIonCompilationEnabled_ = value;
     }
     bool canUseOffthreadIonCompilation() const {
-#ifdef JS_THREADSAFE
         return offthreadIonCompilationEnabled_;
-#else
-        return false;
-#endif
     }
     void setParallelParsingEnabled(bool value) {
         parallelParsingEnabled_ = value;
     }
     bool canUseParallelParsing() const {
-#ifdef JS_THREADSAFE
         return parallelParsingEnabled_;
-#else
-        return false;
-#endif
     }
 
     const JS::RuntimeOptions &options() const {
         return options_;
     }
     JS::RuntimeOptions &options() {
         return options_;
     }
@@ -1735,25 +1689,25 @@ extern const JSSecurityCallbacks NullSec
 // Debugging RAII class which marks the current thread as performing an Ion
 // compilation, for use by CurrentThreadCan{Read,Write}CompilationData
 class AutoEnterIonCompilation
 {
   public:
     AutoEnterIonCompilation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
-#if defined(DEBUG) && defined(JS_THREADSAFE)
+#ifdef DEBUG
         PerThreadData *pt = js::TlsPerThreadData.get();
         JS_ASSERT(!pt->ionCompiling);
         pt->ionCompiling = true;
 #endif
     }
 
     ~AutoEnterIonCompilation() {
-#if defined(DEBUG) && defined(JS_THREADSAFE)
+#ifdef DEBUG
         PerThreadData *pt = js::TlsPerThreadData.get();
         JS_ASSERT(pt->ionCompiling);
         pt->ionCompiling = false;
 #endif
     }
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -30,34 +30,31 @@ SPSProfiler::SPSProfiler(JSRuntime *rt)
     eventMarker_(nullptr)
 {
     JS_ASSERT(rt != nullptr);
 }
 
 bool
 SPSProfiler::init()
 {
-#ifdef JS_THREADSAFE
     lock_ = PR_NewLock();
     if (lock_ == nullptr)
         return false;
-#endif
+
     return true;
 }
 
 SPSProfiler::~SPSProfiler()
 {
     if (strings.initialized()) {
         for (ProfileStringMap::Enum e(strings); !e.empty(); e.popFront())
             js_free(const_cast<char *>(e.front().value()));
     }
-#ifdef JS_THREADSAFE
     if (lock_)
         PR_DestroyLock(lock_);
-#endif
 }
 
 void
 SPSProfiler::setProfilingStack(ProfileEntry *stack, uint32_t *size, uint32_t max)
 {
     AutoSPSLock lock(lock_);
     JS_ASSERT_IF(size_ && *size_ != 0, !enabled());
     if (!strings.initialized())
--- a/js/src/vm/SPSProfiler.h
+++ b/js/src/vm/SPSProfiler.h
@@ -203,27 +203,23 @@ class SPSProfiler
 
 /*
  * This class is used to make sure the strings table
  * is only accessed on one thread at a time.
  */
 class AutoSPSLock
 {
   public:
-#ifdef JS_THREADSAFE
     explicit AutoSPSLock(PRLock *lock)
     {
         MOZ_ASSERT(lock, "Parameter should not be null!");
         lock_ = lock;
         PR_Lock(lock);
     }
     ~AutoSPSLock() { PR_Unlock(lock_); }
-#else
-    explicit AutoSPSLock(PRLock *) {}
-#endif
 
   private:
     PRLock *lock_;
 };
 
 inline size_t
 SPSProfiler::stringsCount()
 {
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -665,22 +665,18 @@ intrinsic_ParallelTestsShouldPass(JSCont
 /*
  * ShouldForceSequential(): Returns true if parallel ops should take
  * the sequential fallback path.
  */
 bool
 js::intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-#ifdef JS_THREADSAFE
     args.rval().setBoolean(cx->runtime()->forkJoinWarmup ||
                            InParallelSection());
-#else
-    args.rval().setBoolean(true);
-#endif
     return true;
 }
 
 bool
 js::intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setBoolean(false);
--- a/js/src/vm/ThreadPool.cpp
+++ b/js/src/vm/ThreadPool.cpp
@@ -125,35 +125,31 @@ ThreadPoolWorker::randomWorker()
     x ^= x << XORSHIFT_C;
     schedulerRNGState_ = x;
     return pool_->workers_[x % pool_->numWorkers()];
 }
 
 bool
 ThreadPoolWorker::start()
 {
-#ifndef JS_THREADSAFE
-    return false;
-#else
     if (isMainThread())
         return true;
 
     MOZ_ASSERT(state_ == CREATED);
 
     // Set state to active now, *before* the thread starts:
     state_ = ACTIVE;
 
     MOZ_ASSERT(CanUseExtraThreads());
 
     return PR_CreateThread(PR_USER_THREAD,
                            HelperThreadMain, this,
                            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
                            PR_UNJOINABLE_THREAD,
                            WORKER_THREAD_STACK_SIZE);
-#endif
 }
 
 #ifdef MOZ_NUWA_PROCESS
 extern "C" {
 MFBT_API bool IsNuwaProcess();
 MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg);
 }
 #endif
@@ -273,48 +269,40 @@ ThreadPool::ThreadPool(JSRuntime *rt)
     freeChunks_(nullptr)
 { }
 
 ThreadPool::~ThreadPool()
 {
     terminateWorkers();
     if (chunkLock_)
         clearChunkCache();
-#ifdef JS_THREADSAFE
     if (chunkLock_)
         PR_DestroyLock(chunkLock_);
     if (joinBarrier_)
         PR_DestroyCondVar(joinBarrier_);
-#endif
 }
 
 bool
 ThreadPool::init()
 {
-#ifdef JS_THREADSAFE
     if (!Monitor::init())
         return false;
     joinBarrier_ = PR_NewCondVar(lock_);
     if (!joinBarrier_)
         return false;
     chunkLock_ = PR_NewLock();
     if (!chunkLock_)
         return false;
-#endif
     return true;
 }
 
 uint32_t
 ThreadPool::numWorkers() const
 {
-#ifdef JS_THREADSAFE
     return HelperThreadState().cpuCount;
-#else
-    return 1;
-#endif
 }
 
 bool
 ThreadPool::workStealing() const
 {
 #ifdef DEBUG
     if (char *stealEnv = getenv("JS_THREADPOOL_STEAL"))
         return !!strtol(stealEnv, nullptr, 10);
@@ -329,17 +317,16 @@ bool
 ThreadPool::lazyStartWorkers(JSContext *cx)
 {
     // Starts the workers if they have not already been started.  If
     // something goes wrong, reports an error and ensures that all
     // partially started threads are terminated.  Therefore, upon exit
     // from this function, the workers array is either full (upon
     // success) or empty (upon failure).
 
-#ifdef JS_THREADSAFE
     if (!workers_.empty()) {
         MOZ_ASSERT(workers_.length() == numWorkers());
         return true;
     }
 
     // Allocate workers array and then start the worker threads.
     // Note that numWorkers() is the number of *desired* workers,
     // but workers_.length() is the number of *successfully
@@ -358,17 +345,16 @@ ThreadPool::lazyStartWorkers(JSContext *
         if (!workers_[workerId]->start()) {
             // Note: do not delete worker here because it has been
             // added to the array and hence will be deleted by
             // |terminateWorkersAndReportOOM()|.
             terminateWorkersAndReportOOM(cx);
             return false;
         }
     }
-#endif
 
     return true;
 }
 
 void
 ThreadPool::terminateWorkersAndReportOOM(JSContext *cx)
 {
     terminateWorkers();
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -713,49 +713,45 @@ TraceLogger::stopEvent()
 TraceLogging::TraceLogging()
 {
     initialized = false;
     enabled = false;
     mainThreadEnabled = true;
     offThreadEnabled = true;
     loggerId = 0;
 
-#ifdef JS_THREADSAFE
     lock = PR_NewLock();
     if (!lock)
         MOZ_CRASH();
-#endif // JS_THREADSAFE
 }
 
 TraceLogging::~TraceLogging()
 {
     if (out) {
         fprintf(out, "]");
         fclose(out);
         out = nullptr;
     }
 
     for (size_t i = 0; i < mainThreadLoggers.length(); i++)
         delete mainThreadLoggers[i];
 
     mainThreadLoggers.clear();
 
-#ifdef JS_THREADSAFE
     if (threadLoggers.initialized()) {
         for (ThreadLoggerHashMap::Range r = threadLoggers.all(); !r.empty(); r.popFront())
             delete r.front().value();
 
         threadLoggers.finish();
     }
 
     if (lock) {
         PR_DestroyLock(lock);
         lock = nullptr;
     }
-#endif // JS_THREADSAFE
 
     enabled = false;
 }
 
 static bool
 ContainsFlag(const char *str, const char *flag)
 {
     size_t flaglen = strlen(flag);
@@ -776,20 +772,18 @@ TraceLogging::lazyInit()
 
     initialized = true;
 
     out = fopen(TRACE_LOG_DIR "tl-data.json", "w");
     if (!out)
         return false;
     fprintf(out, "[");
 
-#ifdef JS_THREADSAFE
     if (!threadLoggers.init())
         return false;
-#endif // JS_THREADSAFE
 
     const char *env = getenv("TLLOG");
     if (!env)
         env = "";
 
     if (strstr(env, "help")) {
         fflush(nullptr);
         printf(
@@ -930,25 +924,20 @@ TraceLogging::forMainThread(PerThreadDat
     }
 
     return mainThread->traceLogger;
 }
 
 TraceLogger *
 js::TraceLoggerForCurrentThread()
 {
-#ifdef JS_THREADSAFE
     PRThread *thread = PR_GetCurrentThread();
     return traceLoggers.forThread(thread);
-#else
-    MOZ_CRASH("No threads supported. Use TraceLoggerForMainThread for the main thread.");
-#endif // JS_THREADSAFE
 }
 
-#ifdef JS_THREADSAFE
 TraceLogger *
 TraceLogging::forThread(PRThread *thread)
 {
     AutoTraceLoggingLock lock(this);
 
     if (!lazyInit())
         return nullptr;
 
@@ -965,17 +954,16 @@ TraceLogging::forThread(PRThread *thread
         return nullptr;
     }
 
     if (!offThreadEnabled)
         logger->disable();
 
     return logger;
 }
-#endif // JS_THREADSAFE
 
 TraceLogger *
 TraceLogging::create()
 {
     if (loggerId > 999) {
         fprintf(stderr, "TraceLogging: Can't create more than 999 different loggers.");
         return nullptr;
     }
--- a/js/src/vm/TraceLogging.h
+++ b/js/src/vm/TraceLogging.h
@@ -2,22 +2,20 @@
  * 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 TraceLogging_h
 #define TraceLogging_h
 
+#include "mozilla/GuardObjects.h"
+
 #include "jsalloc.h"
-#ifdef JS_THREADSAFE
-# include "jslock.h"
-#endif
-
-#include "mozilla/GuardObjects.h"
+#include "jslock.h"
 
 #include "js/HashTable.h"
 #include "js/TypeDecls.h"
 #include "js/Vector.h"
 
 struct JSRuntime;
 
 namespace JS {
@@ -465,50 +463,42 @@ class TraceLogger
 #endif
     }
 #endif
 };
 
 class TraceLogging
 {
 #ifdef JS_TRACE_LOGGING
-#ifdef JS_THREADSAFE
     typedef HashMap<PRThread *,
                     TraceLogger *,
                     PointerHasher<PRThread *, 3>,
                     SystemAllocPolicy> ThreadLoggerHashMap;
-#endif // JS_THREADSAFE
     typedef Vector<TraceLogger *, 1, js::SystemAllocPolicy > MainThreadLoggers;
 
     bool initialized;
     bool enabled;
     bool enabledTextIds[TraceLogger::LAST];
     bool mainThreadEnabled;
     bool offThreadEnabled;
-#ifdef JS_THREADSAFE
     ThreadLoggerHashMap threadLoggers;
-#endif // JS_THREADSAFE
     MainThreadLoggers mainThreadLoggers;
     uint32_t loggerId;
     FILE *out;
 
   public:
     uint64_t startupTime;
-#ifdef JS_THREADSAFE
     PRLock *lock;
-#endif // JS_THREADSAFE
 
     TraceLogging();
     ~TraceLogging();
 
     TraceLogger *forMainThread(JSRuntime *runtime);
     TraceLogger *forMainThread(jit::CompileRuntime *runtime);
-#ifdef JS_THREADSAFE
     TraceLogger *forThread(PRThread *thread);
-#endif // JS_THREADSAFE
 
     bool isTextIdEnabled(uint32_t textId) {
         if (textId < TraceLogger::LAST)
             return enabledTextIds[textId];
         return true;
     }
 
   private:
@@ -662,24 +652,20 @@ class AutoTraceLoggingLock
 {
   TraceLogging *logging;
 
   public:
     AutoTraceLoggingLock(TraceLogging *logging MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : logging(logging)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-#ifdef JS_THREADSAFE
         PR_Lock(logging->lock);
-#endif // JS_THREADSAFE
     }
     ~AutoTraceLoggingLock() {
-#ifdef JS_THREADSAFE
         PR_Unlock(logging->lock);
-#endif // JS_THREADSAFE
     }
   private:
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 #endif
 
 }  /* namedata js */
 
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -85,24 +85,16 @@ public:
 
 private:
     nsCOMPtr<nsIFile> mGREDir;
     nsCOMPtr<nsIFile> mAppDir;
     nsCOMPtr<nsIFile> mPluginDir;
     nsCOMPtr<nsIFile> mAppFile;
 };
 
-#ifdef JS_THREADSAFE
-#define DoBeginRequest(cx) JS_BeginRequest((cx))
-#define DoEndRequest(cx)   JS_EndRequest((cx))
-#else
-#define DoBeginRequest(cx) ((void)0)
-#define DoEndRequest(cx)   ((void)0)
-#endif
-
 static const char kXPConnectServiceContractID[] = "@mozilla.org/js/xpc/XPConnect;1";
 
 #define EXITCODE_RUNTIME_ERROR 3
 #define EXITCODE_FILE_NOT_FOUND 4
 
 static FILE *gOutFile = nullptr;
 static FILE *gErrFile = nullptr;
 static FILE *gInFile = nullptr;
@@ -915,25 +907,25 @@ ProcessFile(JSContext *cx, JS::Handle<JS
         int ch = fgetc(file);
         if (ch == '#') {
             while ((ch = fgetc(file)) != EOF) {
                 if (ch == '\n' || ch == '\r')
                     break;
             }
         }
         ungetc(ch, file);
-        DoBeginRequest(cx);
+        JS_BeginRequest(cx);
 
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename, 1)
                .setCompileAndGo(true);
         if (JS::Compile(cx, obj, options, file, &script) && !compileOnly)
             (void)JS_ExecuteScript(cx, obj, script, &result);
-        DoEndRequest(cx);
+        JS_EndRequest(cx);
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
     hitEOF = false;
     do {
@@ -951,17 +943,17 @@ ProcessFile(JSContext *cx, JS::Handle<JS
             if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
                 hitEOF = true;
                 break;
             }
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
-        DoBeginRequest(cx);
+        JS_BeginRequest(cx);
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         JS::CompileOptions options(cx);
         options.setFileAndLine("typein", startline)
                .setCompileAndGo(true);
         if (JS_CompileScript(cx, obj, buffer, strlen(buffer), options, &script)) {
             JSErrorReporter older;
 
@@ -975,17 +967,17 @@ ProcessFile(JSContext *cx, JS::Handle<JS
                     JSAutoByteString bytes;
                     if (str && bytes.encodeLatin1(cx, str))
                         fprintf(gOutFile, "%s\n", bytes.ptr());
                     else
                         ok = false;
                 }
             }
         }
-        DoEndRequest(cx);
+        JS_EndRequest(cx);
     } while (!hitEOF && !gQuitting);
 
     fprintf(gOutFile, "\n");
 }
 
 static void
 Process(JSContext *cx, JS::Handle<JSObject*> obj, const char *filename, bool forceTTY)
 {