Bug 1461556 - Don't PodZero ObjectGroup instances inside the ObjectGroup constructor -- set most fields using member-initializers in the constructor, and add initializers in the class body for the remaining two fields. r=jandem
authorJeff Walden <jwalden@mit.edu>
Fri, 18 May 2018 11:45:26 -0700
changeset 418925 441f59473bfa
parent 418924 562e5ddb5332
child 418926 7658d2d1e0d7
push id103419
push userjwalden@mit.edu
push date2018-05-18 19:33 +0000
treeherdermozilla-inbound@7658d2d1e0d7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1461556
milestone62.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 1461556 - Don't PodZero ObjectGroup instances inside the ObjectGroup constructor -- set most fields using member-initializers in the constructor, and add initializers in the class body for the remaining two fields. r=jandem
js/src/vm/ObjectGroup.cpp
js/src/vm/ObjectGroup.h
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -31,28 +31,25 @@ using namespace js;
 using mozilla::PodZero;
 
 /////////////////////////////////////////////////////////////////////
 // ObjectGroup
 /////////////////////////////////////////////////////////////////////
 
 ObjectGroup::ObjectGroup(const Class* clasp, TaggedProto proto, JS::Realm* realm,
                          ObjectGroupFlags initialFlags)
+  : clasp_(clasp),
+    proto_(proto),
+    realm_(realm),
+    flags_(initialFlags)
 {
-    PodZero(this);
-
     /* Windows may not appear on prototype chains. */
     MOZ_ASSERT_IF(proto.isObject(), !IsWindow(proto.toObject()));
     MOZ_ASSERT(JS::StringIsASCII(clasp->name));
 
-    this->clasp_ = clasp;
-    this->proto_ = proto;
-    this->realm_ = realm;
-    this->flags_ = initialFlags;
-
     setGeneration(zone()->types.generation);
 }
 
 void
 ObjectGroup::finalize(FreeOp* fop)
 {
     if (newScriptDontCheckGeneration())
         newScriptDontCheckGeneration()->clear();
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -82,27 +82,107 @@ enum NewObjectKind {
  * information is sensitive to changes in the property's type. Future changes
  * to the property (whether those uncovered by analysis or those occurring
  * in the VM) will treat these properties like those of any other object group.
  */
 
 /* Type information about an object accessed by a script. */
 class ObjectGroup : public gc::TenuredCell
 {
+  public:
+    class Property;
+
+  private:
+    /* Class shared by objects in this group. */
+    const Class* clasp_; // set by constructor
+
+    /* Prototype shared by objects in this group. */
+    GCPtr<TaggedProto> proto_; // set by constructor
+
+    /* Realm shared by objects in this group. */
+    JS::Realm* realm_;; // set by constructor
+
+    /* Flags for this group. */
+    ObjectGroupFlags flags_; // set by constructor
+
+    // If non-null, holds additional information about this object, whose
+    // format is indicated by the object's addendum kind.
+    void* addendum_ = nullptr;
+
+    /*
+     * Properties of this object.
+     *
+     * The type sets in the properties of a group describe the possible values
+     * that can be read out of that property in actual JS objects. In native
+     * objects, property types account for plain data properties (those with a
+     * slot and no getter or setter hook) and dense elements. In typed objects
+     * and unboxed objects, property types account for object and value
+     * properties and elements in the object, and expando properties in unboxed
+     * objects.
+     *
+     * For accesses on these properties, the correspondence is as follows:
+     *
+     * 1. If the group has unknownProperties(), the possible properties and
+     *    value types for associated JSObjects are unknown.
+     *
+     * 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
+     *    in |obj|, before obj->getProperty(id) the property in |group| for
+     *    |id| must reflect the result of the getProperty.
+     *
+     * There are several exceptions to this:
+     *
+     * 1. For properties of global JS objects which are undefined at the point
+     *    where the property was (lazily) generated, the property type set will
+     *    remain empty, and the 'undefined' type will only be added after a
+     *    subsequent assignment or deletion. After these properties have been
+     *    assigned a defined value, the only way they can become undefined
+     *    again is after such an assign or deletion.
+     *
+     * 2. Array lengths are special cased by the compiler and VM and are not
+     *    reflected in property types.
+     *
+     * 3. In typed objects (but not unboxed objects), the initial values of
+     *    properties (null pointers and undefined values) are not reflected in
+     *    the property types. These values are always possible when reading the
+     *    property.
+     *
+     * We establish these by using write barriers on calls to setProperty and
+     * defineProperty which are on native properties, and on any jitcode which
+     * might update the property with a new type.
+     */
+    Property** propertySet = nullptr;
+
+    // END OF PROPERTIES
+
+  private:
+    static inline uint32_t offsetOfClasp() {
+        return offsetof(ObjectGroup, clasp_);
+    }
+
+    static inline uint32_t offsetOfProto() {
+        return offsetof(ObjectGroup, proto_);
+    }
+
+    static inline uint32_t offsetOfRealm() {
+        return offsetof(ObjectGroup, realm_);
+    }
+
+    static inline uint32_t offsetOfFlags() {
+        return offsetof(ObjectGroup, flags_);
+    }
+
+    static inline uint32_t offsetOfAddendum() {
+        return offsetof(ObjectGroup, addendum_);
+    }
+
     friend class gc::GCRuntime;
     friend class gc::GCTrace;
 
-    /* Class shared by objects in this group. */
-    const Class* clasp_;
-
-    /* Prototype shared by objects in this group. */
-    GCPtr<TaggedProto> proto_;
-
-    /* Realm shared by objects in this group. */
-    JS::Realm* realm_;
+    // See JSObject::offsetOfGroup() comment.
+    friend class js::jit::MacroAssembler;
 
   public:
     const Class* clasp() const {
         return clasp_;
     }
 
     void setClasp(const Class* clasp) {
         MOZ_ASSERT(JS::StringIsASCII(clasp->name));
@@ -151,20 +231,16 @@ class ObjectGroup : public gc::TenuredCe
         MOZ_ASSERT_IF(res, singleton());
         return res;
     }
 
     JSCompartment* compartment() const { return JS::GetCompartmentForRealm(realm_); }
     JSCompartment* maybeCompartment() const { return compartment(); }
     JS::Realm* realm() const { return realm_; }
 
-  private:
-    /* Flags for this group. */
-    ObjectGroupFlags flags_;
-
   public:
     // Kinds of addendums which can be attached to ObjectGroups.
     enum AddendumKind {
         Addendum_None,
 
         // When used by interpreted function, the addendum stores the
         // canonical JSFunction object.
         Addendum_InterpretedFunction,
@@ -186,20 +262,16 @@ class ObjectGroup : public gc::TenuredCe
         // objects, the addendum points to that unboxed group.
         Addendum_OriginalUnboxedGroup,
 
         // When used by typed objects, the addendum stores a TypeDescr.
         Addendum_TypeDescr
     };
 
   private:
-    // If non-null, holds additional information about this object, whose
-    // format is indicated by the object's addendum kind.
-    void* addendum_;
-
     void setAddendum(AddendumKind kind, void* addendum, bool writeBarrier = true);
 
     AddendumKind addendumKind() const {
         return (AddendumKind)
             ((flags_ & OBJECT_FLAG_ADDENDUM_MASK) >> OBJECT_FLAG_ADDENDUM_SHIFT);
     }
 
     TypeNewScript* newScriptDontCheckGeneration() const {
@@ -328,59 +400,16 @@ class ObjectGroup : public gc::TenuredCe
         Property(const Property& o)
           : 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; }
     };
 
-  private:
-    /*
-     * Properties of this object.
-     *
-     * The type sets in the properties of a group describe the possible values
-     * that can be read out of that property in actual JS objects. In native
-     * objects, property types account for plain data properties (those with a
-     * slot and no getter or setter hook) and dense elements. In typed objects
-     * and unboxed objects, property types account for object and value
-     * properties and elements in the object, and expando properties in unboxed
-     * objects.
-     *
-     * For accesses on these properties, the correspondence is as follows:
-     *
-     * 1. If the group has unknownProperties(), the possible properties and
-     *    value types for associated JSObjects are unknown.
-     *
-     * 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
-     *    in |obj|, before obj->getProperty(id) the property in |group| for
-     *    |id| must reflect the result of the getProperty.
-     *
-     * There are several exceptions to this:
-     *
-     * 1. For properties of global JS objects which are undefined at the point
-     *    where the property was (lazily) generated, the property type set will
-     *    remain empty, and the 'undefined' type will only be added after a
-     *    subsequent assignment or deletion. After these properties have been
-     *    assigned a defined value, the only way they can become undefined
-     *    again is after such an assign or deletion.
-     *
-     * 2. Array lengths are special cased by the compiler and VM and are not
-     *    reflected in property types.
-     *
-     * 3. In typed objects (but not unboxed objects), the initial values of
-     *    properties (null pointers and undefined values) are not reflected in
-     *    the property types. These values are always possible when reading the
-     *    property.
-     *
-     * We establish these by using write barriers on calls to setProperty and
-     * defineProperty which are on native properties, and on any jitcode which
-     * might update the property with a new type.
-     */
-    Property** propertySet;
   public:
 
     inline ObjectGroup(const Class* clasp, TaggedProto proto, JS::Realm* realm,
                        ObjectGroupFlags initialFlags);
 
     inline bool hasAnyFlags(const AutoSweepObjectGroup& sweep, ObjectGroupFlags flags);
     inline bool hasAllFlags(const AutoSweepObjectGroup& sweep, ObjectGroupFlags flags);
 
@@ -459,40 +488,16 @@ class ObjectGroup : public gc::TenuredCe
     }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     void finalize(FreeOp* fop);
 
     static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
 
-  private:
-    // See JSObject::offsetOfGroup() comment.
-    friend class js::jit::MacroAssembler;
-
-    static inline uint32_t offsetOfClasp() {
-        return offsetof(ObjectGroup, clasp_);
-    }
-
-    static inline uint32_t offsetOfProto() {
-        return offsetof(ObjectGroup, proto_);
-    }
-
-    static inline uint32_t offsetOfRealm() {
-        return offsetof(ObjectGroup, realm_);
-    }
-
-    static inline uint32_t offsetOfAddendum() {
-        return offsetof(ObjectGroup, addendum_);
-    }
-
-    static inline uint32_t offsetOfFlags() {
-        return offsetof(ObjectGroup, flags_);
-    }
-
   public:
     const ObjectGroupFlags* addressOfFlags() const {
         return &flags_;
     }
 
     // Get the bit pattern stored in an object's addendum when it has an
     // original unboxed group.
     static inline int32_t addendumOriginalUnboxedGroupValue() {