LCOV - code coverage report
Current view: top level - js/src/vm - ObjectGroup.h (source / functions) Hit Total Coverage
Test: output.info Lines: 107 133 80.5 %
Date: 2017-07-14 16:53:18 Functions: 39 47 83.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef vm_ObjectGroup_h
       8             : #define vm_ObjectGroup_h
       9             : 
      10             : #include "jsbytecode.h"
      11             : #include "jsfriendapi.h"
      12             : 
      13             : #include "ds/IdValuePair.h"
      14             : #include "gc/Barrier.h"
      15             : #include "js/CharacterEncoding.h"
      16             : #include "js/GCHashTable.h"
      17             : #include "vm/TaggedProto.h"
      18             : #include "vm/TypeInference.h"
      19             : 
      20             : namespace js {
      21             : 
      22             : class TypeDescr;
      23             : class UnboxedLayout;
      24             : 
      25             : class PreliminaryObjectArrayWithTemplate;
      26             : class TypeNewScript;
      27             : class HeapTypeSet;
      28             : class AutoClearTypeInferenceStateOnOOM;
      29             : class CompilerConstraintList;
      30             : 
      31             : namespace gc {
      32             : void MergeCompartments(JSCompartment* source, JSCompartment* target);
      33             : } // namespace gc
      34             : 
      35             : /*
      36             :  * The NewObjectKind allows an allocation site to specify the type properties
      37             :  * and lifetime requirements that must be fixed at allocation time.
      38             :  */
      39             : enum NewObjectKind {
      40             :     /* This is the default. Most objects are generic. */
      41             :     GenericObject,
      42             : 
      43             :     /*
      44             :      * Singleton objects are treated specially by the type system. This flag
      45             :      * ensures that the new object is automatically set up correctly as a
      46             :      * singleton and is allocated in the tenured heap.
      47             :      */
      48             :     SingletonObject,
      49             : 
      50             :     /*
      51             :      * CrossCompartmentWrappers use the common Proxy class, but are allowed
      52             :      * to have nursery lifetime.
      53             :      */
      54             :     NurseryAllocatedProxy,
      55             : 
      56             :     /*
      57             :      * Objects which will not benefit from being allocated in the nursery
      58             :      * (e.g. because they are known to have a long lifetime) may be allocated
      59             :      * with this kind to place them immediately into the tenured generation.
      60             :      */
      61             :     TenuredObject
      62             : };
      63             : 
      64             : /*
      65             :  * Lazy object groups overview.
      66             :  *
      67             :  * Object groups which represent at most one JS object are constructed lazily.
      68             :  * These include groups for native functions, standard classes, scripted
      69             :  * functions defined at the top level of global/eval scripts, objects which
      70             :  * dynamically become the prototype of some other object, and in some other
      71             :  * cases. Typical web workloads often create many windows (and many copies of
      72             :  * standard natives) and many scripts, with comparatively few non-singleton
      73             :  * groups.
      74             :  *
      75             :  * We can recover the type information for the object from examining it,
      76             :  * so don't normally track the possible types of its properties as it is
      77             :  * updated. Property type sets for the object are only constructed when an
      78             :  * analyzed script attaches constraints to it: the script is querying that
      79             :  * property off the object or another which delegates to it, and the analysis
      80             :  * information is sensitive to changes in the property's type. Future changes
      81             :  * to the property (whether those uncovered by analysis or those occurring
      82             :  * in the VM) will treat these properties like those of any other object group.
      83             :  */
      84             : 
      85             : /* Type information about an object accessed by a script. */
      86             : class ObjectGroup : public gc::TenuredCell
      87             : {
      88             :     friend void gc::MergeCompartments(JSCompartment* source, JSCompartment* target);
      89             : 
      90             :     /* Class shared by objects in this group. */
      91             :     const Class* clasp_;
      92             : 
      93             :     /* Prototype shared by objects in this group. */
      94             :     GCPtr<TaggedProto> proto_;
      95             : 
      96             :     /* Compartment shared by objects in this group. */
      97             :     JSCompartment* compartment_;
      98             : 
      99             :   public:
     100             : 
     101    13223938 :     const Class* clasp() const {
     102    13223938 :         return clasp_;
     103             :     }
     104             : 
     105        2927 :     void setClasp(const Class* clasp) {
     106        2927 :         MOZ_ASSERT(JS::StringIsASCII(clasp->name));
     107        2927 :         clasp_ = clasp;
     108        2927 :     }
     109             : 
     110             :     bool hasDynamicPrototype() const {
     111             :         return proto_.isDynamic();
     112             :     }
     113             : 
     114             :     const GCPtr<TaggedProto>& proto() const {
     115             :         return proto_;
     116             :     }
     117             : 
     118     1136473 :     GCPtr<TaggedProto>& proto() {
     119     1136473 :         return proto_;
     120             :     }
     121             : 
     122             :     void setProto(TaggedProto proto);
     123             :     void setProtoUnchecked(TaggedProto proto);
     124             : 
     125      704723 :     bool singleton() const {
     126      704723 :         return flagsDontCheckGeneration() & OBJECT_FLAG_SINGLETON;
     127             :     }
     128             : 
     129      731645 :     bool lazy() const {
     130      731645 :         bool res = flagsDontCheckGeneration() & OBJECT_FLAG_LAZY_SINGLETON;
     131      731635 :         MOZ_ASSERT_IF(res, singleton());
     132      731635 :         return res;
     133             :     }
     134             : 
     135     2004655 :     JSCompartment* compartment() const { return compartment_; }
     136        5744 :     JSCompartment* maybeCompartment() const { return compartment(); }
     137             : 
     138             :   private:
     139             :     /* Flags for this group. */
     140             :     ObjectGroupFlags flags_;
     141             : 
     142             :   public:
     143             :     // Kinds of addendums which can be attached to ObjectGroups.
     144             :     enum AddendumKind {
     145             :         Addendum_None,
     146             : 
     147             :         // When used by interpreted function, the addendum stores the
     148             :         // canonical JSFunction object.
     149             :         Addendum_InterpretedFunction,
     150             : 
     151             :         // When used by the 'new' group when constructing an interpreted
     152             :         // function, the addendum stores a TypeNewScript.
     153             :         Addendum_NewScript,
     154             : 
     155             :         // For some plain objects, the addendum stores a PreliminaryObjectArrayWithTemplate.
     156             :         Addendum_PreliminaryObjects,
     157             : 
     158             :         // When objects in this group have an unboxed representation, the
     159             :         // addendum stores an UnboxedLayout (which might have a TypeNewScript
     160             :         // as well, if the group is also constructed using 'new').
     161             :         Addendum_UnboxedLayout,
     162             : 
     163             :         // If this group is used by objects that have been converted from an
     164             :         // unboxed representation and/or have the same allocation kind as such
     165             :         // objects, the addendum points to that unboxed group.
     166             :         Addendum_OriginalUnboxedGroup,
     167             : 
     168             :         // When used by typed objects, the addendum stores a TypeDescr.
     169             :         Addendum_TypeDescr
     170             :     };
     171             : 
     172             :   private:
     173             :     // If non-null, holds additional information about this object, whose
     174             :     // format is indicated by the object's addendum kind.
     175             :     void* addendum_;
     176             : 
     177             :     void setAddendum(AddendumKind kind, void* addendum, bool writeBarrier = true);
     178             : 
     179      649804 :     AddendumKind addendumKind() const {
     180             :         return (AddendumKind)
     181      649804 :             ((flags_ & OBJECT_FLAG_ADDENDUM_MASK) >> OBJECT_FLAG_ADDENDUM_SHIFT);
     182             :     }
     183             : 
     184      320372 :     TypeNewScript* newScriptDontCheckGeneration() const {
     185      320372 :         if (addendumKind() == Addendum_NewScript)
     186        8733 :             return reinterpret_cast<TypeNewScript*>(addendum_);
     187      311642 :         return nullptr;
     188             :     }
     189             : 
     190             :     TypeNewScript* anyNewScript();
     191             :     void detachNewScript(bool writeBarrier, ObjectGroup* replacement);
     192             : 
     193     2529899 :     ObjectGroupFlags flagsDontCheckGeneration() const {
     194     2529899 :         return flags_;
     195             :     }
     196             : 
     197             :   public:
     198             : 
     199             :     inline ObjectGroupFlags flags();
     200             :     inline void addFlags(ObjectGroupFlags flags);
     201             :     inline void clearFlags(ObjectGroupFlags flags);
     202             :     inline TypeNewScript* newScript();
     203             : 
     204         196 :     void setNewScript(TypeNewScript* newScript) {
     205         196 :         MOZ_ASSERT(newScript);
     206         196 :         setAddendum(Addendum_NewScript, newScript);
     207         196 :     }
     208           1 :     void detachNewScript() {
     209           1 :         setAddendum(Addendum_None, nullptr);
     210           1 :     }
     211             : 
     212             :     inline PreliminaryObjectArrayWithTemplate* maybePreliminaryObjects();
     213             : 
     214      197172 :     PreliminaryObjectArrayWithTemplate* maybePreliminaryObjectsDontCheckGeneration() {
     215      197172 :         if (addendumKind() == Addendum_PreliminaryObjects)
     216       17935 :             return reinterpret_cast<PreliminaryObjectArrayWithTemplate*>(addendum_);
     217      179237 :         return nullptr;
     218             :     }
     219             : 
     220        3278 :     void setPreliminaryObjects(PreliminaryObjectArrayWithTemplate* preliminaryObjects) {
     221        3278 :         setAddendum(Addendum_PreliminaryObjects, preliminaryObjects);
     222        3278 :     }
     223             : 
     224          58 :     void detachPreliminaryObjects() {
     225          58 :         MOZ_ASSERT(maybePreliminaryObjectsDontCheckGeneration());
     226          58 :         setAddendum(Addendum_None, nullptr);
     227          58 :     }
     228             : 
     229      169048 :     bool hasUnanalyzedPreliminaryObjects() {
     230      337648 :         return (newScriptDontCheckGeneration() && !newScriptDontCheckGeneration()->analyzed()) ||
     231      337648 :                maybePreliminaryObjectsDontCheckGeneration();
     232             :     }
     233             : 
     234             :     inline UnboxedLayout* maybeUnboxedLayout();
     235             :     inline UnboxedLayout& unboxedLayout();
     236             : 
     237       57851 :     UnboxedLayout* maybeUnboxedLayoutDontCheckGeneration() const {
     238       57851 :         if (addendumKind() == Addendum_UnboxedLayout)
     239       14747 :             return reinterpret_cast<UnboxedLayout*>(addendum_);
     240       43104 :         return nullptr;
     241             :     }
     242             : 
     243       14625 :     UnboxedLayout& unboxedLayoutDontCheckGeneration() const {
     244       14625 :         MOZ_ASSERT(addendumKind() == Addendum_UnboxedLayout);
     245       14625 :         return *maybeUnboxedLayoutDontCheckGeneration();
     246             :     }
     247             : 
     248          19 :     void setUnboxedLayout(UnboxedLayout* layout) {
     249          19 :         setAddendum(Addendum_UnboxedLayout, layout);
     250          19 :     }
     251             : 
     252       31423 :     ObjectGroup* maybeOriginalUnboxedGroup() const {
     253       31423 :         if (addendumKind() == Addendum_OriginalUnboxedGroup)
     254           1 :             return reinterpret_cast<ObjectGroup*>(addendum_);
     255       31422 :         return nullptr;
     256             :     }
     257             : 
     258           4 :     void setOriginalUnboxedGroup(ObjectGroup* group) {
     259           4 :         setAddendum(Addendum_OriginalUnboxedGroup, group);
     260           4 :     }
     261             : 
     262         507 :     TypeDescr* maybeTypeDescr() {
     263             :         // Note: there is no need to sweep when accessing the type descriptor
     264             :         // of an object, as it is strongly held and immutable.
     265         507 :         if (addendumKind() == Addendum_TypeDescr)
     266           0 :             return reinterpret_cast<TypeDescr*>(addendum_);
     267         507 :         return nullptr;
     268             :     }
     269             : 
     270           0 :     TypeDescr& typeDescr() {
     271           0 :         MOZ_ASSERT(addendumKind() == Addendum_TypeDescr);
     272           0 :         return *maybeTypeDescr();
     273             :     }
     274             : 
     275           0 :     void setTypeDescr(TypeDescr* descr) {
     276           0 :         setAddendum(Addendum_TypeDescr, descr);
     277           0 :     }
     278             : 
     279        1141 :     JSFunction* maybeInterpretedFunction() {
     280             :         // Note: as with type descriptors, there is no need to sweep when
     281             :         // accessing the interpreted function associated with an object.
     282        1141 :         if (addendumKind() == Addendum_InterpretedFunction)
     283         340 :             return reinterpret_cast<JSFunction*>(addendum_);
     284         801 :         return nullptr;
     285             :     }
     286             : 
     287       22790 :     void setInterpretedFunction(JSFunction* fun) {
     288       22790 :         setAddendum(Addendum_InterpretedFunction, fun);
     289       22790 :     }
     290             : 
     291             :     class Property
     292             :     {
     293             :       public:
     294             :         // Identifier for this property, JSID_VOID for the aggregate integer
     295             :         // index property, or JSID_EMPTY for properties holding constraints
     296             :         // listening to changes in the group's state.
     297             :         GCPtrId id;
     298             : 
     299             :         // Possible own types for this property.
     300             :         HeapTypeSet types;
     301             : 
     302       24801 :         explicit Property(jsid id)
     303       24801 :           : id(id)
     304       24801 :         {}
     305             : 
     306           0 :         Property(const Property& o)
     307           0 :           : id(o.id.get()), types(o.types)
     308           0 :         {}
     309             : 
     310       38845 :         static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
     311      258325 :         static jsid getKey(Property* p) { return p->id; }
     312             :     };
     313             : 
     314             :   private:
     315             :     /*
     316             :      * Properties of this object.
     317             :      *
     318             :      * The type sets in the properties of a group describe the possible values
     319             :      * that can be read out of that property in actual JS objects. In native
     320             :      * objects, property types account for plain data properties (those with a
     321             :      * slot and no getter or setter hook) and dense elements. In typed objects
     322             :      * and unboxed objects, property types account for object and value
     323             :      * properties and elements in the object, and expando properties in unboxed
     324             :      * objects.
     325             :      *
     326             :      * For accesses on these properties, the correspondence is as follows:
     327             :      *
     328             :      * 1. If the group has unknownProperties(), the possible properties and
     329             :      *    value types for associated JSObjects are unknown.
     330             :      *
     331             :      * 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
     332             :      *    in |obj|, before obj->getProperty(id) the property in |group| for
     333             :      *    |id| must reflect the result of the getProperty.
     334             :      *
     335             :      * There are several exceptions to this:
     336             :      *
     337             :      * 1. For properties of global JS objects which are undefined at the point
     338             :      *    where the property was (lazily) generated, the property type set will
     339             :      *    remain empty, and the 'undefined' type will only be added after a
     340             :      *    subsequent assignment or deletion. After these properties have been
     341             :      *    assigned a defined value, the only way they can become undefined
     342             :      *    again is after such an assign or deletion.
     343             :      *
     344             :      * 2. Array lengths are special cased by the compiler and VM and are not
     345             :      *    reflected in property types.
     346             :      *
     347             :      * 3. In typed objects (but not unboxed objects), the initial values of
     348             :      *    properties (null pointers and undefined values) are not reflected in
     349             :      *    the property types. These values are always possible when reading the
     350             :      *    property.
     351             :      *
     352             :      * We establish these by using write barriers on calls to setProperty and
     353             :      * defineProperty which are on native properties, and on any jitcode which
     354             :      * might update the property with a new type.
     355             :      */
     356             :     Property** propertySet;
     357             :   public:
     358             : 
     359             :     inline ObjectGroup(const Class* clasp, TaggedProto proto, JSCompartment* comp,
     360             :                        ObjectGroupFlags initialFlags);
     361             : 
     362             :     inline bool hasAnyFlags(ObjectGroupFlags flags);
     363             :     inline bool hasAllFlags(ObjectGroupFlags flags);
     364             : 
     365           0 :     bool hasAllFlagsDontCheckGeneration(ObjectGroupFlags flags) {
     366           0 :         MOZ_ASSERT((flags & OBJECT_FLAG_DYNAMIC_MASK) == flags);
     367           0 :         return (this->flagsDontCheckGeneration() & flags) == flags;
     368             :     }
     369             : 
     370             :     inline bool unknownProperties();
     371             : 
     372           0 :     bool unknownPropertiesDontCheckGeneration() {
     373           0 :         MOZ_ASSERT_IF(flagsDontCheckGeneration() & OBJECT_FLAG_UNKNOWN_PROPERTIES,
     374             :                       hasAllFlagsDontCheckGeneration(OBJECT_FLAG_DYNAMIC_MASK));
     375           0 :         return !!(flagsDontCheckGeneration() & OBJECT_FLAG_UNKNOWN_PROPERTIES);
     376             :     }
     377             : 
     378             :     inline bool shouldPreTenure();
     379             : 
     380             :     gc::InitialHeap initialHeap(CompilerConstraintList* constraints);
     381             : 
     382             :     inline bool canPreTenure();
     383             :     inline bool fromAllocationSite();
     384             :     inline void setShouldPreTenure(JSContext* cx);
     385             : 
     386             :     /*
     387             :      * Get or create a property of this object. Only call this for properties which
     388             :      * a script accesses explicitly.
     389             :      */
     390             :     inline HeapTypeSet* getProperty(JSContext* cx, JSObject* obj, jsid id);
     391             : 
     392             :     /* Get a property only if it already exists. */
     393             :     MOZ_ALWAYS_INLINE HeapTypeSet* maybeGetProperty(jsid id);
     394             : 
     395             :     /*
     396             :      * Iterate through the group's properties. getPropertyCount overapproximates
     397             :      * in the hash case (see SET_ARRAY_SIZE in TypeInference-inl.h), and
     398             :      * getProperty may return nullptr.
     399             :      */
     400             :     inline unsigned getPropertyCount();
     401             :     inline Property* getProperty(unsigned i);
     402             : 
     403             :     /* Helpers */
     404             : 
     405             :     void updateNewPropertyTypes(JSContext* cx, JSObject* obj, jsid id, HeapTypeSet* types);
     406             :     void addDefiniteProperties(JSContext* cx, Shape* shape);
     407             :     bool matchDefiniteProperties(HandleObject obj);
     408             :     void markPropertyNonData(JSContext* cx, JSObject* obj, jsid id);
     409             :     void markPropertyNonWritable(JSContext* cx, JSObject* obj, jsid id);
     410             :     void markStateChange(JSContext* cx);
     411             :     void setFlags(JSContext* cx, ObjectGroupFlags flags);
     412             :     void markUnknown(JSContext* cx);
     413             :     void maybeClearNewScriptOnOOM();
     414             :     void clearNewScript(JSContext* cx, ObjectGroup* replacement = nullptr);
     415             : 
     416             :     void print();
     417             : 
     418             :     inline void clearProperties();
     419             :     void traceChildren(JSTracer* trc);
     420             : 
     421             :     inline bool needsSweep();
     422             :     inline void maybeSweep(AutoClearTypeInferenceStateOnOOM* oom);
     423             : 
     424             :   private:
     425             :     void sweep(AutoClearTypeInferenceStateOnOOM* oom);
     426             : 
     427     1351558 :     uint32_t generation() {
     428     1351558 :         return (flags_ & OBJECT_FLAG_GENERATION_MASK) >> OBJECT_FLAG_GENERATION_SHIFT;
     429             :     }
     430             : 
     431             :   public:
     432       50907 :     void setGeneration(uint32_t generation) {
     433       50907 :         MOZ_ASSERT(generation <= (OBJECT_FLAG_GENERATION_MASK >> OBJECT_FLAG_GENERATION_SHIFT));
     434       50907 :         flags_ &= ~OBJECT_FLAG_GENERATION_MASK;
     435       50907 :         flags_ |= generation << OBJECT_FLAG_GENERATION_SHIFT;
     436       50907 :     }
     437             : 
     438             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     439             : 
     440             :     void finalize(FreeOp* fop);
     441             : 
     442             :     static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
     443             : 
     444         132 :     static inline uint32_t offsetOfClasp() {
     445         132 :         return offsetof(ObjectGroup, clasp_);
     446             :     }
     447             : 
     448         102 :     static inline uint32_t offsetOfProto() {
     449         102 :         return offsetof(ObjectGroup, proto_);
     450             :     }
     451             : 
     452          17 :     static inline uint32_t offsetOfCompartment() {
     453          17 :         return offsetof(ObjectGroup, compartment_);
     454             :     }
     455             : 
     456          14 :     static inline uint32_t offsetOfAddendum() {
     457          14 :         return offsetof(ObjectGroup, addendum_);
     458             :     }
     459             : 
     460         302 :     static inline uint32_t offsetOfFlags() {
     461         302 :         return offsetof(ObjectGroup, flags_);
     462             :     }
     463             : 
     464           0 :     const ObjectGroupFlags* addressOfFlags() const {
     465           0 :         return &flags_;
     466             :     }
     467             : 
     468             :     // Get the bit pattern stored in an object's addendum when it has an
     469             :     // original unboxed group.
     470         151 :     static inline int32_t addendumOriginalUnboxedGroupValue() {
     471         151 :         return Addendum_OriginalUnboxedGroup << OBJECT_FLAG_ADDENDUM_SHIFT;
     472             :     }
     473             : 
     474             :     inline uint32_t basePropertyCount();
     475             : 
     476             :   private:
     477             :     inline void setBasePropertyCount(uint32_t count);
     478             : 
     479             :     static void staticAsserts() {
     480             :         JS_STATIC_ASSERT(offsetof(ObjectGroup, proto_) == offsetof(js::shadow::ObjectGroup, proto));
     481             :     }
     482             : 
     483             :   public:
     484             :     // Whether to make a deep cloned singleton when cloning fun.
     485             :     static bool useSingletonForClone(JSFunction* fun);
     486             : 
     487             :     // Whether to make a singleton when calling 'new' at script/pc.
     488             :     static bool useSingletonForNewObject(JSContext* cx, JSScript* script, jsbytecode* pc);
     489             : 
     490             :     // Whether to make a singleton object at an allocation site.
     491             :     static bool useSingletonForAllocationSite(JSScript* script, jsbytecode* pc,
     492             :                                               JSProtoKey key);
     493             :     static bool useSingletonForAllocationSite(JSScript* script, jsbytecode* pc,
     494             :                                               const Class* clasp);
     495             : 
     496             :     // Static accessors for ObjectGroupCompartment NewTable.
     497             : 
     498             :     static ObjectGroup* defaultNewGroup(JSContext* cx, const Class* clasp,
     499             :                                         TaggedProto proto,
     500             :                                         JSObject* associated = nullptr);
     501             :     static ObjectGroup* lazySingletonGroup(JSContext* cx, const Class* clasp,
     502             :                                            TaggedProto proto);
     503             : 
     504             :     static void setDefaultNewGroupUnknown(JSContext* cx, const js::Class* clasp, JS::HandleObject obj);
     505             : 
     506             : #ifdef DEBUG
     507             :     static bool hasDefaultNewGroup(JSObject* proto, const Class* clasp, ObjectGroup* group);
     508             : #endif
     509             : 
     510             :     // Static accessors for ObjectGroupCompartment ArrayObjectTable and PlainObjectTable.
     511             : 
     512             :     enum class NewArrayKind {
     513             :         Normal,       // Specialize array group based on its element type.
     514             :         CopyOnWrite,  // Make an array with copy-on-write elements.
     515             :         UnknownIndex  // Make an array with an unknown element type.
     516             :     };
     517             : 
     518             :     // Create an ArrayObject or UnboxedArrayObject with the specified elements
     519             :     // and a group specialized for the elements.
     520             :     static JSObject* newArrayObject(JSContext* cx, const Value* vp, size_t length,
     521             :                                     NewObjectKind newKind,
     522             :                                     NewArrayKind arrayKind = NewArrayKind::Normal);
     523             : 
     524             :     // Create a PlainObject or UnboxedPlainObject with the specified properties
     525             :     // and a group specialized for those properties.
     526             :     static JSObject* newPlainObject(JSContext* cx,
     527             :                                     IdValuePair* properties, size_t nproperties,
     528             :                                     NewObjectKind newKind);
     529             : 
     530             :     // Static accessors for ObjectGroupCompartment AllocationSiteTable.
     531             : 
     532             :     // Get a non-singleton group to use for objects created at the specified
     533             :     // allocation site.
     534             :     static ObjectGroup* allocationSiteGroup(JSContext* cx, JSScript* script, jsbytecode* pc,
     535             :                                             JSProtoKey key, HandleObject proto = nullptr);
     536             : 
     537             :     // Get a non-singleton group to use for objects created in a JSNative call.
     538             :     static ObjectGroup* callingAllocationSiteGroup(JSContext* cx, JSProtoKey key,
     539             :                                                    HandleObject proto = nullptr);
     540             : 
     541             :     // Set the group or singleton-ness of an object created for an allocation site.
     542             :     static bool
     543             :     setAllocationSiteObjectGroup(JSContext* cx, HandleScript script, jsbytecode* pc,
     544             :                                  HandleObject obj, bool singleton);
     545             : 
     546             :     static ArrayObject* getOrFixupCopyOnWriteObject(JSContext* cx, HandleScript script,
     547             :                                                     jsbytecode* pc);
     548             :     static ArrayObject* getCopyOnWriteObject(JSScript* script, jsbytecode* pc);
     549             : 
     550             :     // Returns false if not found.
     551             :     static bool findAllocationSite(JSContext* cx, ObjectGroup* group,
     552             :                                    JSScript** script, uint32_t* offset);
     553             : 
     554             :   private:
     555             :     static ObjectGroup* defaultNewGroup(JSContext* cx, JSProtoKey key);
     556             : };
     557             : 
     558             : // Structure used to manage the groups in a compartment.
     559             : class ObjectGroupCompartment
     560             : {
     561             :     friend class ObjectGroup;
     562             : 
     563             :     class NewTable;
     564             : 
     565             :     // Set of default 'new' or lazy groups in the compartment.
     566             :     NewTable* defaultNewTable;
     567             :     NewTable* lazyTable;
     568             : 
     569             :     // Cache for defaultNewGroup. Purged on GC.
     570             :     class DefaultNewGroupCache
     571             :     {
     572             :         ObjectGroup* group_;
     573             :         JSObject* associated_;
     574             : 
     575             :       public:
     576         315 :         DefaultNewGroupCache() { purge(); }
     577             : 
     578         554 :         void purge() {
     579         554 :             group_ = nullptr;
     580         554 :         }
     581       36092 :         void put(ObjectGroup* group, JSObject* associated) {
     582       36092 :             group_ = group;
     583       36092 :             associated_ = associated;
     584       36092 :         }
     585             : 
     586             :         MOZ_ALWAYS_INLINE ObjectGroup* lookup(const Class* clasp, TaggedProto proto,
     587             :                                               JSObject* associated);
     588             :     };
     589             :     DefaultNewGroupCache defaultNewGroupCache;
     590             : 
     591             :     struct ArrayObjectKey;
     592             :     using ArrayObjectTable = js::GCRekeyableHashMap<ArrayObjectKey,
     593             :                                                     ReadBarrieredObjectGroup,
     594             :                                                     ArrayObjectKey,
     595             :                                                     SystemAllocPolicy>;
     596             : 
     597             :     struct PlainObjectKey;
     598             :     struct PlainObjectEntry;
     599             :     struct PlainObjectTableSweepPolicy {
     600             :         static bool needsSweep(PlainObjectKey* key, PlainObjectEntry* entry);
     601             :     };
     602             :     using PlainObjectTable = JS::GCHashMap<PlainObjectKey,
     603             :                                            PlainObjectEntry,
     604             :                                            PlainObjectKey,
     605             :                                            SystemAllocPolicy,
     606             :                                            PlainObjectTableSweepPolicy>;
     607             : 
     608             :     // Tables for managing groups common to the contents of large script
     609             :     // singleton objects and JSON objects. These are vanilla ArrayObjects and
     610             :     // PlainObjects, so we distinguish the groups of different ones by looking
     611             :     // at the types of their properties.
     612             :     //
     613             :     // All singleton/JSON arrays which have the same prototype, are homogenous
     614             :     // and of the same element type will share a group. All singleton/JSON
     615             :     // objects which have the same shape and property types will also share a
     616             :     // group. We don't try to collate arrays or objects with type mismatches.
     617             :     ArrayObjectTable* arrayObjectTable;
     618             :     PlainObjectTable* plainObjectTable;
     619             : 
     620             :     struct AllocationSiteKey;
     621             :     class AllocationSiteTable;
     622             : 
     623             :     // Table for referencing types of objects keyed to an allocation site.
     624             :     AllocationSiteTable* allocationSiteTable;
     625             : 
     626             :     // A single per-compartment ObjectGroup for all calls to StringSplitString.
     627             :     // StringSplitString is always called from self-hosted code, and conceptually
     628             :     // the return object for a string.split(string) operation should have a
     629             :     // unified type.  Having a global group for this also allows us to remove
     630             :     // the hash-table lookup that would be required if we allocated this group
     631             :     // on the basis of call-site pc.
     632             :     ReadBarrieredObjectGroup stringSplitStringGroup;
     633             : 
     634             :   public:
     635             :     struct NewEntry;
     636             : 
     637             :     ObjectGroupCompartment();
     638             :     ~ObjectGroupCompartment();
     639             : 
     640             :     void replaceAllocationSiteGroup(JSScript* script, jsbytecode* pc,
     641             :                                     JSProtoKey kind, ObjectGroup* group);
     642             : 
     643             :     void removeDefaultNewGroup(const Class* clasp, TaggedProto proto, JSObject* associated);
     644             :     void replaceDefaultNewGroup(const Class* clasp, TaggedProto proto, JSObject* associated,
     645             :                                 ObjectGroup* group);
     646             : 
     647             :     static ObjectGroup* makeGroup(JSContext* cx, const Class* clasp,
     648             :                                   Handle<TaggedProto> proto,
     649             :                                   ObjectGroupFlags initialFlags = 0);
     650             : 
     651             :     static ObjectGroup* getStringSplitStringGroup(JSContext* cx);
     652             : 
     653             :     void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
     654             :                                 size_t* allocationSiteTables,
     655             :                                 size_t* arrayGroupTables,
     656             :                                 size_t* plainObjectGroupTables,
     657             :                                 size_t* compartmentTables);
     658             : 
     659             :     void clearTables();
     660             : 
     661             :     void sweep(FreeOp* fop);
     662             : 
     663         223 :     void purge() {
     664         223 :         defaultNewGroupCache.purge();
     665         223 :     }
     666             : 
     667             : #ifdef JSGC_HASH_TABLE_CHECKS
     668           0 :     void checkTablesAfterMovingGC() {
     669           0 :         checkNewTableAfterMovingGC(defaultNewTable);
     670           0 :         checkNewTableAfterMovingGC(lazyTable);
     671           0 :     }
     672             : #endif
     673             : 
     674           0 :     void fixupTablesAfterMovingGC() {
     675           0 :         fixupNewTableAfterMovingGC(defaultNewTable);
     676           0 :         fixupNewTableAfterMovingGC(lazyTable);
     677           0 :     }
     678             : 
     679             :   private:
     680             : #ifdef JSGC_HASH_TABLE_CHECKS
     681             :     void checkNewTableAfterMovingGC(NewTable* table);
     682             : #endif
     683             : 
     684             :     void fixupNewTableAfterMovingGC(NewTable* table);
     685             : };
     686             : 
     687             : PlainObject*
     688             : NewPlainObjectWithProperties(JSContext* cx, IdValuePair* properties, size_t nproperties,
     689             :                              NewObjectKind newKind);
     690             : 
     691             : bool
     692             : CombineArrayElementTypes(JSContext* cx, JSObject* newObj,
     693             :                          const Value* compare, size_t ncompare);
     694             : 
     695             : bool
     696             : CombinePlainObjectPropertyTypes(JSContext* cx, JSObject* newObj,
     697             :                                 const Value* compare, size_t ncompare);
     698             : 
     699             : } // namespace js
     700             : 
     701             : #endif /* vm_ObjectGroup_h */

Generated by: LCOV version 1.13