Bug 1468406 part 4 - Remove remaining JSObject::realm() calls. r=luke

This commit is contained in:
Jan de Mooij 2018-06-20 11:04:02 +02:00
Родитель 5070dbcceb
Коммит d1ca5feadb
19 изменённых файлов: 106 добавлений и 40 удалений

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

@ -1360,7 +1360,7 @@ CaptureFirstSubsumedFrame(JSContext* cx, unsigned argc, JS::Value* vp)
return false; return false;
} }
JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->realm()->principals())); JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->nonCCWRealm()->principals()));
if (args.length() > 1) if (args.length() > 1)
capture.as<JS::FirstSubsumedFrame>().ignoreSelfHosted = JS::ToBoolean(args[1]); capture.as<JS::FirstSubsumedFrame>().ignoreSelfHosted = JS::ToBoolean(args[1]);

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

@ -1128,7 +1128,7 @@ GetPropIRGenerator::tryAttachCrossCompartmentWrapper(HandleObject obj, ObjOperan
// so we optimize for that case as well. // so we optimize for that case as well.
isWindowProxy = IsWindowProxy(unwrapped); isWindowProxy = IsWindowProxy(unwrapped);
if (isWindowProxy) { if (isWindowProxy) {
MOZ_ASSERT(ToWindowIfWindowProxy(unwrapped) == unwrapped->realm()->maybeGlobal()); MOZ_ASSERT(ToWindowIfWindowProxy(unwrapped) == &unwrapped->nonCCWGlobal());
unwrapped = cx_->global(); unwrapped = cx_->global();
MOZ_ASSERT(unwrapped); MOZ_ASSERT(unwrapped);
} }

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

@ -7,6 +7,8 @@
#include "jsapi-tests/tests.h" #include "jsapi-tests/tests.h"
#include "vm/JSObject-inl.h"
using namespace JS; using namespace JS;
static void static void
@ -28,7 +30,7 @@ unsigned
countIonScripts(JSObject* global) countIonScripts(JSObject* global)
{ {
unsigned count = 0; unsigned count = 0;
js::IterateScripts(cx, global->realm(), &count, ScriptCallback); js::IterateScripts(cx, global->nonCCWRealm(), &count, ScriptCallback);
return count; return count;
} }

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

@ -12,6 +12,8 @@
#include "vm/Realm.h" #include "vm/Realm.h"
#include "vm/SavedFrame.h" #include "vm/SavedFrame.h"
#include "vm/JSObject-inl.h"
using JS::RootedObject; using JS::RootedObject;
using JS::RootedScript; using JS::RootedScript;
using JS::RootedString; using JS::RootedString;
@ -128,8 +130,8 @@ BEGIN_TEST(test_ubiNodeCompartment)
CHECK(global1->compartment() != global2->compartment()); CHECK(global1->compartment() != global2->compartment());
CHECK(JS::ubi::Node(global2).compartment() == global2->compartment()); CHECK(JS::ubi::Node(global2).compartment() == global2->compartment());
CHECK(JS::ubi::Node(global2).compartment() != global1->compartment()); CHECK(JS::ubi::Node(global2).compartment() != global1->compartment());
CHECK(JS::ubi::Node(global2).realm() == global2->realm()); CHECK(JS::ubi::Node(global2).realm() == global2->nonCCWRealm());
CHECK(JS::ubi::Node(global2).realm() != global1->realm()); CHECK(JS::ubi::Node(global2).realm() != global1->nonCCWRealm());
JS::CompileOptions options(cx); JS::CompileOptions options(cx);
@ -147,8 +149,8 @@ BEGIN_TEST(test_ubiNodeCompartment)
CHECK(JS::ubi::Node(script1).compartment() == global1->compartment()); CHECK(JS::ubi::Node(script1).compartment() == global1->compartment());
CHECK(JS::ubi::Node(script2).compartment() == global2->compartment()); CHECK(JS::ubi::Node(script2).compartment() == global2->compartment());
CHECK(JS::ubi::Node(script1).realm() == global1->realm()); CHECK(JS::ubi::Node(script1).realm() == global1->nonCCWRealm());
CHECK(JS::ubi::Node(script2).realm() == global2->realm()); CHECK(JS::ubi::Node(script2).realm() == global2->nonCCWRealm());
// Now create a wrapper for global1 in global2's compartment. // Now create a wrapper for global1 in global2's compartment.
RootedObject wrappedGlobal1(cx, global1); RootedObject wrappedGlobal1(cx, global1);

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

@ -885,7 +885,7 @@ JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
// destination, then we know that we won't find a wrapper in the // destination, then we know that we won't find a wrapper in the
// destination's cross compartment map and that the same // destination's cross compartment map and that the same
// object will continue to work. // object will continue to work.
AutoRealmUnchecked ar(cx, origobj->realm()); AutoRealmUnchecked ar(cx, origobj->deprecatedRealm());
if (!JSObject::swap(cx, origobj, target)) if (!JSObject::swap(cx, origobj, target))
MOZ_CRASH(); MOZ_CRASH();
newIdentity = origobj; newIdentity = origobj;
@ -919,7 +919,7 @@ JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
// Lastly, update the original object to point to the new one. // Lastly, update the original object to point to the new one.
if (origobj->compartment() != destination) { if (origobj->compartment() != destination) {
RootedObject newIdentityWrapper(cx, newIdentity); RootedObject newIdentityWrapper(cx, newIdentity);
AutoRealmUnchecked ar(cx, origobj->realm()); AutoRealmUnchecked ar(cx, origobj->deprecatedRealm());
if (!JS_WrapObject(cx, &newIdentityWrapper)) if (!JS_WrapObject(cx, &newIdentityWrapper))
MOZ_CRASH(); MOZ_CRASH();
MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity); MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);

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

@ -614,7 +614,7 @@ js::RemapWrapper(JSContext* cx, JSObject* wobjArg, JSObject* newTargetArg)
MOZ_ASSERT(!JS_IsDeadWrapper(origTarget), MOZ_ASSERT(!JS_IsDeadWrapper(origTarget),
"We don't want a dead proxy in the wrapper map"); "We don't want a dead proxy in the wrapper map");
Value origv = ObjectValue(*origTarget); Value origv = ObjectValue(*origTarget);
Realm* wrealm = wobj->realm(); Realm* wrealm = wobj->deprecatedRealm();
JS::Compartment* wcompartment = wobj->compartment(); JS::Compartment* wcompartment = wobj->compartment();
AutoDisableProxyCheck adpc; AutoDisableProxyCheck adpc;

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

@ -10669,7 +10669,7 @@ DebuggerObject::unwrap(JSContext* cx, HandleDebuggerObject object,
// Don't allow unwrapping to create a D.O whose referent is in an // Don't allow unwrapping to create a D.O whose referent is in an
// invisible-to-Debugger global. (If our referent is a *wrapper* to such, // invisible-to-Debugger global. (If our referent is a *wrapper* to such,
// and the wrapper is in a visible realm, that's fine.) // and the wrapper is in a visible realm, that's fine.)
if (unwrapped->realm()->creationOptions().invisibleToDebugger()) { if (unwrapped->nonCCWRealm()->creationOptions().invisibleToDebugger()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_INVISIBLE_COMPARTMENT); JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_INVISIBLE_COMPARTMENT);
return false; return false;
} }
@ -11545,7 +11545,27 @@ Debugger::isDebuggerCrossCompartmentEdge(JSObject* obj, const gc::Cell* target)
return referent == target; return referent == target;
} }
#endif
static void
CheckDebuggeeThingRealm(Realm* realm, bool invisibleOk)
{
MOZ_ASSERT(!realm->creationOptions().mergeable());
MOZ_ASSERT_IF(!invisibleOk, !realm->creationOptions().invisibleToDebugger());
}
void
js::CheckDebuggeeThing(JSScript* script, bool invisibleOk)
{
CheckDebuggeeThingRealm(script->realm(), invisibleOk);
}
void
js::CheckDebuggeeThing(JSObject* obj, bool invisibleOk)
{
if (Realm* realm = JS::GetObjectRealmOrNull(obj))
CheckDebuggeeThingRealm(realm, invisibleOk);
}
#endif // DEBUG
/*** JS::dbg::GarbageCollectionEvent **************************************************************/ /*** JS::dbg::GarbageCollectionEvent **************************************************************/

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

@ -89,6 +89,14 @@ typedef HashSet<ReadBarrieredGlobalObject,
MovableCellHasher<ReadBarrieredGlobalObject>, MovableCellHasher<ReadBarrieredGlobalObject>,
ZoneAllocPolicy> WeakGlobalObjectSet; ZoneAllocPolicy> WeakGlobalObjectSet;
#ifdef DEBUG
extern void
CheckDebuggeeThing(JSScript* script, bool invisibleOk);
extern void
CheckDebuggeeThing(JSObject* obj, bool invisibleOk);
#endif
/* /*
* A weakmap from GC thing keys to JSObject values that supports the keys being * A weakmap from GC thing keys to JSObject values that supports the keys being
* in different compartments to the values. All values must be in the same * in different compartments to the values. All values must be in the same
@ -161,9 +169,9 @@ class DebuggerWeakMap : private WeakMap<HeapPtr<UnbarrieredKey>, HeapPtr<JSObjec
template<typename KeyInput, typename ValueInput> template<typename KeyInput, typename ValueInput>
bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) { bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) {
MOZ_ASSERT(v->compartment() == this->compartment); MOZ_ASSERT(v->compartment() == this->compartment);
MOZ_ASSERT(!k->realm()->creationOptions().mergeable()); #ifdef DEBUG
MOZ_ASSERT_IF(!InvisibleKeysOk, CheckDebuggeeThing(k, InvisibleKeysOk);
!k->realm()->creationOptions().invisibleToDebugger()); #endif
MOZ_ASSERT(!Base::has(k)); MOZ_ASSERT(!Base::has(k));
if (!incZoneCount(k->zone())) if (!incZoneCount(k->zone()))
return false; return false;

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

@ -2552,7 +2552,7 @@ DebugEnvironments::addDebugEnvironment(JSContext* cx, Handle<EnvironmentObject*>
Handle<DebugEnvironmentProxy*> debugEnv) Handle<DebugEnvironmentProxy*> debugEnv)
{ {
MOZ_ASSERT(cx->realm() == env->realm()); MOZ_ASSERT(cx->realm() == env->realm());
MOZ_ASSERT(cx->realm() == debugEnv->realm()); MOZ_ASSERT(cx->realm() == debugEnv->nonCCWRealm());
if (!CanUseDebugEnvironmentMaps(cx)) if (!CanUseDebugEnvironmentMaps(cx))
return true; return true;
@ -2585,7 +2585,7 @@ DebugEnvironments::addDebugEnvironment(JSContext* cx, const EnvironmentIter& ei,
Handle<DebugEnvironmentProxy*> debugEnv) Handle<DebugEnvironmentProxy*> debugEnv)
{ {
MOZ_ASSERT(!ei.hasSyntacticEnvironment()); MOZ_ASSERT(!ei.hasSyntacticEnvironment());
MOZ_ASSERT(cx->realm() == debugEnv->realm()); MOZ_ASSERT(cx->realm() == debugEnv->nonCCWRealm());
// Generators should always have environments. // Generators should always have environments.
MOZ_ASSERT_IF(ei.scope().is<FunctionScope>(), MOZ_ASSERT_IF(ei.scope().is<FunctionScope>(),
!ei.scope().as<FunctionScope>().canonicalFunction()->isGenerator() && !ei.scope().as<FunctionScope>().canonicalFunction()->isGenerator() &&
@ -2867,7 +2867,7 @@ DebugEnvironments::updateLiveEnvironments(JSContext* cx)
continue; continue;
AbstractFramePtr frame = i.abstractFramePtr(); AbstractFramePtr frame = i.abstractFramePtr();
if (frame.environmentChain()->realm() != cx->realm()) if (frame.realm() != cx->realm())
continue; continue;
if (frame.isFunctionFrame()) { if (frame.isFunctionFrame()) {
@ -2896,7 +2896,7 @@ DebugEnvironments::updateLiveEnvironments(JSContext* cx)
if (frame.prevUpToDate()) if (frame.prevUpToDate())
return true; return true;
MOZ_ASSERT(frame.environmentChain()->realm()->isDebuggee()); MOZ_ASSERT(frame.realm()->isDebuggee());
frame.setPrevUpToDate(); frame.setPrevUpToDate();
} }
@ -2935,7 +2935,7 @@ DebugEnvironments::unsetPrevUpToDateUntil(JSContext* cx, AbstractFramePtr until)
if (frame == until) if (frame == until)
return; return;
if (frame.environmentChain()->realm() != cx->realm()) if (frame.realm() != cx->realm())
continue; continue;
frame.unsetPrevUpToDate(); frame.unsetPrevUpToDate();

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

@ -478,9 +478,22 @@ JSContext::enterAtomsZone(const js::AutoLockForExclusiveAccess& lock)
arenas_ = &zone_->arenas; arenas_ = &zone_->arenas;
} }
template <typename T>
inline void inline void
JSContext::enterRealmOf(const T& target) JSContext::enterRealmOf(JSObject* target)
{
MOZ_ASSERT(JS::CellIsNotGray(target));
enterRealm(target->deprecatedRealm());
}
inline void
JSContext::enterRealmOf(JSScript* target)
{
MOZ_ASSERT(JS::CellIsNotGray(target));
enterRealm(target->realm());
}
inline void
JSContext::enterRealmOf(js::ObjectGroup* target)
{ {
MOZ_ASSERT(JS::CellIsNotGray(target)); MOZ_ASSERT(JS::CellIsNotGray(target));
enterRealm(target->realm()); enterRealm(target->realm());

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

@ -212,8 +212,9 @@ struct JSContext : public JS::RootingContext,
friend class js::AutoRealm; friend class js::AutoRealm;
public: public:
template <typename T> inline void enterRealmOf(JSObject* target);
inline void enterRealmOf(const T& target); inline void enterRealmOf(JSScript* target);
inline void enterRealmOf(js::ObjectGroup* target);
inline void enterNullRealm(); inline void enterNullRealm();
inline void leaveRealm(JS::Realm* oldRealm); inline void leaveRealm(JS::Realm* oldRealm);

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

@ -393,21 +393,19 @@ SetNewObjectMetadata(JSContext* cx, T* obj)
inline js::GlobalObject& inline js::GlobalObject&
JSObject::deprecatedGlobal() const JSObject::deprecatedGlobal() const
{ {
return *realm()->unsafeUnbarrieredMaybeGlobal(); return *deprecatedRealm()->unsafeUnbarrieredMaybeGlobal();
} }
inline js::GlobalObject& inline js::GlobalObject&
JSObject::nonCCWGlobal() const JSObject::nonCCWGlobal() const
{ {
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(this));
/* /*
* The global is read-barriered so that it is kept live by access through * The global is read-barriered so that it is kept live by access through
* the Realm. When accessed through a JSObject, however, the global will be * the Realm. When accessed through a JSObject, however, the global will be
* already kept live by the black JSObject's group pointer, so does not * already kept live by the black JSObject's group pointer, so does not
* need to be read-barriered. * need to be read-barriered.
*/ */
return *realm()->unsafeUnbarrieredMaybeGlobal(); return *nonCCWRealm()->unsafeUnbarrieredMaybeGlobal();
} }
inline bool inline bool

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

@ -162,7 +162,6 @@ class JSObject : public js::gc::Cell
JS::Compartment* compartment() const { return group_->compartment(); } JS::Compartment* compartment() const { return group_->compartment(); }
JS::Compartment* maybeCompartment() const { return compartment(); } JS::Compartment* maybeCompartment() const { return compartment(); }
JS::Realm* realm() const { return group_->realm(); }
inline js::Shape* maybeShape() const; inline js::Shape* maybeShape() const;
inline js::Shape* ensureShape(JSContext* cx); inline js::Shape* ensureShape(JSContext* cx);
@ -433,9 +432,27 @@ class JSObject : public js::gc::Cell
inline js::GlobalObject& deprecatedGlobal() const; inline js::GlobalObject& deprecatedGlobal() const;
// Cross-compartment wrappers are not associated with a single realm/global, // Cross-compartment wrappers are not associated with a single realm/global,
// so this method asserts the object is not a CCW. // so these methods assert the object is not a CCW.
inline js::GlobalObject& nonCCWGlobal() const; inline js::GlobalObject& nonCCWGlobal() const;
JS::Realm* nonCCWRealm() const {
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(this));
return group_->realm();
}
// Returns the object's realm even if the object is a CCW (be careful, in
// this case the realm is not very meaningful because wrappers are shared by
// all realms in the compartment).
JS::Realm* maybeCCWRealm() const {
return group_->realm();
}
// Deprecated: call nonCCWRealm(), maybeCCWRealm(), or NativeObject::realm()
// instead!
JS::Realm* deprecatedRealm() const {
return group_->realm();
}
/* /*
* ES5 meta-object properties and operations. * ES5 meta-object properties and operations.
*/ */

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

@ -461,7 +461,7 @@ StatsCellCallback(JSRuntime* rt, void* data, void* thing, JS::TraceKind traceKin
switch (traceKind) { switch (traceKind) {
case JS::TraceKind::Object: { case JS::TraceKind::Object: {
JSObject* obj = static_cast<JSObject*>(thing); JSObject* obj = static_cast<JSObject*>(thing);
RealmStats& realmStats = obj->realm()->realmStats(); RealmStats& realmStats = obj->maybeCCWRealm()->realmStats();
JS::ClassInfo info; // This zeroes all the sizes. JS::ClassInfo info; // This zeroes all the sizes.
info.objectsGCHeap += thingSize; info.objectsGCHeap += thingSize;

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

@ -1474,8 +1474,10 @@ class NativeObject : public ShapedObject
// Native objects are never wrappers, so a native object always has a realm // Native objects are never wrappers, so a native object always has a realm
// and global. // and global.
JS::Realm* realm() const {
return nonCCWRealm();
}
inline js::GlobalObject& global() const; inline js::GlobalObject& global() const;
JS::Realm* realm() const { return JSObject::realm(); }
/* JIT Accessors */ /* JIT Accessors */
static size_t offsetOfElements() { return offsetof(NativeObject, elements_); } static size_t offsetOfElements() { return offsetof(NativeObject, elements_); }

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

@ -46,7 +46,10 @@ JS::Realm::globalIsAboutToBeFinalized()
/* static */ inline js::ObjectRealm& /* static */ inline js::ObjectRealm&
js::ObjectRealm::get(const JSObject* obj) js::ObjectRealm::get(const JSObject* obj)
{ {
return obj->realm()->objects_; // Note: obj might be a CCW if we're accessing ObjectRealm::enumerators.
// CCWs here are fine because we always return the same ObjectRealm for a
// particular (CCW) object.
return obj->maybeCCWRealm()->objects_;
} }
template <typename T> template <typename T>

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

@ -642,12 +642,12 @@ Realm::forgetAllocationMetadataBuilder()
void void
Realm::setNewObjectMetadata(JSContext* cx, HandleObject obj) Realm::setNewObjectMetadata(JSContext* cx, HandleObject obj)
{ {
MOZ_ASSERT(obj->realm() == this); MOZ_ASSERT(obj->maybeCCWRealm() == this);
assertSameCompartment(cx, compartment(), obj); assertSameCompartment(cx, compartment(), obj);
AutoEnterOOMUnsafeRegion oomUnsafe; AutoEnterOOMUnsafeRegion oomUnsafe;
if (JSObject* metadata = allocationMetadataBuilder_->build(cx, obj, oomUnsafe)) { if (JSObject* metadata = allocationMetadataBuilder_->build(cx, obj, oomUnsafe)) {
MOZ_ASSERT(metadata->realm() == obj->realm()); MOZ_ASSERT(metadata->maybeCCWRealm() == obj->maybeCCWRealm());
assertSameCompartment(cx, metadata); assertSameCompartment(cx, metadata);
if (!objects_.objectMetadataTable) { if (!objects_.objectMetadataTable) {
@ -1016,7 +1016,7 @@ JS::GetCurrentRealmOrNull(JSContext* cx)
JS_PUBLIC_API(JS::Realm*) JS_PUBLIC_API(JS::Realm*)
JS::GetObjectRealmOrNull(JSObject* obj) JS::GetObjectRealmOrNull(JSObject* obj)
{ {
return IsCrossCompartmentWrapper(obj) ? nullptr : obj->realm(); return IsCrossCompartmentWrapper(obj) ? nullptr : obj->nonCCWRealm();
} }
JS_PUBLIC_API(void*) JS_PUBLIC_API(void*)

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

@ -784,15 +784,15 @@ public:
MOZ_RELEASE_ASSERT(cx->realm()); MOZ_RELEASE_ASSERT(cx->realm());
if (obj) if (obj)
MOZ_RELEASE_ASSERT(obj->realm()); MOZ_RELEASE_ASSERT(obj->deprecatedRealm());
// Note that obj might be null here, since we're doing this before // Note that obj might be null here, since we're doing this before
// UnwrapSavedFrame. // UnwrapSavedFrame.
if (obj && cx->realm() != obj->realm()) if (obj && cx->realm() != obj->deprecatedRealm())
{ {
JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes; JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes;
if (subsumes && subsumes(cx->realm()->principals(), if (subsumes && subsumes(cx->realm()->principals(),
obj->realm()->principals())) obj->deprecatedRealm()->principals()))
{ {
ar_.emplace(cx, obj); ar_.emplace(cx, obj);
} }

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

@ -497,7 +497,7 @@ AbstractFramePtr::pushVarEnvironment(JSContext* cx, HandleScope scope)
inline JS::Realm* inline JS::Realm*
AbstractFramePtr::realm() const AbstractFramePtr::realm() const
{ {
return environmentChain()->realm(); return environmentChain()->nonCCWRealm();
} }
inline unsigned inline unsigned