LCOV - code coverage report
Current view: directory - js/src/vm - ObjectImpl.h (source / functions) Found Hit Coverage
Test: app.info Lines: 46 46 100.0 %
Date: 2012-06-02 Functions: 29 29 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=78:
       3                 :  *
       4                 :  * This Source Code Form is subject to the terms of the Mozilla Public
       5                 :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       6                 :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       7                 : 
       8                 : #ifndef ObjectImpl_h___
       9                 : #define ObjectImpl_h___
      10                 : 
      11                 : #include "mozilla/Assertions.h"
      12                 : #include "mozilla/StandardInteger.h"
      13                 : 
      14                 : #include "jsfriendapi.h"
      15                 : #include "jsinfer.h"
      16                 : #include "jsval.h"
      17                 : 
      18                 : #include "gc/Barrier.h"
      19                 : 
      20                 : namespace js {
      21                 : 
      22                 : /*
      23                 :  * Header structure for object element arrays. This structure is immediately
      24                 :  * followed by an array of elements, with the elements member in an object
      25                 :  * pointing to the beginning of that array (the end of this structure).
      26                 :  * See below for usage of this structure.
      27                 :  */
      28                 : class ObjectElements
      29                 : {
      30                 :     friend struct ::JSObject;
      31                 : 
      32                 :     /* Number of allocated slots. */
      33                 :     uint32_t capacity;
      34                 : 
      35                 :     /*
      36                 :      * Number of initialized elements. This is <= the capacity, and for arrays
      37                 :      * is <= the length. Memory for elements above the initialized length is
      38                 :      * uninitialized, but values between the initialized length and the proper
      39                 :      * length are conceptually holes.
      40                 :      */
      41                 :     uint32_t initializedLength;
      42                 : 
      43                 :     /* 'length' property of array objects, unused for other objects. */
      44                 :     uint32_t length;
      45                 : 
      46                 :     /* :XXX: bug 586842 store state about sparse slots. */
      47                 :     uint32_t unused;
      48                 : 
      49                 :     void staticAsserts() {
      50                 :         MOZ_STATIC_ASSERT(sizeof(ObjectElements) == VALUES_PER_HEADER * sizeof(Value),
      51                 :                           "Elements size and values-per-Elements mismatch");
      52                 :     }
      53                 : 
      54                 :   public:
      55                 : 
      56          414569 :     ObjectElements(uint32_t capacity, uint32_t length)
      57          414569 :       : capacity(capacity), initializedLength(0), length(length)
      58          414569 :     {}
      59                 : 
      60          608242 :     HeapSlot *elements() { return (HeapSlot *)(uintptr_t(this) + sizeof(ObjectElements)); }
      61       508541724 :     static ObjectElements * fromElements(HeapSlot *elems) {
      62       508541724 :         return (ObjectElements *)(uintptr_t(elems) - sizeof(ObjectElements));
      63                 :     }
      64                 : 
      65           18999 :     static int offsetOfCapacity() {
      66           18999 :         return (int)offsetof(ObjectElements, capacity) - (int)sizeof(ObjectElements);
      67                 :     }
      68          138687 :     static int offsetOfInitializedLength() {
      69          138687 :         return (int)offsetof(ObjectElements, initializedLength) - (int)sizeof(ObjectElements);
      70                 :     }
      71           44865 :     static int offsetOfLength() {
      72           44865 :         return (int)offsetof(ObjectElements, length) - (int)sizeof(ObjectElements);
      73                 :     }
      74                 : 
      75                 :     static const size_t VALUES_PER_HEADER = 2;
      76                 : };
      77                 : 
      78                 : /* Shared singleton for objects with no elements. */
      79                 : extern HeapSlot *emptyObjectElements;
      80                 : 
      81                 : struct Class;
      82                 : struct GCMarker;
      83                 : struct ObjectOps;
      84                 : struct Shape;
      85                 : 
      86                 : class NewObjectCache;
      87                 : 
      88                 : /*
      89                 :  * ObjectImpl specifies the internal implementation of an object.  (In contrast
      90                 :  * JSObject specifies an "external" interface, at the conceptual level of that
      91                 :  * exposed in ECMAScript.)
      92                 :  *
      93                 :  * The |shape_| member stores the shape of the object, which includes the
      94                 :  * object's class and the layout of all its properties.
      95                 :  *
      96                 :  * The type member stores the type of the object, which contains its prototype
      97                 :  * object and the possible types of its properties.
      98                 :  *
      99                 :  * The rest of the object stores its named properties and indexed elements.
     100                 :  * These are stored separately from one another. Objects are followed by an
     101                 :  * variable-sized array of values for inline storage, which may be used by
     102                 :  * either properties of native objects (fixed slots) or by elements.
     103                 :  *
     104                 :  * Two native objects with the same shape are guaranteed to have the same
     105                 :  * number of fixed slots.
     106                 :  *
     107                 :  * Named property storage can be split between fixed slots and a dynamically
     108                 :  * allocated array (the slots member). For an object with N fixed slots, shapes
     109                 :  * with slots [0..N-1] are stored in the fixed slots, and the remainder are
     110                 :  * stored in the dynamic array. If all properties fit in the fixed slots, the
     111                 :  * 'slots' member is NULL.
     112                 :  *
     113                 :  * Elements are indexed via the 'elements' member. This member can point to
     114                 :  * either the shared emptyObjectElements singleton, into the inline value array
     115                 :  * (the address of the third value, to leave room for a ObjectElements header;
     116                 :  * in this case numFixedSlots() is zero) or to a dynamically allocated array.
     117                 :  *
     118                 :  * Only certain combinations of properties and elements storage are currently
     119                 :  * possible. This will be changing soon :XXX: bug 586842.
     120                 :  *
     121                 :  * - For objects other than arrays and typed arrays, the elements are empty.
     122                 :  *
     123                 :  * - For 'slow' arrays, both elements and properties are used, but the
     124                 :  *   elements have zero capacity --- only the length member is used.
     125                 :  *
     126                 :  * - For dense arrays, elements are used and properties are not used.
     127                 :  *
     128                 :  * - For typed array buffers, elements are used and properties are not used.
     129                 :  *   The data indexed by the elements do not represent Values, but primitive
     130                 :  *   unboxed integers or floating point values.
     131                 :  *
     132                 :  * The members of this class are currently protected; in the long run this will
     133                 :  * will change so that some members are private, and only certain methods that
     134                 :  * act upon them will be protected.
     135                 :  */
     136                 : class ObjectImpl : public gc::Cell
     137         3737027 : {
     138                 :   protected:
     139                 :     /*
     140                 :      * Shape of the object, encodes the layout of the object's properties and
     141                 :      * all other information about its structure. See jsscope.h.
     142                 :      */
     143                 :     HeapPtrShape shape_;
     144                 : 
     145                 :     /*
     146                 :      * The object's type and prototype. For objects with the LAZY_TYPE flag
     147                 :      * set, this is the prototype's default 'new' type and can only be used
     148                 :      * to get that prototype.
     149                 :      */
     150                 :     HeapPtrTypeObject type_;
     151                 : 
     152                 :     HeapSlot *slots;     /* Slots for object properties. */
     153                 :     HeapSlot *elements;  /* Slots for object elements. */
     154                 : 
     155                 :   private:
     156                 :     static void staticAsserts() {
     157                 :         MOZ_STATIC_ASSERT(sizeof(ObjectImpl) == sizeof(shadow::Object),
     158                 :                           "shadow interface must match actual implementation");
     159                 :         MOZ_STATIC_ASSERT(sizeof(ObjectImpl) % sizeof(Value) == 0,
     160                 :                           "fixed slots after an object must be aligned");
     161                 : 
     162                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, shape_) == offsetof(shadow::Object, shape),
     163                 :                           "shadow shape must match actual shape");
     164                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, type_) == offsetof(shadow::Object, type),
     165                 :                           "shadow type must match actual type");
     166                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, slots) == offsetof(shadow::Object, slots),
     167                 :                           "shadow slots must match actual slots");
     168                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, elements) == offsetof(shadow::Object, _1),
     169                 :                           "shadow placeholder must match actual elements");
     170                 :     }
     171                 : 
     172         3335693 :     JSObject * asObjectPtr() { return reinterpret_cast<JSObject *>(this); }
     173                 : 
     174                 :   protected:
     175                 :     friend struct GCMarker;
     176                 :     friend struct Shape;
     177                 :     friend class NewObjectCache;
     178                 : 
     179                 :     /* Minimum size for dynamically allocated slots. */
     180                 :     static const uint32_t SLOT_CAPACITY_MIN = 8;
     181                 : 
     182       423521024 :     HeapSlot *fixedSlots() const {
     183       423521024 :         return reinterpret_cast<HeapSlot *>(uintptr_t(this) + sizeof(ObjectImpl));
     184                 :     }
     185                 : 
     186                 :     /*
     187                 :      * These functions are currently public for simplicity; in the long run
     188                 :      * it may make sense to make at least some of them private.
     189                 :      */
     190                 : 
     191                 :   public:
     192              -1 :     Shape * lastProperty() const {
     193              -1 :         MOZ_ASSERT(shape_);
     194              -1 :         return shape_;
     195                 :     }
     196                 : 
     197       135435317 :     types::TypeObject *type() const {
     198       135435317 :         MOZ_ASSERT(!hasLazyType());
     199       135435317 :         return type_;
     200                 :     }
     201                 : 
     202     -1876973095 :     size_t numFixedSlots() const {
     203     -1876973095 :         return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots();
     204                 :     }
     205                 : 
     206                 :     /*
     207                 :      * Whether this is the only object which has its specified type. This
     208                 :      * object will have its type constructed lazily as needed by analysis.
     209                 :      */
     210       133344137 :     bool hasSingletonType() const { return !!type_->singleton; }
     211                 : 
     212                 :     /*
     213                 :      * Whether the object's type has not been constructed yet. If an object
     214                 :      * might have a lazy type, use getType() below, otherwise type().
     215                 :      */
     216       183786396 :     bool hasLazyType() const { return type_->lazy(); }
     217                 : 
     218                 :     inline bool isNative() const;
     219                 : 
     220                 :     const Shape * nativeLookup(JSContext *cx, jsid id);
     221                 : 
     222                 :     inline Class *getClass() const;
     223                 :     inline JSClass *getJSClass() const;
     224                 :     inline bool hasClass(const Class *c) const;
     225                 :     inline const ObjectOps *getOps() const;
     226                 : 
     227                 :     /*
     228                 :      * An object is a delegate if it is on another object's prototype or scope
     229                 :      * chain, and therefore the delegate might be asked implicitly to get or
     230                 :      * set a property on behalf of another object. Delegates may be accessed
     231                 :      * directly too, as may any object, but only those objects linked after the
     232                 :      * head of any prototype or scope chain are flagged as delegates. This
     233                 :      * definition helps to optimize shape-based property cache invalidation
     234                 :      * (see Purge{Scope,Proto}Chain in jsobj.cpp).
     235                 :      */
     236                 :     inline bool isDelegate() const;
     237                 : 
     238                 :     /*
     239                 :      * Return true if this object is a native one that has been converted from
     240                 :      * shared-immutable prototype-rooted shape storage to dictionary-shapes in
     241                 :      * a doubly-linked list.
     242                 :      */
     243                 :     inline bool inDictionaryMode() const;
     244                 : 
     245                 :     /*
     246                 :      * Get the number of dynamic slots to allocate to cover the properties in
     247                 :      * an object with the given number of fixed slots and slot span. The slot
     248                 :      * capacity is not stored explicitly, and the allocated size of the slot
     249                 :      * array is kept in sync with this count.
     250                 :      */
     251                 :     static inline size_t dynamicSlotsCount(size_t nfixed, size_t span);
     252                 : 
     253                 :     /* Memory usage functions. */
     254                 :     inline size_t sizeOfThis() const;
     255                 : 
     256                 :     /* Elements accessors. */
     257                 : 
     258       508531686 :     ObjectElements * getElementsHeader() const {
     259       508531686 :         return ObjectElements::fromElements(elements);
     260                 :     }
     261                 : 
     262        10929685 :     inline HeapSlot *fixedElements() const {
     263                 :         MOZ_STATIC_ASSERT(2 * sizeof(Value) == sizeof(ObjectElements),
     264                 :                           "when elements are stored inline, the first two "
     265                 :                           "slots will hold the ObjectElements header");
     266        10929685 :         return &fixedSlots()[2];
     267                 :     }
     268                 : 
     269         2960481 :     void setFixedElements() { this->elements = fixedElements(); }
     270                 : 
     271        49742191 :     inline bool hasDynamicElements() const {
     272                 :         /*
     273                 :          * Note: for objects with zero fixed slots this could potentially give
     274                 :          * a spurious 'true' result, if the end of this object is exactly
     275                 :          * aligned with the end of its arena and dynamic slots are allocated
     276                 :          * immediately afterwards. Such cases cannot occur for dense arrays
     277                 :          * (which have at least two fixed slots) and can only result in a leak.
     278                 :          */
     279        49742191 :         return elements != emptyObjectElements && elements != fixedElements();
     280                 :     }
     281                 : 
     282                 :     /* GC support. */
     283                 :     static inline void readBarrier(ObjectImpl *obj);
     284                 :     static inline void writeBarrierPre(ObjectImpl *obj);
     285                 :     static inline void writeBarrierPost(ObjectImpl *obj, void *addr);
     286                 :     inline void privateWriteBarrierPre(void **oldval);
     287                 :     inline void privateWriteBarrierPost(void **oldval);
     288                 :     void markChildren(JSTracer *trc);
     289                 : 
     290                 :     /* JIT Accessors */
     291          992256 :     static size_t offsetOfShape() { return offsetof(ObjectImpl, shape_); }
     292          776524 :     HeapPtrShape *addressOfShape() { return &shape_; }
     293                 : 
     294          119327 :     static size_t offsetOfType() { return offsetof(ObjectImpl, type_); }
     295          373937 :     HeapPtrTypeObject *addressOfType() { return &type_; }
     296                 : 
     297          158765 :     static size_t offsetOfElements() { return offsetof(ObjectImpl, elements); }
     298           19251 :     static size_t offsetOfFixedElements() {
     299           19251 :         return sizeof(ObjectImpl) + sizeof(ObjectElements);
     300                 :     }
     301                 : 
     302          251949 :     static size_t getFixedSlotOffset(size_t slot) {
     303          251949 :         return sizeof(ObjectImpl) + slot * sizeof(Value);
     304                 :     }
     305           36433 :     static size_t getPrivateDataOffset(size_t nfixed) { return getFixedSlotOffset(nfixed); }
     306         1225568 :     static size_t offsetOfSlots() { return offsetof(ObjectImpl, slots); }
     307                 : 
     308                 :     /* These functions are public, and they should remain public. */
     309                 : 
     310                 :   public:
     311       309269929 :     JSObject * getProto() const {
     312       309269929 :         return type_->proto;
     313                 :     }
     314                 : 
     315                 :     inline bool isExtensible() const;
     316                 : };
     317                 : 
     318                 : } /* namespace js */
     319                 : 
     320                 : #endif /* ObjectImpl_h__ */

Generated by: LCOV version 1.7