author | Steve Fink <sfink@mozilla.com> |
Tue, 12 Jan 2016 12:55:35 -0800 | |
changeset 281954 | c1153dc8ccd12858e6f0e2b3762e2331b9feee01 |
parent 281953 | d0b106a76c7f44f96aea815e7dfb74902d49b386 |
child 281955 | d8f94c8056847a041d918102131eab86f15cd4ed |
push id | 29950 |
push user | cbook@mozilla.com |
push date | Thu, 28 Jan 2016 11:14:03 +0000 |
treeherder | mozilla-central@2b73b0a4d52b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | terrence |
bugs | 1237445 |
milestone | 47.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
|
js/src/vm/RegExpObject.cpp | file | annotate | diff | comparison | revisions | |
js/src/vm/RegExpObject.h | file | annotate | diff | comparison | revisions |
--- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -782,48 +782,53 @@ RegExpCompartment::init(JSContext* cx) if (cx) ReportOutOfMemory(cx); return false; } return true; } +bool +RegExpShared::needsSweep(JSRuntime* rt) +{ + // Sometimes RegExpShared instances are marked without the compartment + // being subsequently cleared. This can happen if a GC is restarted while + // in progress (i.e. performing a full GC in the middle of an incremental + // GC) or if a RegExpShared referenced via the stack is traced but is not + // in a zone being collected. + // + // Because of this we only treat the marked_ bit as a hint, and destroy the + // RegExpShared if it was accidentally marked earlier but wasn't marked by + // the current trace. + bool keep = marked() && IsMarked(&source); + for (size_t i = 0; i < ArrayLength(compilationArray); i++) { + RegExpShared::RegExpCompilation& compilation = compilationArray[i]; + if (compilation.jitCode && gc::IsAboutToBeFinalized(&compilation.jitCode)) + keep = false; + } + + MOZ_ASSERT(rt->isHeapMajorCollecting()); + if (keep || rt->gc.isHeapCompacting()) { + clearMarked(); + return false; + } + + return true; +} + void RegExpCompartment::sweep(JSRuntime* rt) { if (!set_.initialized()) return; for (Set::Enum e(set_); !e.empty(); e.popFront()) { RegExpShared* shared = e.front(); - - // Sometimes RegExpShared instances are marked without the - // compartment being subsequently cleared. This can happen if a GC is - // restarted while in progress (i.e. performing a full GC in the - // middle of an incremental GC) or if a RegExpShared referenced via the - // stack is traced but is not in a zone being collected. - // - // Because of this we only treat the marked_ bit as a hint, and destroy - // the RegExpShared if it was accidentally marked earlier but wasn't - // marked by the current trace. - bool keep = shared->marked() && - IsMarked(&shared->source); - for (size_t i = 0; i < ArrayLength(shared->compilationArray); i++) { - RegExpShared::RegExpCompilation& compilation = shared->compilationArray[i]; - if (compilation.jitCode && - IsAboutToBeFinalized(&compilation.jitCode)) - { - keep = false; - } - } - MOZ_ASSERT(rt->isHeapMajorCollecting()); - if (keep || rt->gc.isHeapCompacting()) { - shared->clearMarked(); - } else { + if (shared->needsSweep(rt)) { js_delete(shared); e.removeFront(); } } if (matchResultTemplateObject_ && IsAboutToBeFinalized(&matchResultTemplateObject_)) {
--- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -196,16 +196,17 @@ class RegExpShared bool isCompiled() const { return isCompiled(Normal, true, true) || isCompiled(Normal, true, false) || isCompiled(Normal, false, true) || isCompiled(Normal, false, false) || isCompiled(MatchOnly, true, true) || isCompiled(MatchOnly, true, false) || isCompiled(MatchOnly, false, true) || isCompiled(MatchOnly, false, false); } void trace(JSTracer* trc); + bool needsSweep(JSRuntime* rt); bool marked() const { return marked_; } void clearMarked() { marked_ = false; } static size_t offsetOfSource() { return offsetof(RegExpShared, source); }