Bug 816784 part 2 - Optimize NukeCrossCompartmentWrappers() to iterate only the targetting wrappers. r=jonco

Changed the type of argument |targetFilter| of NukeCrossCompartmentWrappers()
from CompartmentFilter to JSCompartment* because it is always a single target
compartment, and we can optimize the iteration not to iterate the outer map.

MozReview-Commit-ID: 7cDCgJI0H9z

--HG--
extra : rebase_source : ee9341168a28b5e6f273c512b0562ee4ddc297bc
extra : source : e80197b115673f259293d112da61c8dd9edc121e
This commit is contained in:
Ting-Yu Chou 2017-05-03 13:56:54 +08:00
parent 5fe0cca12d
commit e11749eeba
4 changed files with 27 additions and 19 deletions

View File

@ -9651,8 +9651,7 @@ public:
: js::NukeWindowReferences);
} else {
// We only want to nuke wrappers for the chrome->content case
js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(),
js::SingleCompartment(cpt),
js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
win->IsInnerWindow() ? js::DontNukeWindowReferences
: js::NukeWindowReferences,
js::NukeIncomingReferences);

View File

@ -1229,7 +1229,7 @@ struct CompartmentsWithPrincipals : public CompartmentFilter {
extern JS_FRIEND_API(bool)
NukeCrossCompartmentWrappers(JSContext* cx,
const CompartmentFilter& sourceFilter,
const CompartmentFilter& targetFilter,
JSCompartment* target,
NukeReferencesToWindow nukeReferencesToWindow,
NukeReferencesFromTarget nukeReferencesFromTarget);

View File

@ -515,7 +515,7 @@ js::NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper)
JS_FRIEND_API(bool)
js::NukeCrossCompartmentWrappers(JSContext* cx,
const CompartmentFilter& sourceFilter,
const CompartmentFilter& targetFilter,
JSCompartment* target,
js::NukeReferencesToWindow nukeReferencesToWindow,
js::NukeReferencesFromTarget nukeReferencesFromTarget)
{
@ -531,18 +531,30 @@ js::NukeCrossCompartmentWrappers(JSContext* cx,
// If the compartment matches both the source and target filter, we may
// want to cut both incoming and outgoing wrappers.
bool nukeAll = (nukeReferencesFromTarget == NukeAllReferences &&
targetFilter.match(c));
target == c.get());
// Iterate the wrappers looking for anything interesting.
for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
// Some cross-compartment wrappers are for strings. We're not
// interested in those.
const CrossCompartmentKey& k = e.front().key();
// Iterate only the wrappers that have target compartment matched unless
// |nukeAll| is true. The wrappers for strings that we're not interested
// in won't be here because they have compartment nullptr. Use Maybe to
// avoid copying from conditionally initializing WrapperEnum.
mozilla::Maybe<JSCompartment::WrapperEnum> e;
if (MOZ_LIKELY(!nukeAll))
e.emplace(c, target);
else
e.emplace(c);
for (; !e->empty(); e->popFront()) {
// Skip debugger references because NukeCrossCompartmentWrapper()
// doesn't know how to nuke them yet, see bug 1084626 for more
// information.
const CrossCompartmentKey& k = e->front().key();
if (!k.is<JSObject*>())
continue;
AutoWrapperRooter wobj(cx, WrapperValue(e));
JSObject* wrapped = UncheckedUnwrap(wobj);
AutoWrapperRooter wobj(cx, WrapperValue(*e));
// Unwrap from the wrapped object in CrossCompartmentKey instead of
// the wrapper, this could save us a bit of time.
JSObject* wrapped = UncheckedUnwrap(k.as<JSObject*>());
// We never nuke script source objects, since only ever used internally by the JS
// engine, and are expected to remain valid throughout a scripts lifetime.
@ -558,11 +570,9 @@ js::NukeCrossCompartmentWrappers(JSContext* cx,
continue;
}
if (MOZ_UNLIKELY(nukeAll) || targetFilter.match(wrapped->compartment())) {
// We found a wrapper to nuke.
e.removeFront();
NukeCrossCompartmentWrapper(cx, wobj);
}
// Now this is the wrapper we want to nuke.
e->removeFront();
NukeCrossCompartmentWrapper(cx, wobj);
}
}

View File

@ -591,8 +591,7 @@ NukeAllWrappersForCompartment(JSContext* cx, JSCompartment* compartment,
// we need to be sure that we don't have any existing cross-compartment
// wrappers which may be replaced with dead wrappers during unrelated
// wrapper recomputation *before* we set that bit.
js::NukeCrossCompartmentWrappers(cx, js::AllCompartments(),
js::SingleCompartment(compartment),
js::NukeCrossCompartmentWrappers(cx, js::AllCompartments(), compartment,
nukeReferencesToWindow,
js::NukeAllReferences);