Bug 973238 Part 7 -- Remove type object addendum; leave the addendum mechanism in place r=bhackett
authorNicholas D. Matsakis <nmatsakis@mozilla.com>
Tue, 11 Mar 2014 13:44:58 -0400
changeset 206611 3e9ea27401838363e58d8908bd320ef13fd8d04f
parent 206610 4903226b4f2ff4f6c44fe08e91e5dff0e163741d
child 206612 880fd861075fb7d434080053bd5863dc1fe5a720
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs973238
milestone32.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 973238 Part 7 -- Remove type object addendum; leave the addendum mechanism in place r=bhackett
CLOBBER
js/src/builtin/TypedObject.cpp
js/src/gc/Marking.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 973238 part 6 needs clobber due to self-hosted code (bug 1019955).
+Bug 973238 part 7 needs clobber due to self-hosted code (bug 1019955).
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1478,26 +1478,16 @@ TypedObject::createUnattachedWithClass(J
         return nullptr;
 
     obj->initPrivate(nullptr);
     obj->initReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0));
     obj->initReservedSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(length));
     obj->initReservedSlot(JS_BUFVIEW_SLOT_OWNER, NullValue());
     obj->initReservedSlot(JS_BUFVIEW_SLOT_NEXT_VIEW, PrivateValue(nullptr));
 
-    // Tag the type object for this instance with the type
-    // representation, if that has not been done already.
-    if (!type->is<SimpleTypeDescr>()) { // FIXME Bug 929651
-        RootedTypeObject typeObj(cx, obj->getType(cx));
-        if (typeObj) {
-            if (!typeObj->addTypedObjectAddendum(cx, type))
-                return nullptr;
-        }
-    }
-
     return static_cast<TypedObject*>(&*obj);
 }
 
 void
 TypedObject::attach(ArrayBufferObject &buffer, int32_t offset)
 {
     JS_ASSERT(offset >= 0);
     JS_ASSERT((size_t) (offset + size()) <= buffer.byteLength());
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1279,18 +1279,16 @@ ScanTypeObject(GCMarker *gcmarker, types
         PushMarkStack(gcmarker, type->proto().toObject());
 
     if (type->singleton() && !type->lazy())
         PushMarkStack(gcmarker, type->singleton());
 
     if (type->hasNewScript()) {
         PushMarkStack(gcmarker, type->newScript()->fun);
         PushMarkStack(gcmarker, type->newScript()->templateObject);
-    } else if (type->hasTypedObject()) {
-        PushMarkStack(gcmarker, type->typedObject()->descrHeapPtr());
     }
 
     if (type->interpretedFunction)
         PushMarkStack(gcmarker, type->interpretedFunction);
 }
 
 static void
 gc::MarkChildren(JSTracer *trc, types::TypeObject *type)
@@ -1306,18 +1304,16 @@ gc::MarkChildren(JSTracer *trc, types::T
         MarkObject(trc, &type->protoRaw(), "type_proto");
 
     if (type->singleton() && !type->lazy())
         MarkObject(trc, &type->singletonRaw(), "type_singleton");
 
     if (type->hasNewScript()) {
         MarkObject(trc, &type->newScript()->fun, "type_new_function");
         MarkObject(trc, &type->newScript()->templateObject, "type_new_template");
-    } else if (type->hasTypedObject()) {
-        MarkObject(trc, &type->typedObject()->descrHeapPtr(), "type_heap_ptr");
     }
 
     if (type->interpretedFunction)
         MarkObject(trc, &type->interpretedFunction, "type_function");
 }
 
 static void
 gc::MarkChildren(JSTracer *trc, jit::JitCode *code)
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3036,16 +3036,39 @@ TypeObject::markUnknown(ExclusiveContext
         if (prop) {
             prop->types.addType(cx, Type::UnknownType());
             prop->types.setNonDataProperty(cx);
         }
     }
 }
 
 void
+TypeObject::maybeClearNewScriptAddendumOnOOM()
+{
+    if (!isMarked())
+        return;
+
+    if (!addendum || addendum->kind != TypeObjectAddendum::NewScript)
+        return;
+
+    for (unsigned i = 0; i < getPropertyCount(); i++) {
+        Property *prop = getProperty(i);
+        if (!prop)
+            continue;
+        if (prop->types.definiteProperty())
+            prop->types.setNonDataPropertyIgnoringConstraints();
+    }
+
+    // This method is called during GC sweeping, so there is no write barrier
+    // that needs to be triggered.
+    js_free(addendum);
+    addendum.unsafeSet(nullptr);
+}
+
+void
 TypeObject::clearAddendum(ExclusiveContext *cx)
 {
     JS_ASSERT(!(flags() & OBJECT_FLAG_ADDENDUM_CLEARED));
 
     addFlags(OBJECT_FLAG_ADDENDUM_CLEARED);
 
     /*
      * It is possible for the object to not have a new script or other
@@ -3059,20 +3082,16 @@ TypeObject::clearAddendum(ExclusiveConte
      */
     if (!addendum)
         return;
 
     switch (addendum->kind) {
       case TypeObjectAddendum::NewScript:
         clearNewScriptAddendum(cx);
         break;
-
-      case TypeObjectAddendum::TypedObject:
-        clearTypedObjectAddendum(cx);
-        break;
     }
 
     /* We nullptr out addendum *before* freeing it so the write barrier works. */
     TypeObjectAddendum *savedAddendum = addendum;
     addendum = nullptr;
     js_free(savedAddendum);
 
     markStateChange(cx);
@@ -3178,44 +3197,16 @@ TypeObject::clearNewScriptAddendum(Exclu
         }
     } else {
         // Threads with an ExclusiveContext are not allowed to run scripts.
         JS_ASSERT(!cx->perThreadData->activation());
     }
 }
 
 void
-TypeObject::maybeClearNewScriptAddendumOnOOM()
-{
-    if (!isMarked())
-        return;
-
-    if (!addendum || addendum->kind != TypeObjectAddendum::NewScript)
-        return;
-
-    for (unsigned i = 0; i < getPropertyCount(); i++) {
-        Property *prop = getProperty(i);
-        if (!prop)
-            continue;
-        if (prop->types.definiteProperty())
-            prop->types.setNonDataPropertyIgnoringConstraints();
-    }
-
-    // This method is called during GC sweeping, so there is no write barrier
-    // that needs to be triggered.
-    js_free(addendum);
-    addendum.unsafeSet(nullptr);
-}
-
-void
-TypeObject::clearTypedObjectAddendum(ExclusiveContext *cx)
-{
-}
-
-void
 TypeObject::print()
 {
     TaggedProto tagged(proto());
     fprintf(stderr, "%s : %s",
             TypeObjectString(this),
             tagged.isObject() ? TypeString(Type::ObjectType(tagged.toObject()))
                               : (tagged.isLazy() ? "(lazy)" : "(null)"));
 
@@ -4557,67 +4548,22 @@ TypeScript::printTypes(JSContext *cx, Ha
             fprintf(stderr, "\n");
         }
     }
 
     fprintf(stderr, "\n");
 }
 #endif /* DEBUG */
 
-/////////////////////////////////////////////////////////////////////
-// Binary data
-/////////////////////////////////////////////////////////////////////
-
 void
 TypeObject::setAddendum(TypeObjectAddendum *addendum)
 {
     this->addendum = addendum;
 }
 
-bool
-TypeObject::addTypedObjectAddendum(JSContext *cx, Handle<TypeDescr*> descr)
-{
-    // Type descriptors are always pre-tenured. This is both because
-    // we expect them to live a long time and so that they can be
-    // safely accessed during ion compilation.
-    JS_ASSERT(!IsInsideNursery(descr));
-    JS_ASSERT(descr);
-
-    if (flags() & OBJECT_FLAG_ADDENDUM_CLEARED)
-        return true;
-
-    JS_ASSERT(!unknownProperties());
-
-    if (addendum) {
-        JS_ASSERT(hasTypedObject());
-        JS_ASSERT(&typedObject()->descr() == descr);
-        return true;
-    }
-
-    TypeTypedObject *typedObject = js_new<TypeTypedObject>(descr);
-    if (!typedObject)
-        return false;
-    addendum = typedObject;
-    return true;
-}
-
-/////////////////////////////////////////////////////////////////////
-// Type object addenda constructor
-/////////////////////////////////////////////////////////////////////
-
 TypeObjectAddendum::TypeObjectAddendum(Kind kind)
   : kind(kind)
 {}
 
 TypeNewScript::TypeNewScript()
   : TypeObjectAddendum(NewScript)
 {}
 
-TypeTypedObject::TypeTypedObject(Handle<TypeDescr*> descr)
-  : TypeObjectAddendum(TypedObject),
-    descr_(descr)
-{
-}
-
-TypeDescr &
-js::types::TypeTypedObject::descr() {
-    return descr_->as<TypeDescr>();
-}
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -807,47 +807,36 @@ struct Property
       : id(o.id.get()), types(o.types)
     {}
 
     static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
     static jsid getKey(Property *p) { return p->id; }
 };
 
 struct TypeNewScript;
-struct TypeTypedObject;
 
 struct TypeObjectAddendum
 {
     enum Kind {
-        NewScript,
-        TypedObject
+        NewScript
     };
 
     explicit TypeObjectAddendum(Kind kind);
 
     const Kind kind;
 
     bool isNewScript() {
         return kind == NewScript;
     }
 
     TypeNewScript *asNewScript() {
         JS_ASSERT(isNewScript());
         return (TypeNewScript*) this;
     }
 
-    bool isTypedObject() {
-        return kind == TypedObject;
-    }
-
-    TypeTypedObject *asTypedObject() {
-        JS_ASSERT(isTypedObject());
-        return (TypeTypedObject*) this;
-    }
-
     static inline void writeBarrierPre(TypeObjectAddendum *type);
 
     static void writeBarrierPost(TypeObjectAddendum *newScript, void *addr) {}
 };
 
 /*
  * Information attached to a TypeObject if it is always constructed using 'new'
  * on a particular script. This is used to manage state related to the definite
@@ -894,31 +883,16 @@ struct TypeNewScript : public TypeObject
           : kind(kind), offset(offset)
         {}
     };
     Initializer *initializerList;
 
     static inline void writeBarrierPre(TypeNewScript *newScript);
 };
 
-struct TypeTypedObject : public TypeObjectAddendum
-{
-  private:
-    HeapPtrObject descr_;
-
-  public:
-    explicit TypeTypedObject(Handle<TypeDescr*> descr);
-
-    HeapPtrObject &descrHeapPtr() {
-        return descr_;
-    }
-
-    TypeDescr &descr();
-};
-
 /*
  * Lazy type objects overview.
  *
  * Type objects which represent at most one JS object are constructed lazily.
  * These include types for native functions, standard classes, scripted
  * functions defined at the top level of global/eval scripts, and in some
  * other cases. Typical web workloads often create many windows (and many
  * copies of standard natives) and many scripts, with comparatively few
@@ -1022,35 +996,18 @@ struct TypeObject : gc::BarrieredCell<Ty
     bool hasNewScript() const {
         return addendum && addendum->isNewScript();
     }
 
     TypeNewScript *newScript() {
         return addendum->asNewScript();
     }
 
-    bool hasTypedObject() {
-        return addendum && addendum->isTypedObject();
-    }
-
-    TypeTypedObject *typedObject() {
-        return addendum->asTypedObject();
-    }
-
     void setAddendum(TypeObjectAddendum *addendum);
 
-    /*
-     * Tag the type object for a binary data type descriptor, instance,
-     * or handle with the type representation of the data it points at.
-     * If this type object is already tagged with a binary data addendum,
-     * this addendum must already be associated with the same TypeRepresentation,
-     * and the method has no effect.
-     */
-    bool addTypedObjectAddendum(JSContext *cx, Handle<TypeDescr*> descr);
-
   private:
     /*
      * Properties of this object. This may contain JSID_VOID, representing the
      * types of all integer indexes of the object, and/or JSID_EMPTY, holding
      * constraints listening to changes to the object's state.
      *
      * The type sets in the properties of a type object describe the possible
      * values that can be read out of that property in actual JS objects.
@@ -1152,20 +1109,19 @@ struct TypeObject : gc::BarrieredCell<Ty
     void addPrototype(JSContext *cx, TypeObject *proto);
     void addPropertyType(ExclusiveContext *cx, jsid id, Type type);
     void addPropertyType(ExclusiveContext *cx, jsid id, const Value &value);
     void markPropertyNonData(ExclusiveContext *cx, jsid id);
     void markPropertyNonWritable(ExclusiveContext *cx, jsid id);
     void markStateChange(ExclusiveContext *cx);
     void setFlags(ExclusiveContext *cx, TypeObjectFlags flags);
     void markUnknown(ExclusiveContext *cx);
+    void maybeClearNewScriptAddendumOnOOM();
     void clearAddendum(ExclusiveContext *cx);
     void clearNewScriptAddendum(ExclusiveContext *cx);
-    void clearTypedObjectAddendum(ExclusiveContext *cx);
-    void maybeClearNewScriptAddendumOnOOM();
     bool isPropertyNonData(jsid id);
     bool isPropertyNonWritable(jsid id);
 
     void print();
 
     inline void clearProperties();
     inline void sweep(FreeOp *fop, bool *oom);
 
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1219,19 +1219,16 @@ TypeObjectAddendum::writeBarrierPre(Type
 {
 #ifdef JSGC_INCREMENTAL
     if (!type)
         return;
 
     switch (type->kind) {
       case NewScript:
         return TypeNewScript::writeBarrierPre(type->asNewScript());
-
-      case TypedObject:
-        return TypeTypedObject::writeBarrierPre(type->asTypedObject());
     }
 #endif
 }
 
 inline void
 TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
 {
 #ifdef JSGC_INCREMENTAL