Bug 1456494 - Initialize Zone::helperThreadUse_ first to avoid accessing uninitialized memory in debug builds. r=jonco

--HG--
extra : rebase_source : 9abb7cecd084e7f8c4bbe7ce1ff3e34c10e024ce
This commit is contained in:
Jan de Mooij 2018-04-26 09:57:15 +02:00
Родитель 37bc3aaed9
Коммит 4da56c6d15
2 изменённых файлов: 43 добавлений и 45 удалений

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

@ -26,6 +26,10 @@ Zone * const Zone::NotOnList = reinterpret_cast<Zone*>(1);
JS::Zone::Zone(JSRuntime* rt)
: JS::shadow::Zone(rt, &rt->gc.marker),
// Note: don't use |this| before initializing helperThreadUse_!
// ProtectedData checks in CheckZone::check may read this field.
helperThreadUse_(HelperThreadUse::None),
helperThreadOwnerContext_(nullptr),
debuggers(this, nullptr),
uniqueIds_(this),
suppressAllocationMetadataBuilder(this, false),
@ -54,8 +58,6 @@ JS::Zone::Zone(JSRuntime* rt)
nurseryShapes_(this),
data(this, nullptr),
isSystem(this, false),
helperThreadOwnerContext_(nullptr),
helperThreadUse(HelperThreadUse::None),
#ifdef DEBUG
gcLastSweepGroupIndex(this, 0),
#endif
@ -78,7 +80,7 @@ JS::Zone::Zone(JSRuntime* rt)
Zone::~Zone()
{
MOZ_ASSERT(helperThreadUse == HelperThreadUse::None);
MOZ_ASSERT(helperThreadUse_ == HelperThreadUse::None);
JSRuntime* rt = runtimeFromAnyThread();
if (this == rt->gc.systemZone)

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

@ -151,6 +151,44 @@ struct Zone : public JS::shadow::Zone,
MOZ_MUST_USE bool init(bool isSystem);
void destroy(js::FreeOp *fop);
private:
enum class HelperThreadUse : uint32_t {
None,
Pending,
Active
};
mozilla::Atomic<HelperThreadUse> helperThreadUse_;
// The helper thread context with exclusive access to this zone, if
// usedByHelperThread(), or nullptr when on the main thread.
js::UnprotectedData<JSContext*> helperThreadOwnerContext_;
public:
bool ownedByCurrentHelperThread();
void setHelperThreadOwnerContext(JSContext* cx);
// Whether this zone was created for use by a helper thread.
bool createdForHelperThread() const {
return helperThreadUse_ != HelperThreadUse::None;
}
// Whether this zone is currently in use by a helper thread.
bool usedByHelperThread() {
MOZ_ASSERT_IF(isAtomsZone(), helperThreadUse_ == HelperThreadUse::None);
return helperThreadUse_ == HelperThreadUse::Active;
}
void setCreatedForHelperThread() {
MOZ_ASSERT(helperThreadUse_ == HelperThreadUse::None);
helperThreadUse_ = HelperThreadUse::Pending;
}
void setUsedByHelperThread() {
MOZ_ASSERT(helperThreadUse_ == HelperThreadUse::Pending);
helperThreadUse_ = HelperThreadUse::Active;
}
void clearUsedByHelperThread() {
MOZ_ASSERT(helperThreadUse_ != HelperThreadUse::None);
helperThreadUse_ = HelperThreadUse::None;
}
void findOutgoingEdges(js::gc::ZoneComponentFinder& finder);
void discardJitCode(js::FreeOp* fop, bool discardBaselineCode = true);
@ -513,48 +551,6 @@ struct Zone : public JS::shadow::Zone,
js::ZoneData<bool> isSystem;
private:
// The helper thread context with exclusive access to this zone, if
// usedByHelperThread(), or nullptr when on the main thread.
js::UnprotectedData<JSContext*> helperThreadOwnerContext_;
public:
bool ownedByCurrentHelperThread();
void setHelperThreadOwnerContext(JSContext* cx);
private:
enum class HelperThreadUse : uint32_t
{
None,
Pending,
Active
};
mozilla::Atomic<HelperThreadUse> helperThreadUse;
public:
// Whether this zone was created for use by a helper thread.
bool createdForHelperThread() const {
return helperThreadUse != HelperThreadUse::None;
}
// Whether this zone is currently in use by a helper thread.
bool usedByHelperThread() {
MOZ_ASSERT_IF(isAtomsZone(), helperThreadUse == HelperThreadUse::None);
return helperThreadUse == HelperThreadUse::Active;
}
void setCreatedForHelperThread() {
MOZ_ASSERT(helperThreadUse == HelperThreadUse::None);
helperThreadUse = HelperThreadUse::Pending;
}
void setUsedByHelperThread() {
MOZ_ASSERT(helperThreadUse == HelperThreadUse::Pending);
helperThreadUse = HelperThreadUse::Active;
}
void clearUsedByHelperThread() {
MOZ_ASSERT(helperThreadUse != HelperThreadUse::None);
helperThreadUse = HelperThreadUse::None;
}
#ifdef DEBUG
js::ZoneData<unsigned> gcLastSweepGroupIndex;
#endif