author | Jan de Mooij <jdemooij@mozilla.com> |
Thu, 14 Jun 2018 09:07:31 -0700 | |
changeset 422544 | 3d767ed287afdfc29a0ad9aa43561f688c731b77 |
parent 422543 | 4face648a1521ac31836069665fa5cbb46df4ea9 |
child 422545 | e9c6358496ff694f7b4127c02c4dcee0fa8be96a |
push id | 104289 |
push user | jandemooij@gmail.com |
push date | Thu, 14 Jun 2018 16:13:19 +0000 |
treeherder | mozilla-inbound@fc2ffbc36c07 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | luke |
bugs | 1468252 |
milestone | 62.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
|
--- a/js/public/Wrapper.h +++ b/js/public/Wrapper.h @@ -138,17 +138,17 @@ class JS_FRIEND_API(Wrapper) : public Fo LAST_USED_FLAG = CROSS_COMPARTMENT }; static JSObject* New(JSContext* cx, JSObject* obj, const Wrapper* handler, const WrapperOptions& options = WrapperOptions()); static JSObject* Renew(JSObject* existing, JSObject* obj, const Wrapper* handler); - static const Wrapper* wrapperHandler(JSObject* wrapper); + static const Wrapper* wrapperHandler(const JSObject* wrapper); static JSObject* wrappedObject(JSObject* wrapper); unsigned flags() const { return mFlags; } static const char family; @@ -330,17 +330,17 @@ class JS_FRIEND_API(SecurityWrapper) : p }; typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper; extern JSObject* TransparentObjectWrapper(JSContext* cx, HandleObject existing, HandleObject obj); inline bool -IsWrapper(JSObject* obj) +IsWrapper(const JSObject* obj) { return IsProxy(obj) && GetProxyHandler(obj)->family() == &Wrapper::family; } // Given a JSObject, returns that object stripped of wrappers. If // stopAtWindowProxy is true, then this returns the WindowProxy if it was // previously wrapped. Otherwise, this returns the first object for which // JSObject::isWrapper returns false.
--- a/js/src/builtin/Promise.cpp +++ b/js/src/builtin/Promise.cpp @@ -750,17 +750,17 @@ EnqueuePromiseReactionJob(JSContext* cx, // unwrapping and then getting the global. This is very convoluted, but // much better than having to store the original global as a private value // because we couldn't wrap it to store it as a normal JS value. RootedObject global(cx); RootedObject objectFromIncumbentGlobal(cx, reaction->incumbentGlobalObject()); if (objectFromIncumbentGlobal) { objectFromIncumbentGlobal = CheckedUnwrap(objectFromIncumbentGlobal); MOZ_ASSERT(objectFromIncumbentGlobal); - global = &objectFromIncumbentGlobal->global(); + global = &objectFromIncumbentGlobal->nonCCWGlobal(); } // Note: the global we pass here might be from a different compartment // than job and promise. While it's somewhat unusual to pass objects // from multiple compartments, in this case we specifically need the // global to be unwrapped because wrapping and unwrapping aren't // necessarily symmetric for globals. return cx->runtime()->enqueuePromiseJob(cx, job, promise, global); @@ -1022,17 +1022,17 @@ RejectMaybeWrappedPromise(JSContext *cx, // rejection handler. if (!promise->compartment()->wrap(cx, &reason)) return false; if (reason.isObject() && !CheckedUnwrap(&reason.toObject())) { // Report the existing reason, so we don't just drop it on the // floor. RootedObject realReason(cx, UncheckedUnwrap(&reason.toObject())); RootedValue realReasonVal(cx, ObjectValue(*realReason)); - RootedObject realGlobal(cx, &realReason->global()); + RootedObject realGlobal(cx, &realReason->nonCCWGlobal()); ReportErrorToGlobal(cx, realGlobal, realReasonVal); // Async stacks are only properly adopted if there's at least one // interpreter frame active right now. If a thenable job with a // throwing `then` function got us here, that'll not be the case, // so we add one by throwing the error from self-hosted code. if (!GetInternalError(cx, JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON, &reason)) return false;
--- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -5173,17 +5173,17 @@ ObjectGlobal(JSContext* cx, unsigned arg } RootedObject obj(cx, &args[0].toObject()); if (IsWrapper(obj)) { args.rval().setNull(); return true; } - obj = ToWindowProxyIfWindow(&obj->global()); + obj = ToWindowProxyIfWindow(&obj->nonCCWGlobal()); args.rval().setObject(*obj); return true; } JSScript* js::TestingFunctionArgumentToScript(JSContext* cx, HandleValue v,
--- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -1498,17 +1498,17 @@ js::SetWindowProxy(JSContext* cx, Handle MOZ_ASSERT(IsWindowProxy(windowProxy)); global->as<GlobalObject>().setWindowProxy(windowProxy); } JS_FRIEND_API(JSObject*) js::ToWindowIfWindowProxy(JSObject* obj) { if (IsWindowProxy(obj)) - return &obj->global(); + return &obj->nonCCWGlobal(); return obj; } JS_FRIEND_API(JSObject*) js::detail::ToWindowProxyIfWindowSlow(JSObject* obj) { if (JSObject* windowProxy = obj->as<GlobalObject>().maybeWindowProxy()) return windowProxy;
--- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -670,17 +670,17 @@ InheritanceProtoKeyForStandardClass(JSPr // Otherwise, we inherit [Object]. return JSProto_Object; } JS_FRIEND_API(bool) IsFunctionObject(JSObject* obj); JS_FRIEND_API(bool) -IsCrossCompartmentWrapper(JSObject* obj); +IsCrossCompartmentWrapper(const JSObject* obj); static MOZ_ALWAYS_INLINE JS::Compartment* GetObjectCompartment(JSObject* obj) { JS::Realm* realm = reinterpret_cast<shadow::Object*>(obj)->group->realm; return JS::GetCompartmentForRealm(realm); }
--- a/js/src/proxy/CrossCompartmentWrapper.cpp +++ b/js/src/proxy/CrossCompartmentWrapper.cpp @@ -487,17 +487,17 @@ CrossCompartmentWrapper::boxedValue_unbo NOTHING, Wrapper::boxedValue_unbox(cx, wrapper, vp), cx->compartment()->wrap(cx, vp)); } const CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u); bool -js::IsCrossCompartmentWrapper(JSObject* obj) +js::IsCrossCompartmentWrapper(const JSObject* obj) { return IsWrapper(obj) && !!(Wrapper::wrapperHandler(obj)->flags() & Wrapper::CROSS_COMPARTMENT); } static void NukeRemovedCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper) {
--- a/js/src/proxy/Wrapper.cpp +++ b/js/src/proxy/Wrapper.cpp @@ -325,17 +325,17 @@ Wrapper::New(JSContext* cx, JSObject* ob JSObject* Wrapper::Renew(JSObject* existing, JSObject* obj, const Wrapper* handler) { existing->as<ProxyObject>().renew(handler, ObjectValue(*obj)); return existing; } const Wrapper* -Wrapper::wrapperHandler(JSObject* wrapper) +Wrapper::wrapperHandler(const JSObject* wrapper) { MOZ_ASSERT(wrapper->is<WrapperObject>()); return static_cast<const Wrapper*>(wrapper->as<ProxyObject>().handler()); } JSObject* Wrapper::wrappedObject(JSObject* wrapper) {
--- a/js/src/vm/JSObject-inl.h +++ b/js/src/vm/JSObject-inl.h @@ -397,16 +397,23 @@ JSObject::global() const * 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 * already kept live by the black JSObject's group pointer, so does not * need to be read-barriered. */ return *realm()->unsafeUnbarrieredMaybeGlobal(); } +inline js::GlobalObject& +JSObject::nonCCWGlobal() const +{ + MOZ_ASSERT(!js::IsCrossCompartmentWrapper(this)); + return global(); +} + inline js::GlobalObject* JSObject::globalForTracing(JSTracer*) const { return realm()->unsafeUnbarrieredMaybeGlobal(); } inline bool JSObject::isOwnGlobal(JSTracer* trc) const
--- a/js/src/vm/JSObject.cpp +++ b/js/src/vm/JSObject.cpp @@ -2194,17 +2194,17 @@ js::GetObjectFromIncumbentGlobal(JSConte return false; return true; } static bool IsStandardPrototype(JSObject* obj, JSProtoKey key) { - Value v = obj->global().getPrototype(key); + Value v = obj->nonCCWGlobal().getPrototype(key); return v.isObject() && obj == &v.toObject(); } JSProtoKey JS::IdentifyStandardInstance(JSObject* obj) { // Note: The prototype shares its JSClass with instances. MOZ_ASSERT(!obj->is<CrossCompartmentWrapperObject>()); @@ -2236,17 +2236,17 @@ JS::IdentifyStandardConstructor(JSObject { // Note that NATIVE_CTOR does not imply that we are a standard constructor, // but the converse is true (at least until we start having self-hosted // constructors for standard classes). This lets us avoid a costly loop for // many functions (which, depending on the call site, may be the common case). if (!obj->is<JSFunction>() || !(obj->as<JSFunction>().flags() & JSFunction::NATIVE_CTOR)) return JSProto_Null; - GlobalObject& global = obj->global(); + GlobalObject& global = obj->as<JSFunction>().global(); for (size_t k = 0; k < JSProto_LIMIT; ++k) { JSProtoKey key = static_cast<JSProtoKey>(k); if (global.getConstructor(key) == ObjectValue(*obj)) return key; } return JSProto_Null; }
--- a/js/src/vm/JSObject.h +++ b/js/src/vm/JSObject.h @@ -426,16 +426,20 @@ class JSObject : public js::gc::Cell * non-EnvironmentObject, this will just be the global (the name * "enclosing environment" still applies in this situation because * non-EnvironmentObjects can be on the environment chain). */ inline JSObject* enclosingEnvironment() const; inline js::GlobalObject& global() const; + // Cross-compartment wrappers are not associated with a single realm/global, + // so this method asserts the object is not a CCW. + inline js::GlobalObject& nonCCWGlobal() const; + // In some rare cases the global object's compartment's global may not be // the same global object. For this reason, we need to take extra care when // tracing. // // These cases are: // 1) The off-thread parsing task uses a dummy global since it cannot // share with the actual global being used concurrently on the active // thread.
--- a/js/src/vm/NativeObject-inl.h +++ b/js/src/vm/NativeObject-inl.h @@ -667,17 +667,17 @@ NativeObject::allocKindForTenure() const if (!CanBeFinalizedInBackground(kind, getClass())) return kind; return GetBackgroundAllocKind(kind); } inline js::GlobalObject& NativeObject::global() const { - return JSObject::global(); + return nonCCWGlobal(); } inline js::gc::AllocKind PlainObject::allocKindForTenure() const { using namespace js::gc; AllocKind kind = GetGCObjectFixedSlotsKind(numFixedSlots()); MOZ_ASSERT(!IsBackgroundFinalized(kind));