Bug 687724 (part 2) - Make JSCompartment::global() fallible. r=luke.

--HG--
extra : rebase_source : 68a5558772d643ab9f3b32b60a89fdbaf9b5e6ad
This commit is contained in:
Nicholas Nethercote 2012-07-03 17:25:15 -07:00
parent 452ba219a1
commit 309a1e7fdb
8 changed files with 31 additions and 14 deletions

View File

@ -634,8 +634,11 @@ ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
if (base->hasSetterObject())
PushMarkStack(gcmarker, base->setterObject());
if (JSObject *parent = base->getObjectParent())
if (JSObject *parent = base->getObjectParent()) {
PushMarkStack(gcmarker, parent);
} else if (GlobalObject *global = base->compartment()->maybeGlobal()) {
PushMarkStack(gcmarker, global);
}
/*
* All children of the owned base shape are consistent with its

View File

@ -1388,8 +1388,8 @@ JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
GlobalObject &global = target->compartment()->global();
return JS_EnterCrossCompartmentCall(cx, &global);
GlobalObject *global = target->compartment()->maybeGlobal();
return global ? JS_EnterCrossCompartmentCall(cx, global) : NULL;
}
JS_PUBLIC_API(JSCrossCompartmentCall *)

View File

@ -229,7 +229,7 @@ class CompartmentChecker
{
if (cx->compartment) {
GlobalObject *global = GetGlobalForScopeChain(cx);
JS_ASSERT(cx->compartment->global() == *global);
JS_ASSERT(cx->compartment->maybeGlobal() == global);
}
}

View File

@ -491,6 +491,9 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
discardJitCode(fop);
}
if (global_ && !IsObjectMarked(&global_))
global_ = NULL;
/* JIT code can hold references on RegExpShared, so sweep regexps after clearing code. */
regExps.sweep(rt);

View File

@ -119,12 +119,23 @@ struct JSCompartment
private:
js::GlobalObject *global_;
public:
js::GlobalObject &global() const {
JS_ASSERT(global_->compartment() == this);
return *global_;
// Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the
// compartment's global has been collected. The latter can happen if e.g.
// a string in a compartment is rooted but no object is, and thus the
// global isn't rooted, and thus the global can be finalized while the
// compartment lives on.
//
// In contrast, JSObject::global() is infallible because marking a JSObject
// always marks its global as well.
// TODO: add infallible JSScript::global() and JSContext::global()
//
js::GlobalObject *maybeGlobal() const {
JS_ASSERT_IF(global_, global_->compartment() == this);
return global_;
}
void initGlobal(js::GlobalObject &global) {
JS_ASSERT(global.compartment() == this);
JS_ASSERT(!global_);
global_ = &global;
}

View File

@ -2348,7 +2348,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *paren
JS_ASSERT(clasp != &ArrayClass);
JS_ASSERT_IF(clasp == &FunctionClass,
kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT_IF(parent, parent->global() == cx->compartment->global());
JS_ASSERT_IF(parent, &parent->global() == cx->compartment->maybeGlobal());
RootedTypeObject type(cx, type_);

View File

@ -1234,7 +1234,7 @@ JSObject::global() const
JSObject *obj = const_cast<JSObject *>(this);
while (JSObject *parent = obj->getParent())
obj = parent;
JS_ASSERT(obj->asGlobal() == compartment()->global());
JS_ASSERT(&obj->asGlobal() == compartment()->maybeGlobal());
return obj->asGlobal();
}

View File

@ -1521,7 +1521,7 @@ class TypedArrayTemplate
RootedId id(cx, NameToId(name));
unsigned flags = JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED | JSPROP_GETTER;
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
JSObject *getter = js_NewFunction(cx, NULL, Getter<ValueGetter>, 0, 0, global, NULL);
if (!getter)
return false;
@ -3008,7 +3008,7 @@ template<class ArrayType>
static inline JSObject *
InitTypedArrayClass(JSContext *cx)
{
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
RootedObject proto(cx, global->createBlankPrototype(cx, ArrayType::protoClass()));
if (!proto)
return NULL;
@ -3085,7 +3085,7 @@ Class TypedArray::protoClasses[TYPE_MAX] = {
static JSObject *
InitArrayBufferClass(JSContext *cx)
{
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
RootedObject arrayBufferProto(cx, global->createBlankPrototype(cx, &ArrayBufferObject::protoClass));
if (!arrayBufferProto)
return NULL;
@ -3198,7 +3198,7 @@ DefineDataViewGetter(JSContext *cx, PropertyName *name, HandleObject proto)
RootedId id(cx, NameToId(name));
unsigned flags = JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED | JSPROP_GETTER;
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
JSObject *getter = js_NewFunction(cx, NULL, DataViewGetter<ValueGetter>, 0, 0, global, NULL);
if (!getter)
return false;
@ -3211,7 +3211,7 @@ DefineDataViewGetter(JSContext *cx, PropertyName *name, HandleObject proto)
JSObject *
DataViewObject::initClass(JSContext *cx)
{
Rooted<GlobalObject*> global(cx, &cx->compartment->global());
Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
RootedObject proto(cx, global->createBlankPrototype(cx, &DataViewObject::protoClass));
if (!proto)
return NULL;