diff --git a/js/src/gc/DeletePolicy.h b/js/src/gc/DeletePolicy.h new file mode 100644 index 000000000000..bfa21158dbba --- /dev/null +++ b/js/src/gc/DeletePolicy.h @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef gc_DeletePolicy_h +#define gc_DeletePolicy_h + +#include "js/TracingAPI.h" + +namespace js { +namespace gc { + +struct ClearEdgesTracer : public JS::CallbackTracer +{ + ClearEdgesTracer(); + +#ifdef DEBUG + TracerKind getTracerKind() const override { return TracerKind::ClearEdges; } +#endif + + template + inline void clearEdge(T** thingp); + + void onObjectEdge(JSObject** objp) override; + void onStringEdge(JSString** strp) override; + void onSymbolEdge(JS::Symbol** symp) override; + void onScriptEdge(JSScript** scriptp) override; + void onShapeEdge(js::Shape** shapep) override; + void onObjectGroupEdge(js::ObjectGroup** groupp) override; + void onBaseShapeEdge(js::BaseShape** basep) override; + void onJitCodeEdge(js::jit::JitCode** codep) override; + void onLazyScriptEdge(js::LazyScript** lazyp) override; + void onScopeEdge(js::Scope** scopep) override; + void onRegExpSharedEdge(js::RegExpShared** sharedp) override; + void onChild(const JS::GCCellPtr& thing) override; +}; + +#ifdef DEBUG +inline bool +IsClearEdgesTracer(JSTracer *trc) +{ + return trc->isCallbackTracer() && + trc->asCallbackTracer()->getTracerKind() == JS::CallbackTracer::TracerKind::ClearEdges; +} +#endif + +} // namespace gc + +/* + * Provides a delete policy that can be used for objects which have their + * lifetime managed by the GC so they can be safely destroyed outside of GC. + * + * This is necessary for example when initializing such an object may fail after + * the initial allocation. The partially-initialized object must be destroyed, + * but it may not be safe to do so at the current time as the store buffer may + * contain pointers into it. + * + * This policy traces GC pointers in the object and clears them, making sure to + * trigger barriers while doing so. This will remove any store buffer pointers + * into the object and make it safe to delete. + */ +template +struct GCManagedDeletePolicy +{ + void operator()(const T* constPtr) { + if (constPtr) { + auto ptr = const_cast(constPtr); + gc::ClearEdgesTracer trc; + ptr->trace(&trc); + js_delete(ptr); + } + } +}; + +} // namespace js + +#endif // gc_DeletePolicy_h diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 920fe69c9d93..5f86c4493522 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -9,21 +9,20 @@ #include "mozilla/Atomics.h" #include "mozilla/HashFunctions.h" -#include "mozilla/MemoryReporting.h" -#include "jscntxt.h" - -#include "ds/SplayTree.h" #include "gc/FindSCCs.h" #include "gc/GCRuntime.h" #include "js/GCHashTable.h" -#include "js/TracingAPI.h" #include "vm/MallocProvider.h" #include "vm/RegExpShared.h" -#include "vm/TypeInference.h" +#include "vm/Runtime.h" + +struct JSContext; namespace js { +class Debugger; + namespace jit { class JitZone; } // namespace jit @@ -987,92 +986,6 @@ ZoneAllocPolicy::pod_realloc(T* p, size_t oldSize, size_t newSize) return zone->pod_realloc(p, oldSize, newSize); } -/* - * Provides a delete policy that can be used for objects which have their - * lifetime managed by the GC so they can be safely destroyed outside of GC. - * - * This is necessary for example when initializing such an object may fail after - * the initial allocation. The partially-initialized object must be destroyed, - * but it may not be safe to do so at the current time as the store buffer may - * contain pointers into it. - * - * This policy traces GC pointers in the object and clears them, making sure to - * trigger barriers while doing so. This will remove any store buffer pointers - * into the object and make it safe to delete. - */ -template -struct GCManagedDeletePolicy -{ - struct ClearEdgesTracer : public JS::CallbackTracer - { - explicit ClearEdgesTracer(JSContext* cx) : CallbackTracer(cx, TraceWeakMapKeysValues) {} -#ifdef DEBUG - TracerKind getTracerKind() const override { return TracerKind::ClearEdges; } -#endif - - template - void clearEdge(S** thingp) { - InternalBarrierMethods::preBarrier(*thingp); - InternalBarrierMethods::postBarrier(thingp, *thingp, nullptr); - *thingp = nullptr; - } - - void onObjectEdge(JSObject** objp) override { clearEdge(objp); } - void onStringEdge(JSString** strp) override { clearEdge(strp); } - void onSymbolEdge(JS::Symbol** symp) override { clearEdge(symp); } - void onScriptEdge(JSScript** scriptp) override { clearEdge(scriptp); } - void onShapeEdge(js::Shape** shapep) override { clearEdge(shapep); } - void onObjectGroupEdge(js::ObjectGroup** groupp) override { clearEdge(groupp); } - void onBaseShapeEdge(js::BaseShape** basep) override { clearEdge(basep); } - void onJitCodeEdge(js::jit::JitCode** codep) override { clearEdge(codep); } - void onLazyScriptEdge(js::LazyScript** lazyp) override { clearEdge(lazyp); } - void onScopeEdge(js::Scope** scopep) override { clearEdge(scopep); } - void onRegExpSharedEdge(js::RegExpShared** sharedp) override { clearEdge(sharedp); } - void onChild(const JS::GCCellPtr& thing) override { MOZ_CRASH(); } - }; - - void operator()(const T* constPtr) { - if (constPtr) { - auto ptr = const_cast(constPtr); - ClearEdgesTracer trc(TlsContext.get()); - ptr->trace(&trc); - js_delete(ptr); - } - } -}; - -#ifdef DEBUG -inline bool -IsClearEdgesTracer(JSTracer *trc) -{ - return trc->isCallbackTracer() && - trc->asCallbackTracer()->getTracerKind() == JS::CallbackTracer::TracerKind::ClearEdges; -} -#endif - } // namespace js -namespace JS { - -// Scope data that contain GCPtrs must use the correct DeletePolicy. -// -// This is defined here because vm/Scope.h cannot #include "vm/Runtime.h" - -template <> -struct DeletePolicy - : public js::GCManagedDeletePolicy -{ }; - -template <> -struct DeletePolicy - : public js::GCManagedDeletePolicy -{ }; - -template <> -struct DeletePolicy - : public js::GCManagedDeletePolicy -{ }; - -} // namespace JS - #endif // gc_Zone_h diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index baa81591f3c3..e04e8c65a4ea 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -18,6 +18,7 @@ #include "js/Vector.h" #include "threading/ProtectedData.h" #include "vm/ErrorReporting.h" +#include "vm/MallocProvider.h" #include "vm/Runtime.h" #ifdef _MSC_VER diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 02dd5271b75e..54efd37bc983 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -9047,3 +9047,29 @@ js::gc::detail::CellIsNotGray(const Cell* cell) return false; } #endif + +js::gc::ClearEdgesTracer::ClearEdgesTracer() + : CallbackTracer(TlsContext.get(), TraceWeakMapKeysValues) +{} + +template +inline void +js::gc::ClearEdgesTracer::clearEdge(S** thingp) +{ + InternalBarrierMethods::preBarrier(*thingp); + InternalBarrierMethods::postBarrier(thingp, *thingp, nullptr); + *thingp = nullptr; +} + +void js::gc::ClearEdgesTracer::onObjectEdge(JSObject** objp) { clearEdge(objp); } +void js::gc::ClearEdgesTracer::onStringEdge(JSString** strp) { clearEdge(strp); } +void js::gc::ClearEdgesTracer::onSymbolEdge(JS::Symbol** symp) { clearEdge(symp); } +void js::gc::ClearEdgesTracer::onScriptEdge(JSScript** scriptp) { clearEdge(scriptp); } +void js::gc::ClearEdgesTracer::onShapeEdge(js::Shape** shapep) { clearEdge(shapep); } +void js::gc::ClearEdgesTracer::onObjectGroupEdge(js::ObjectGroup** groupp) { clearEdge(groupp); } +void js::gc::ClearEdgesTracer::onBaseShapeEdge(js::BaseShape** basep) { clearEdge(basep); } +void js::gc::ClearEdgesTracer::onJitCodeEdge(js::jit::JitCode** codep) { clearEdge(codep); } +void js::gc::ClearEdgesTracer::onLazyScriptEdge(js::LazyScript** lazyp) { clearEdge(lazyp); } +void js::gc::ClearEdgesTracer::onScopeEdge(js::Scope** scopep) { clearEdge(scopep); } +void js::gc::ClearEdgesTracer::onRegExpSharedEdge(js::RegExpShared** sharedp) { clearEdge(sharedp); } +void js::gc::ClearEdgesTracer::onChild(const JS::GCCellPtr& thing) { MOZ_CRASH(); } diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index c220af104bcd..8856c5f28044 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -14,6 +14,7 @@ #include "jsfriendapi.h" #include "jsobj.h" +#include "gc/DeletePolicy.h" #include "gc/StoreBuffer.h" #include "js/HashTable.h" diff --git a/js/src/vm/Scope.h b/js/src/vm/Scope.h index 0876da443f62..473f89aef587 100644 --- a/js/src/vm/Scope.h +++ b/js/src/vm/Scope.h @@ -13,6 +13,7 @@ #include "jsobj.h" #include "jsopcode.h" +#include "gc/DeletePolicy.h" #include "gc/Heap.h" #include "gc/Policy.h" #include "js/UbiNode.h" @@ -1538,6 +1539,23 @@ DEFINE_SCOPE_DATA_GCPOLICY(js::WasmFunctionScope::Data); #undef DEFINE_SCOPE_DATA_GCPOLICY +// Scope data that contain GCPtrs must use the correct DeletePolicy. + +template <> +struct DeletePolicy + : public js::GCManagedDeletePolicy +{}; + +template <> +struct DeletePolicy + : public js::GCManagedDeletePolicy +{}; + +template <> +struct DeletePolicy + : public js::GCManagedDeletePolicy +{ }; + namespace ubi { template <> diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h index 75224f813682..175c744d1de1 100644 --- a/js/src/vm/UnboxedObject.h +++ b/js/src/vm/UnboxedObject.h @@ -9,6 +9,7 @@ #include "jsobj.h" +#include "gc/DeletePolicy.h" #include "gc/Zone.h" #include "vm/Runtime.h" #include "vm/TypeInference.h"