зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1465002 - Make GetScriptedCallerGlobal work with same-compartment realms. r=luke
This commit is contained in:
Родитель
f8fc9044ec
Коммит
c5f8610e4f
|
@ -7544,37 +7544,58 @@ DescribeScriptedCaller(JSContext* cx, AutoFilename* filename, unsigned* lineno,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast path to get the activation to use for GetScriptedCallerGlobal. If this
|
// Fast path to get the activation and realm to use for GetScriptedCallerGlobal.
|
||||||
// returns false, the fast path didn't work out and the caller has to use the
|
// If this returns false, the fast path didn't work out and the caller has to
|
||||||
// (much slower) NonBuiltinFrameIter path.
|
// use the (much slower) NonBuiltinFrameIter path.
|
||||||
//
|
//
|
||||||
// The optimization here is that we skip Ion-inlined frames and only look at
|
// The optimization here is that we skip Ion-inlined frames and only look at
|
||||||
// 'outer' frames. That's fine: each activation is tied to a single compartment,
|
// 'outer' frames. That's fine because Ion doesn't inline cross-realm calls.
|
||||||
// so if an activation contains at least one non-self-hosted frame, we can use
|
// However, GetScriptedCallerGlobal has to skip self-hosted frames and Ion
|
||||||
// the activation's global for GetScriptedCallerGlobal. If, however, all 'outer'
|
// can inline self-hosted scripts, so we have to be careful:
|
||||||
// frames are self-hosted, it's possible Ion inlined a non-self-hosted script,
|
//
|
||||||
// so we must return false and use the slower path.
|
// * When we see a non-self-hosted outer script, it's possible we inlined
|
||||||
|
// self-hosted scripts into it but that doesn't matter because these scripts
|
||||||
|
// all have the same realm/global anyway.
|
||||||
|
//
|
||||||
|
// * When we see a self-hosted outer script, it's possible we inlined
|
||||||
|
// non-self-hosted scripts into it, so we have to give up because in this
|
||||||
|
// case, whether or not to skip the self-hosted frame (to the possibly
|
||||||
|
// different-realm caller) requires the slow path to handle inlining. Baseline
|
||||||
|
// and the interpreter don't inline so this only affects Ion.
|
||||||
static bool
|
static bool
|
||||||
GetScriptedCallerActivationFast(JSContext* cx, Activation** activation)
|
GetScriptedCallerActivationRealmFast(JSContext* cx, Activation** activation, Realm** realm)
|
||||||
{
|
{
|
||||||
ActivationIterator activationIter(cx);
|
ActivationIterator activationIter(cx);
|
||||||
|
|
||||||
if (activationIter.done()) {
|
if (activationIter.done()) {
|
||||||
*activation = nullptr;
|
*activation = nullptr;
|
||||||
|
*realm = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
*activation = activationIter.activation();
|
|
||||||
|
|
||||||
if (activationIter->isJit()) {
|
if (activationIter->isJit()) {
|
||||||
for (OnlyJSJitFrameIter iter(activationIter); !iter.done(); ++iter) {
|
for (OnlyJSJitFrameIter iter(activationIter); !iter.done(); ++iter) {
|
||||||
if (iter.frame().isScripted() && !iter.frame().script()->selfHosted())
|
if (!iter.frame().isScripted())
|
||||||
|
continue;
|
||||||
|
if (!iter.frame().script()->selfHosted()) {
|
||||||
|
*activation = activationIter.activation();
|
||||||
|
*realm = iter.frame().script()->realm();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
if (iter.frame().isIonScripted()) {
|
||||||
|
// Ion might have inlined non-self-hosted scripts in this
|
||||||
|
// self-hosted script.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (activationIter->isInterpreter()) {
|
} else if (activationIter->isInterpreter()) {
|
||||||
for (InterpreterFrameIterator iter((*activation)->asInterpreter()); !iter.done(); ++iter) {
|
InterpreterActivation* act = activationIter->asInterpreter();
|
||||||
if (!iter.frame()->script()->selfHosted())
|
for (InterpreterFrameIterator iter(act); !iter.done(); ++iter) {
|
||||||
|
if (!iter.frame()->script()->selfHosted()) {
|
||||||
|
*activation = act;
|
||||||
|
*realm = iter.frame()->script()->realm();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7585,8 +7606,8 @@ JS_PUBLIC_API(JSObject*)
|
||||||
GetScriptedCallerGlobal(JSContext* cx)
|
GetScriptedCallerGlobal(JSContext* cx)
|
||||||
{
|
{
|
||||||
Activation* activation;
|
Activation* activation;
|
||||||
|
Realm* realm;
|
||||||
if (GetScriptedCallerActivationFast(cx, &activation)) {
|
if (GetScriptedCallerActivationRealmFast(cx, &activation, &realm)) {
|
||||||
if (!activation)
|
if (!activation)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
|
@ -7594,18 +7615,21 @@ GetScriptedCallerGlobal(JSContext* cx)
|
||||||
if (i.done())
|
if (i.done())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
activation = i.activation();
|
activation = i.activation();
|
||||||
|
realm = i.realm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(realm->compartment() == activation->compartment());
|
||||||
|
|
||||||
// If the caller is hidden, the embedding wants us to return null here so
|
// If the caller is hidden, the embedding wants us to return null here so
|
||||||
// that it can check its own stack (see HideScriptedCaller).
|
// that it can check its own stack (see HideScriptedCaller).
|
||||||
if (activation->scriptedCallerIsHidden())
|
if (activation->scriptedCallerIsHidden())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
GlobalObject* global = JS::GetRealmForCompartment(activation->compartment())->maybeGlobal();
|
GlobalObject* global = realm->maybeGlobal();
|
||||||
|
|
||||||
// No one should be running code in the atoms realm or running code in
|
// No one should be running code in the atoms realm or running code in a
|
||||||
// a compartment without any live objects, so there should definitely be a
|
// realm without any live objects, so there should definitely be a live
|
||||||
// live global.
|
// global.
|
||||||
MOZ_ASSERT(global);
|
MOZ_ASSERT(global);
|
||||||
|
|
||||||
return global;
|
return global;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче