Bug 1421319 - Split out GCManagedDeletePolicy into its own header r=sfink

This commit is contained in:
Jon Coppeard 2017-11-29 11:29:13 +00:00
Родитель 63739feac3
Коммит 295da27e19
7 изменённых файлов: 131 добавлений и 92 удалений

79
js/src/gc/DeletePolicy.h Normal file
Просмотреть файл

@ -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 <typename T>
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 <typename T>
struct GCManagedDeletePolicy
{
void operator()(const T* constPtr) {
if (constPtr) {
auto ptr = const_cast<T*>(constPtr);
gc::ClearEdgesTracer trc;
ptr->trace(&trc);
js_delete(ptr);
}
}
};
} // namespace js
#endif // gc_DeletePolicy_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<T>(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 <typename T>
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 <typename S>
void clearEdge(S** thingp) {
InternalBarrierMethods<S*>::preBarrier(*thingp);
InternalBarrierMethods<S*>::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<T*>(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<js::FunctionScope::Data>
: public js::GCManagedDeletePolicy<js::FunctionScope::Data>
{ };
template <>
struct DeletePolicy<js::ModuleScope::Data>
: public js::GCManagedDeletePolicy<js::ModuleScope::Data>
{ };
template <>
struct DeletePolicy<js::WasmInstanceScope::Data>
: public js::GCManagedDeletePolicy<js::WasmInstanceScope::Data>
{ };
} // namespace JS
#endif // gc_Zone_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

Просмотреть файл

@ -9047,3 +9047,29 @@ js::gc::detail::CellIsNotGray(const Cell* cell)
return false;
}
#endif
js::gc::ClearEdgesTracer::ClearEdgesTracer()
: CallbackTracer(TlsContext.get(), TraceWeakMapKeysValues)
{}
template <typename S>
inline void
js::gc::ClearEdgesTracer::clearEdge(S** thingp)
{
InternalBarrierMethods<S*>::preBarrier(*thingp);
InternalBarrierMethods<S*>::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(); }

Просмотреть файл

@ -14,6 +14,7 @@
#include "jsfriendapi.h"
#include "jsobj.h"
#include "gc/DeletePolicy.h"
#include "gc/StoreBuffer.h"
#include "js/HashTable.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<js::FunctionScope::Data>
: public js::GCManagedDeletePolicy<js::FunctionScope::Data>
{};
template <>
struct DeletePolicy<js::ModuleScope::Data>
: public js::GCManagedDeletePolicy<js::ModuleScope::Data>
{};
template <>
struct DeletePolicy<js::WasmInstanceScope::Data>
: public js::GCManagedDeletePolicy<js::WasmInstanceScope::Data>
{ };
namespace ubi {
template <>

Просмотреть файл

@ -9,6 +9,7 @@
#include "jsobj.h"
#include "gc/DeletePolicy.h"
#include "gc/Zone.h"
#include "vm/Runtime.h"
#include "vm/TypeInference.h"