Bug 1129473 - Ensure off-thread parsing sets the is-delegate flag on builtin protos. r=bhackett
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 06 Feb 2015 18:17:00 +0100
changeset 245412 84c309df6d242314b362fed16d8514ee407e5234
parent 245411 c8d97a8ed806dfacd2aa14c060de0062e25a1d0a
child 245413 4f92dc4510bf6dd8630474e305bda08697fe3eca
push id7677
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 18:11:24 +0000
treeherdermozilla-aurora@f531d838c055 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1129473
milestone38.0a1
Bug 1129473 - Ensure off-thread parsing sets the is-delegate flag on builtin protos. r=bhackett
js/src/jsobj.h
js/src/vm/HelperThreads.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/ObjectGroup.h
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -348,19 +348,17 @@ class JSObject : public js::gc::Cell
     }
 
     bool hasTenuredProto() const;
 
     bool uninlinedIsProxy() const;
 
     JSObject *getProto() const {
         MOZ_ASSERT(!uninlinedIsProxy());
-        JSObject *proto = getTaggedProto().toObjectOrNull();
-        MOZ_ASSERT_IF(proto && proto->isNative(), proto->isDelegate());
-        return proto;
+        return getTaggedProto().toObjectOrNull();
     }
 
     // Normal objects and a subset of proxies have uninteresting [[Prototype]].
     // For such objects the [[Prototype]] is just a value returned when needed
     // for accesses, or modified in response to requests.  These objects store
     // the [[Prototype]] directly within |obj->type_|.
     //
     // Proxies that don't have such a simple [[Prototype]] instead have a
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -840,16 +840,25 @@ static void
 LeaveParseTaskZone(JSRuntime *rt, ParseTask *task)
 {
     // Mark the zone as no longer in use by an ExclusiveContext, and available
     // to be collected by the GC.
     task->cx->leaveCompartment(task->cx->compartment());
     rt->clearUsedByExclusiveThread(task->cx->zone());
 }
 
+static bool
+EnsureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key)
+{
+    if (!GlobalObject::ensureConstructor(cx, global, key))
+        return false;
+
+    return global->getPrototype(key).toObject().setDelegate(cx);
+}
+
 JSScript *
 GlobalHelperThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *token)
 {
     ScopedJSDeletePtr<ParseTask> parseTask;
 
     // The token is a ParseTask* which should be in the finished list.
     // Find and remove its entry.
     {
@@ -871,21 +880,21 @@ GlobalHelperThreadState::finishParseTask
     }
 
     JSContext *cx = maybecx;
     MOZ_ASSERT(cx->compartment());
 
     // Make sure we have all the constructors we need for the prototype
     // remapping below, since we can't GC while that's happening.
     Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
-    if (!GlobalObject::ensureConstructor(cx, global, JSProto_Object) ||
-        !GlobalObject::ensureConstructor(cx, global, JSProto_Array) ||
-        !GlobalObject::ensureConstructor(cx, global, JSProto_Function) ||
-        !GlobalObject::ensureConstructor(cx, global, JSProto_RegExp) ||
-        !GlobalObject::ensureConstructor(cx, global, JSProto_Iterator))
+    if (!EnsureConstructor(cx, global, JSProto_Object) ||
+        !EnsureConstructor(cx, global, JSProto_Array) ||
+        !EnsureConstructor(cx, global, JSProto_Function) ||
+        !EnsureConstructor(cx, global, JSProto_RegExp) ||
+        !EnsureConstructor(cx, global, JSProto_Iterator))
     {
         LeaveParseTaskZone(rt, parseTask);
         return nullptr;
     }
 
     LeaveParseTaskZone(rt, parseTask);
 
     // Point the prototypes of any objects in the script's compartment to refer
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -44,16 +44,23 @@ ObjectGroup::ObjectGroup(const Class *cl
 void
 ObjectGroup::finalize(FreeOp *fop)
 {
     fop->delete_(newScriptDontCheckGeneration());
     fop->delete_(maybeUnboxedLayoutDontCheckGeneration());
 }
 
 void
+ObjectGroup::setProtoUnchecked(TaggedProto proto)
+{
+    proto_ = proto.raw();
+    MOZ_ASSERT_IF(proto_ && proto_->isNative(), proto_->isDelegate());
+}
+
+void
 ObjectGroup::setProto(JSContext *cx, TaggedProto proto)
 {
     MOZ_ASSERT(singleton());
 
     if (proto.isObject() && IsInsideNursery(proto.toObject()))
         addFlags(OBJECT_FLAG_NURSERY_PROTO);
 
     setProtoUnchecked(proto);
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -251,19 +251,17 @@ class ObjectGroup : public gc::TenuredCe
         return singleton_;
     }
 
     // For use during marking, don't call otherwise.
     HeapPtrObject &protoRaw() { return proto_; }
     HeapPtrObject &singletonRaw() { return singleton_; }
 
     void setProto(JSContext *cx, TaggedProto proto);
-    void setProtoUnchecked(TaggedProto proto) {
-        proto_ = proto.raw();
-    }
+    void setProtoUnchecked(TaggedProto proto);
 
     void initSingleton(JSObject *singleton) {
         singleton_ = singleton;
     }
 
     /*
      * Value held by singleton if this is a standin group for a singleton JS
      * object whose group has not been constructed yet.