/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * 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 "threading/ProtectedData.h" #include "gc/Zone.h" #include "vm/HelperThreads.h" #include "vm/JSContext.h" namespace js { #ifdef JS_HAS_PROTECTED_DATA_CHECKS /* static */ mozilla::Atomic AutoNoteSingleThreadedRegion::count(0); template static inline bool OnHelperThread() { if (Helper == AllowedHelperThread::IonCompile || Helper == AllowedHelperThread::GCTaskOrIonCompile) { if (CurrentThreadIsIonCompiling()) { return true; } } if (Helper == AllowedHelperThread::GCTask || Helper == AllowedHelperThread::GCTaskOrIonCompile) { JSContext* cx = TlsContext.get(); if (cx->defaultFreeOp()->isCollecting()) { return true; } } return false; } void CheckThreadLocal::check() const { JSContext* cx = TlsContext.get(); MOZ_ASSERT(cx); MOZ_ASSERT_IF(cx->isMainThreadContext(), CurrentThreadCanAccessRuntime(cx->runtime())); MOZ_ASSERT(id == ThreadId::ThisThreadId()); } void CheckContextLocal::check() const { if (!cx_->isInitialized()) { return; } JSContext* cx = TlsContext.get(); MOZ_ASSERT(cx); MOZ_ASSERT_IF(cx->isMainThreadContext(), CurrentThreadCanAccessRuntime(cx->runtime())); MOZ_ASSERT(cx_ == cx); } template void CheckMainThread::check() const { if (OnHelperThread()) { return; } JSContext* cx = TlsContext.get(); MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); } template class CheckMainThread; template class CheckMainThread; template class CheckMainThread; template void CheckZone::check() const { if (OnHelperThread()) { return; } if (zone->usedByHelperThread()) { // This may only be accessed by the helper thread using this zone. MOZ_ASSERT(zone->ownedByCurrentHelperThread()); } else { // The main thread is permitted access to all zones. These accesses // are threadsafe if the zone is not in use by a helper thread. MOZ_ASSERT(CurrentThreadCanAccessRuntime(TlsContext.get()->runtime())); } } template class CheckZone; template class CheckZone; template class CheckZone; template class CheckZone; template void CheckGlobalLock::check() const { if (OnHelperThread()) { return; } switch (Lock) { case GlobalLock::GCLock: TlsContext.get()->runtime()->gc.assertCurrentThreadHasLockedGC(); break; case GlobalLock::ScriptDataLock: TlsContext.get()->runtime()->assertCurrentThreadHasScriptDataAccess(); break; case GlobalLock::HelperThreadLock: gHelperThreadLock.assertOwnedByCurrentThread(); break; } } template class CheckGlobalLock; template class CheckGlobalLock; template class CheckGlobalLock; template void CheckArenaListAccess::check() const { MOZ_ASSERT(zone); if (OnHelperThread()) { return; } JSRuntime* rt = TlsContext.get()->runtime(); if (zone->isAtomsZone()) { // The main thread can access the atoms arenas if it holds all the atoms // table locks. if (rt->currentThreadHasAtomsTableAccess()) { return; } // Otherwise we must hold the GC lock if parallel parsing is running. if (rt->isOffThreadParseRunning()) { rt->gc.assertCurrentThreadHasLockedGC(); } return; } CheckZone::check(); } template class CheckArenaListAccess; #endif // JS_HAS_PROTECTED_DATA_CHECKS } // namespace js