Bug 1073577 - Fix new object cache interactions with moving GC r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 30 Sep 2014 13:20:48 +0100
changeset 207877 f33f7dc50aa94521cf970088f69ed78e791c7a32
parent 207876 1de7e7a7ad8d4d0ca08be29b4019f7fcc996ff62
child 207878 5172971f07dc1079fddf3b267a9ca9734eae0f32
push id49806
push userjcoppeard@mozilla.com
push dateTue, 30 Sep 2014 12:25:53 +0000
treeherdermozilla-inbound@f33f7dc50aa9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1073577
milestone35.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
Bug 1073577 - Fix new object cache interactions with moving GC r=terrence
js/src/jsobj.cpp
js/src/vm/Runtime.h
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1520,18 +1520,20 @@ JSObject *
 js::NewObjectWithGivenProto(ExclusiveContext *cxArg, const js::Class *clasp,
                             js::TaggedProto protoArg, JSObject *parentArg,
                             gc::AllocKind allocKind, NewObjectKind newKind)
 {
     if (CanBeFinalizedInBackground(allocKind, clasp))
         allocKind = GetBackgroundAllocKind(allocKind);
 
     NewObjectCache::EntryIndex entry = -1;
+    uint64_t gcNumber = 0;
     if (JSContext *cx = cxArg->maybeJSContext()) {
-        NewObjectCache &cache = cx->runtime()->newObjectCache;
+        JSRuntime *rt = cx->runtime();
+        NewObjectCache &cache = rt->newObjectCache;
         if (protoArg.isObject() &&
             newKind == GenericObject &&
             !cx->compartment()->hasObjectMetadataCallback() &&
             (!parentArg || parentArg == protoArg.toObject()->getParent()) &&
             !protoArg.toObject()->is<GlobalObject>())
         {
             if (cache.lookupProto(clasp, protoArg.toObject(), allocKind, &entry)) {
                 JSObject *obj = cache.newObjectFromHit<NoGC>(cx, entry, GetInitialHeap(newKind, clasp));
@@ -1542,16 +1544,17 @@ js::NewObjectWithGivenProto(ExclusiveCon
                     RootedObject parent(cxArg, parentArg);
                     obj = cache.newObjectFromHit<CanGC>(cx, entry, GetInitialHeap(newKind, clasp));
                     JS_ASSERT(!obj);
                     parentArg = parent;
                     protoArg = proto;
                 }
             }
         }
+        gcNumber = rt->gc.gcNumber();
     }
 
     Rooted<TaggedProto> proto(cxArg, protoArg);
     RootedObject parent(cxArg, parentArg);
 
     types::TypeObject *type = cxArg->getNewType(clasp, proto, nullptr);
     if (!type)
         return nullptr;
@@ -1562,17 +1565,19 @@ js::NewObjectWithGivenProto(ExclusiveCon
      */
     if (!parent && proto.isObject())
         parent = proto.toObject()->getParent();
 
     RootedObject obj(cxArg, NewObject(cxArg, type, parent, allocKind, newKind));
     if (!obj)
         return nullptr;
 
-    if (entry != -1 && !obj->hasDynamicSlots()) {
+    if (entry != -1 && !obj->hasDynamicSlots() &&
+        cxArg->asJSContext()->runtime()->gc.gcNumber() == gcNumber)
+    {
         cxArg->asJSContext()->runtime()->newObjectCache.fillProto(entry, clasp,
                                                                   proto, allocKind, obj);
     }
 
     return obj;
 }
 
 static JSProtoKey
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -310,28 +310,33 @@ class NewObjectCache
         JS_ASSERT(obj->type() == type);
         return fill(entry, type->clasp(), type, kind, obj);
     }
 
     /* Invalidate any entries which might produce an object with shape/proto. */
     void invalidateEntriesForShape(JSContext *cx, HandleShape shape, HandleObject proto);
 
   private:
-    bool lookup(const Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry) {
+    EntryIndex makeIndex(const Class *clasp, gc::Cell *key, gc::AllocKind kind) {
         uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + kind;
-        *pentry = hash % mozilla::ArrayLength(entries);
+        return hash % mozilla::ArrayLength(entries);
+    }
 
+    bool lookup(const Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry) {
+        *pentry = makeIndex(clasp, key, kind);
         Entry *entry = &entries[*pentry];
 
         /* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
         return entry->clasp == clasp && entry->key == key;
     }
 
-    void fill(EntryIndex entry_, const Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj) {
+    void fill(EntryIndex entry_, const Class *clasp, gc::Cell *key, gc::AllocKind kind,
+              JSObject *obj) {
         JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
+        JS_ASSERT(entry_ == makeIndex(clasp, key, kind));
         Entry *entry = &entries[entry_];
 
         JS_ASSERT(!obj->hasDynamicSlots() && !obj->hasDynamicElements());
 
         entry->clasp = clasp;
         entry->key = key;
         entry->kind = kind;