LCOV - code coverage report
Current view: directory - js/src/vm - ObjectImpl.h (source / functions) Found Hit Coverage
Test: app.info Lines: 86 69 80.2 %
Date: 2012-04-07 Functions: 43 35 81.4 %

       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                 : class ObjectImpl;
      23                 : 
      24                 : class DenseElementsHeader;
      25                 : class SparseElementsHeader;
      26                 : class Uint8ElementsHeader;
      27                 : class Int8ElementsHeader;
      28                 : class Uint16ElementsHeader;
      29                 : class Int16ElementsHeader;
      30                 : class Uint32ElementsHeader;
      31                 : class Int32ElementsHeader;
      32                 : class Uint8ClampedElementsHeader;
      33                 : class Float32ElementsHeader;
      34                 : class Float64ElementsHeader;
      35                 : class ArrayBufferElementsHeader;
      36                 : 
      37                 : enum ElementsKind {
      38                 :     DenseElements,
      39                 :     SparseElements,
      40                 :     Uint8Elements,
      41                 :     Int8Elements,
      42                 :     Uint16Elements,
      43                 :     Int16Elements,
      44                 :     Uint32Elements,
      45                 :     Int32Elements,
      46                 :     Uint8ClampedElements,
      47                 :     Float32Elements,
      48                 :     Float64Elements,
      49                 :     ArrayBufferElements
      50                 : };
      51                 : 
      52                 : class ElementsHeader
      53                 : {
      54                 :   protected:
      55                 :     uint32_t type;
      56                 :     uint32_t length; /* Array length, byte length of ArrayBuffer */
      57                 : 
      58                 :     union {
      59                 :         class {
      60                 :             friend class DenseElementsHeader;
      61                 :             uint32_t initializedLength;
      62                 :             uint32_t capacity;
      63                 :         } dense;
      64                 :         class {
      65                 :             friend class SparseElementsHeader;
      66                 :             Shape * shape;
      67                 :         } sparse;
      68                 :     };
      69                 : 
      70                 :     void staticAsserts() {
      71                 :         MOZ_STATIC_ASSERT(sizeof(ElementsHeader) == ValuesPerHeader * sizeof(Value),
      72                 :                           "Elements size and values-per-Elements mismatch");
      73                 :     }
      74                 : 
      75                 :   public:
      76               0 :     ElementsKind kind() const {
      77               0 :         MOZ_ASSERT(type <= ArrayBufferElements);
      78               0 :         return ElementsKind(type);
      79                 :     }
      80                 : 
      81               0 :     inline bool isDenseElements() const { return kind() == DenseElements; }
      82               0 :     inline bool isSparseElements() const { return kind() == SparseElements; }
      83                 :     inline bool isUint8Elements() const { return kind() == Uint8Elements; }
      84                 :     inline bool isInt8Elements() const { return kind() == Int8Elements; }
      85                 :     inline bool isUint16Elements() const { return kind() == Uint16Elements; }
      86                 :     inline bool isInt16Elements() const { return kind() == Int16Elements; }
      87                 :     inline bool isUint32Elements() const { return kind() == Uint32Elements; }
      88                 :     inline bool isInt32Elements() const { return kind() == Int32Elements; }
      89                 :     inline bool isUint8ClampedElements() const { return kind() == Uint8ClampedElements; }
      90                 :     inline bool isFloat32Elements() const { return kind() == Float32Elements; }
      91                 :     inline bool isFloat64Elements() const { return kind() == Float64Elements; }
      92                 :     inline bool isArrayBufferElements() const { return kind() == ArrayBufferElements; }
      93                 : 
      94                 :     inline DenseElementsHeader & asDenseElements();
      95                 :     inline SparseElementsHeader & asSparseElements();
      96                 :     inline Uint8ElementsHeader & asUint8Elements();
      97                 :     inline Int8ElementsHeader & asInt8Elements();
      98                 :     inline Uint16ElementsHeader & asUint16Elements();
      99                 :     inline Int16ElementsHeader & asInt16Elements();
     100                 :     inline Uint32ElementsHeader & asUint32Elements();
     101                 :     inline Int32ElementsHeader & asInt32Elements();
     102                 :     inline Uint8ClampedElementsHeader & asUint8ClampedElements();
     103                 :     inline Float32ElementsHeader & asFloat32Elements();
     104                 :     inline Float64ElementsHeader & asFloat64Elements();
     105                 :     inline ArrayBufferElementsHeader & asArrayBufferElements();
     106                 : 
     107                 :     static ElementsHeader * fromElements(HeapSlot *elems) {
     108                 :         return reinterpret_cast<ElementsHeader *>(uintptr_t(elems) - sizeof(ElementsHeader));
     109                 :     }
     110                 : 
     111                 :     static const size_t ValuesPerHeader = 2;
     112                 : };
     113                 : 
     114                 : class DenseElementsHeader : public ElementsHeader
     115                 : {
     116                 :   public:
     117                 :     uint32_t capacity() const {
     118                 :         MOZ_ASSERT(ElementsHeader::isDenseElements());
     119                 :         return dense.capacity;
     120                 :     }
     121                 : 
     122               0 :     uint32_t initializedLength() const {
     123               0 :         MOZ_ASSERT(ElementsHeader::isDenseElements());
     124               0 :         return dense.initializedLength;
     125                 :     }
     126                 : 
     127                 :     uint32_t length() const {
     128                 :         MOZ_ASSERT(ElementsHeader::isDenseElements());
     129                 :         return ElementsHeader::length;
     130                 :     }
     131                 : 
     132                 :     bool defineElement(JSContext *cx, ObjectImpl *obj,
     133                 :                        uint32_t index, const Value &value,
     134                 :                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     135                 : 
     136                 :   private:
     137                 :     inline bool isDenseElements() const MOZ_DELETE;
     138                 :     inline DenseElementsHeader & asDenseElements() MOZ_DELETE;
     139                 : 
     140                 :     DenseElementsHeader(const DenseElementsHeader &other) MOZ_DELETE;
     141                 :     void operator=(const DenseElementsHeader &other) MOZ_DELETE;
     142                 : };
     143                 : 
     144                 : class SparseElementsHeader : public ElementsHeader
     145                 : {
     146                 :   public:
     147                 :     Shape * shape() {
     148                 :         MOZ_ASSERT(ElementsHeader::isSparseElements());
     149                 :         return sparse.shape;
     150                 :     }
     151                 : 
     152                 :     uint32_t length() const {
     153                 :         MOZ_ASSERT(ElementsHeader::isSparseElements());
     154                 :         return ElementsHeader::length;
     155                 :     }
     156                 : 
     157                 :     bool defineElement(JSContext *cx, ObjectImpl *obj,
     158                 :                        uint32_t index, const Value &value,
     159                 :                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     160                 : 
     161                 :   private:
     162                 :     inline bool isSparseElements() const MOZ_DELETE;
     163                 :     inline SparseElementsHeader & asSparseElements() MOZ_DELETE;
     164                 : 
     165                 :     SparseElementsHeader(const SparseElementsHeader &other) MOZ_DELETE;
     166                 :     void operator=(const SparseElementsHeader &other) MOZ_DELETE;
     167                 : };
     168                 : 
     169                 : template <typename T>
     170                 : class TypedElementsHeader : public ElementsHeader
     171                 : {
     172                 :   public:
     173                 :     uint32_t byteLength() const {
     174                 :         return ElementsHeader::length;
     175                 :     }
     176                 : 
     177                 :     bool defineElement(JSContext *cx, ObjectImpl *obj,
     178                 :                        uint32_t index, const Value &value,
     179                 :                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     180                 : 
     181                 :   private:
     182                 :     TypedElementsHeader(const TypedElementsHeader &other) MOZ_DELETE;
     183                 :     void operator=(const TypedElementsHeader &other) MOZ_DELETE;
     184                 : };
     185                 : 
     186                 : class Uint8ElementsHeader : public TypedElementsHeader<uint8_t>
     187                 : {
     188                 :   private:
     189                 :     inline bool isUint8Elements() const MOZ_DELETE;
     190                 :     inline Uint8ElementsHeader & asUint8Elements() MOZ_DELETE;
     191                 :     Uint8ElementsHeader(const Uint8ElementsHeader &other) MOZ_DELETE;
     192                 :     void operator=(const Uint8ElementsHeader &other) MOZ_DELETE;
     193                 : };
     194                 : class Int8ElementsHeader : public TypedElementsHeader<int8_t>
     195                 : {
     196                 :   private:
     197                 :     bool isInt8Elements() const MOZ_DELETE;
     198                 :     Int8ElementsHeader & asInt8Elements() MOZ_DELETE;
     199                 :     Int8ElementsHeader(const Int8ElementsHeader &other) MOZ_DELETE;
     200                 :     void operator=(const Int8ElementsHeader &other) MOZ_DELETE;
     201                 : };
     202                 : class Uint16ElementsHeader : public TypedElementsHeader<uint16_t>
     203                 : {
     204                 :   private:
     205                 :     bool isUint16Elements() const MOZ_DELETE;
     206                 :     Uint16ElementsHeader & asUint16Elements() MOZ_DELETE;
     207                 :     Uint16ElementsHeader(const Uint16ElementsHeader &other) MOZ_DELETE;
     208                 :     void operator=(const Uint16ElementsHeader &other) MOZ_DELETE;
     209                 : };
     210                 : class Int16ElementsHeader : public TypedElementsHeader<int16_t>
     211                 : {
     212                 :   private:
     213                 :     bool isInt16Elements() const MOZ_DELETE;
     214                 :     Int16ElementsHeader & asInt16Elements() MOZ_DELETE;
     215                 :     Int16ElementsHeader(const Int16ElementsHeader &other) MOZ_DELETE;
     216                 :     void operator=(const Int16ElementsHeader &other) MOZ_DELETE;
     217                 : };
     218                 : class Uint32ElementsHeader : public TypedElementsHeader<uint32_t>
     219                 : {
     220                 :   private:
     221                 :     bool isUint32Elements() const MOZ_DELETE;
     222                 :     Uint32ElementsHeader & asUint32Elements() MOZ_DELETE;
     223                 :     Uint32ElementsHeader(const Uint32ElementsHeader &other) MOZ_DELETE;
     224                 :     void operator=(const Uint32ElementsHeader &other) MOZ_DELETE;
     225                 : };
     226                 : class Int32ElementsHeader : public TypedElementsHeader<int32_t>
     227                 : {
     228                 :   private:
     229                 :     bool isInt32Elements() const MOZ_DELETE;
     230                 :     Int32ElementsHeader & asInt32Elements() MOZ_DELETE;
     231                 :     Int32ElementsHeader(const Int32ElementsHeader &other) MOZ_DELETE;
     232                 :     void operator=(const Int32ElementsHeader &other) MOZ_DELETE;
     233                 : };
     234                 : class Float32ElementsHeader : public TypedElementsHeader<float>
     235                 : {
     236                 :   private:
     237                 :     bool isFloat32Elements() const MOZ_DELETE;
     238                 :     Float32ElementsHeader & asFloat32Elements() MOZ_DELETE;
     239                 :     Float32ElementsHeader(const Float32ElementsHeader &other) MOZ_DELETE;
     240                 :     void operator=(const Float32ElementsHeader &other) MOZ_DELETE;
     241                 : };
     242                 : class Float64ElementsHeader : public TypedElementsHeader<double>
     243                 : {
     244                 :   private:
     245                 :     bool isFloat64Elements() const MOZ_DELETE;
     246                 :     Float64ElementsHeader & asFloat64Elements() MOZ_DELETE;
     247                 :     Float64ElementsHeader(const Float64ElementsHeader &other) MOZ_DELETE;
     248                 :     void operator=(const Float64ElementsHeader &other) MOZ_DELETE;
     249                 : };
     250                 : 
     251                 : class Uint8ClampedElementsHeader : public TypedElementsHeader<uint8_t>
     252                 : {
     253                 :   private:
     254                 :     inline bool isUint8Clamped() const MOZ_DELETE;
     255                 :     inline Uint8ClampedElementsHeader & asUint8ClampedElements() MOZ_DELETE;
     256                 :     Uint8ClampedElementsHeader(const Uint8ClampedElementsHeader &other) MOZ_DELETE;
     257                 :     void operator=(const Uint8ClampedElementsHeader &other) MOZ_DELETE;
     258                 : };
     259                 : 
     260                 : class ArrayBufferElementsHeader : public ElementsHeader
     261                 : {
     262                 :   public:
     263                 :     bool defineElement(JSContext *cx, ObjectImpl *obj,
     264                 :                        uint32_t index, const Value &value,
     265                 :                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     266                 : 
     267                 :   private:
     268                 :     inline bool isArrayBufferElements() const MOZ_DELETE;
     269                 :     inline ArrayBufferElementsHeader & asArrayBufferElements() MOZ_DELETE;
     270                 : 
     271                 :     ArrayBufferElementsHeader(const ArrayBufferElementsHeader &other) MOZ_DELETE;
     272                 :     void operator=(const ArrayBufferElementsHeader &other) MOZ_DELETE;
     273                 : };
     274                 : 
     275                 : inline DenseElementsHeader &
     276                 : ElementsHeader::asDenseElements()
     277                 : {
     278                 :     MOZ_ASSERT(isDenseElements());
     279                 :     return *static_cast<DenseElementsHeader *>(this);
     280                 : }
     281                 : 
     282                 : inline SparseElementsHeader &
     283               0 : ElementsHeader::asSparseElements()
     284                 : {
     285               0 :     MOZ_ASSERT(isSparseElements());
     286               0 :     return *static_cast<SparseElementsHeader *>(this);
     287                 : }
     288                 : 
     289                 : inline Uint8ElementsHeader &
     290                 : ElementsHeader::asUint8Elements()
     291                 : {
     292                 :     MOZ_ASSERT(isUint8Elements());
     293                 :     return *static_cast<Uint8ElementsHeader *>(this);
     294                 : }
     295                 : 
     296                 : inline Int8ElementsHeader &
     297                 : ElementsHeader::asInt8Elements()
     298                 : {
     299                 :     MOZ_ASSERT(isInt8Elements());
     300                 :     return *static_cast<Int8ElementsHeader *>(this);
     301                 : }
     302                 : 
     303                 : inline Uint16ElementsHeader &
     304                 : ElementsHeader::asUint16Elements()
     305                 : {
     306                 :     MOZ_ASSERT(isUint16Elements());
     307                 :     return *static_cast<Uint16ElementsHeader *>(this);
     308                 : }
     309                 : 
     310                 : inline Int16ElementsHeader &
     311                 : ElementsHeader::asInt16Elements()
     312                 : {
     313                 :     MOZ_ASSERT(isInt16Elements());
     314                 :     return *static_cast<Int16ElementsHeader *>(this);
     315                 : }
     316                 : 
     317                 : inline Uint32ElementsHeader &
     318                 : ElementsHeader::asUint32Elements()
     319                 : {
     320                 :     MOZ_ASSERT(isUint32Elements());
     321                 :     return *static_cast<Uint32ElementsHeader *>(this);
     322                 : }
     323                 : 
     324                 : inline Int32ElementsHeader &
     325                 : ElementsHeader::asInt32Elements()
     326                 : {
     327                 :     MOZ_ASSERT(isInt32Elements());
     328                 :     return *static_cast<Int32ElementsHeader *>(this);
     329                 : }
     330                 : 
     331                 : inline Uint8ClampedElementsHeader &
     332                 : ElementsHeader::asUint8ClampedElements()
     333                 : {
     334                 :     MOZ_ASSERT(isUint8ClampedElements());
     335                 :     return *static_cast<Uint8ClampedElementsHeader *>(this);
     336                 : }
     337                 : 
     338                 : inline Float32ElementsHeader &
     339                 : ElementsHeader::asFloat32Elements()
     340                 : {
     341                 :     MOZ_ASSERT(isFloat32Elements());
     342                 :     return *static_cast<Float32ElementsHeader *>(this);
     343                 : }
     344                 : 
     345                 : inline Float64ElementsHeader &
     346                 : ElementsHeader::asFloat64Elements()
     347                 : {
     348                 :     MOZ_ASSERT(isFloat64Elements());
     349                 :     return *static_cast<Float64ElementsHeader *>(this);
     350                 : }
     351                 : 
     352                 : inline ArrayBufferElementsHeader &
     353                 : ElementsHeader::asArrayBufferElements()
     354                 : {
     355                 :     MOZ_ASSERT(isArrayBufferElements());
     356                 :     return *static_cast<ArrayBufferElementsHeader *>(this);
     357                 : }
     358                 : 
     359                 : /*
     360                 :  * Header structure for object element arrays. This structure is immediately
     361                 :  * followed by an array of elements, with the elements member in an object
     362                 :  * pointing to the beginning of that array (the end of this structure).
     363                 :  * See below for usage of this structure.
     364                 :  */
     365                 : class ObjectElements
     366                 : {
     367                 :     friend struct ::JSObject;
     368                 :     friend class ObjectImpl;
     369                 : 
     370                 :     /* Number of allocated slots. */
     371                 :     uint32_t capacity;
     372                 : 
     373                 :     /*
     374                 :      * Number of initialized elements. This is <= the capacity, and for arrays
     375                 :      * is <= the length. Memory for elements above the initialized length is
     376                 :      * uninitialized, but values between the initialized length and the proper
     377                 :      * length are conceptually holes.
     378                 :      */
     379                 :     uint32_t initializedLength;
     380                 : 
     381                 :     /* 'length' property of array objects, unused for other objects. */
     382                 :     uint32_t length;
     383                 : 
     384                 :     /* :XXX: bug 586842 store state about sparse slots. */
     385                 :     uint32_t unused;
     386                 : 
     387                 :     void staticAsserts() {
     388                 :         MOZ_STATIC_ASSERT(sizeof(ObjectElements) == VALUES_PER_HEADER * sizeof(Value),
     389                 :                           "Elements size and values-per-Elements mismatch");
     390                 :     }
     391                 : 
     392                 :   public:
     393                 : 
     394          473715 :     ObjectElements(uint32_t capacity, uint32_t length)
     395          473715 :       : capacity(capacity), initializedLength(0), length(length)
     396          473715 :     {}
     397                 : 
     398          291325 :     HeapSlot *elements() { return (HeapSlot *)(uintptr_t(this) + sizeof(ObjectElements)); }
     399       224613608 :     static ObjectElements * fromElements(HeapSlot *elems) {
     400       224613608 :         return (ObjectElements *)(uintptr_t(elems) - sizeof(ObjectElements));
     401                 :     }
     402                 : 
     403           18989 :     static int offsetOfCapacity() {
     404           18989 :         return (int)offsetof(ObjectElements, capacity) - (int)sizeof(ObjectElements);
     405                 :     }
     406          137055 :     static int offsetOfInitializedLength() {
     407          137055 :         return (int)offsetof(ObjectElements, initializedLength) - (int)sizeof(ObjectElements);
     408                 :     }
     409           42629 :     static int offsetOfLength() {
     410           42629 :         return (int)offsetof(ObjectElements, length) - (int)sizeof(ObjectElements);
     411                 :     }
     412                 : 
     413                 :     static const size_t VALUES_PER_HEADER = 2;
     414                 : };
     415                 : 
     416                 : /* Shared singleton for objects with no elements. */
     417                 : extern HeapSlot *emptyObjectElements;
     418                 : 
     419                 : struct Class;
     420                 : struct GCMarker;
     421                 : struct ObjectOps;
     422                 : struct Shape;
     423                 : 
     424                 : class NewObjectCache;
     425                 : 
     426                 : /*
     427                 :  * ObjectImpl specifies the internal implementation of an object.  (In contrast
     428                 :  * JSObject specifies an "external" interface, at the conceptual level of that
     429                 :  * exposed in ECMAScript.)
     430                 :  *
     431                 :  * The |shape_| member stores the shape of the object, which includes the
     432                 :  * object's class and the layout of all its properties.
     433                 :  *
     434                 :  * The type member stores the type of the object, which contains its prototype
     435                 :  * object and the possible types of its properties.
     436                 :  *
     437                 :  * The rest of the object stores its named properties and indexed elements.
     438                 :  * These are stored separately from one another. Objects are followed by an
     439                 :  * variable-sized array of values for inline storage, which may be used by
     440                 :  * either properties of native objects (fixed slots) or by elements.
     441                 :  *
     442                 :  * Two native objects with the same shape are guaranteed to have the same
     443                 :  * number of fixed slots.
     444                 :  *
     445                 :  * Named property storage can be split between fixed slots and a dynamically
     446                 :  * allocated array (the slots member). For an object with N fixed slots, shapes
     447                 :  * with slots [0..N-1] are stored in the fixed slots, and the remainder are
     448                 :  * stored in the dynamic array. If all properties fit in the fixed slots, the
     449                 :  * 'slots' member is NULL.
     450                 :  *
     451                 :  * Elements are indexed via the 'elements' member. This member can point to
     452                 :  * either the shared emptyObjectElements singleton, into the inline value array
     453                 :  * (the address of the third value, to leave room for a ObjectElements header;
     454                 :  * in this case numFixedSlots() is zero) or to a dynamically allocated array.
     455                 :  *
     456                 :  * Only certain combinations of properties and elements storage are currently
     457                 :  * possible. This will be changing soon :XXX: bug 586842.
     458                 :  *
     459                 :  * - For objects other than arrays and typed arrays, the elements are empty.
     460                 :  *
     461                 :  * - For 'slow' arrays, both elements and properties are used, but the
     462                 :  *   elements have zero capacity --- only the length member is used.
     463                 :  *
     464                 :  * - For dense arrays, elements are used and properties are not used.
     465                 :  *
     466                 :  * - For typed array buffers, elements are used and properties are not used.
     467                 :  *   The data indexed by the elements do not represent Values, but primitive
     468                 :  *   unboxed integers or floating point values.
     469                 :  *
     470                 :  * The members of this class are currently protected; in the long run this will
     471                 :  * will change so that some members are private, and only certain methods that
     472                 :  * act upon them will be protected.
     473                 :  */
     474                 : class ObjectImpl : public gc::Cell
     475         3385370 : {
     476                 :   protected:
     477                 :     /*
     478                 :      * Shape of the object, encodes the layout of the object's properties and
     479                 :      * all other information about its structure. See jsscope.h.
     480                 :      */
     481                 :     HeapPtrShape shape_;
     482                 : 
     483                 :     /*
     484                 :      * The object's type and prototype. For objects with the LAZY_TYPE flag
     485                 :      * set, this is the prototype's default 'new' type and can only be used
     486                 :      * to get that prototype.
     487                 :      */
     488                 :     HeapPtrTypeObject type_;
     489                 : 
     490                 :     HeapSlot *slots;     /* Slots for object properties. */
     491                 :     HeapSlot *elements;  /* Slots for object elements. */
     492                 : 
     493                 :   private:
     494                 :     static void staticAsserts() {
     495                 :         MOZ_STATIC_ASSERT(sizeof(ObjectImpl) == sizeof(shadow::Object),
     496                 :                           "shadow interface must match actual implementation");
     497                 :         MOZ_STATIC_ASSERT(sizeof(ObjectImpl) % sizeof(Value) == 0,
     498                 :                           "fixed slots after an object must be aligned");
     499                 : 
     500                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, shape_) == offsetof(shadow::Object, shape),
     501                 :                           "shadow shape must match actual shape");
     502                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, type_) == offsetof(shadow::Object, type),
     503                 :                           "shadow type must match actual type");
     504                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, slots) == offsetof(shadow::Object, slots),
     505                 :                           "shadow slots must match actual slots");
     506                 :         MOZ_STATIC_ASSERT(offsetof(ObjectImpl, elements) == offsetof(shadow::Object, _1),
     507                 :                           "shadow placeholder must match actual elements");
     508                 :     }
     509                 : 
     510       104938476 :     JSObject * asObjectPtr() { return reinterpret_cast<JSObject *>(this); }
     511                 : 
     512                 :     /* These functions are public, and they should remain public. */
     513                 : 
     514                 :   public:
     515       204013694 :     JSObject * getProto() const {
     516       204013694 :         return type_->proto;
     517                 :     }
     518                 : 
     519                 :     inline bool isExtensible() const;
     520                 : 
     521                 :     /*
     522                 :      * XXX Once the property/element split of bug 586842 is complete, these
     523                 :      *     methods should move back to JSObject.
     524                 :      */
     525                 :     inline bool isDenseArray() const;
     526                 :     inline bool isSlowArray() const;
     527                 :     inline bool isArray() const;
     528                 : 
     529                 :     inline HeapSlotArray getDenseArrayElements();
     530                 :     inline const Value & getDenseArrayElement(uint32_t idx);
     531                 :     inline uint32_t getDenseArrayInitializedLength();
     532                 : 
     533               0 :     bool makeElementsSparse(JSContext *cx) {
     534               0 :         NEW_OBJECT_REPRESENTATION_ONLY();
     535                 : 
     536                 :         MOZ_NOT_REACHED("NYI");
     537                 :         return false;
     538                 :     }
     539                 : 
     540                 :   protected:
     541                 : #ifdef DEBUG
     542                 :     void checkShapeConsistency();
     543                 : #else
     544                 :     void checkShapeConsistency() { }
     545                 : #endif
     546                 : 
     547                 :   private:
     548                 :     /*
     549                 :      * Get internal pointers to the range of values starting at start and
     550                 :      * running for length.
     551                 :      */
     552                 :     inline void getSlotRangeUnchecked(uint32_t start, uint32_t length,
     553                 :                                       HeapSlot **fixedStart, HeapSlot **fixedEnd,
     554                 :                                       HeapSlot **slotsStart, HeapSlot **slotsEnd);
     555                 :     inline void getSlotRange(uint32_t start, uint32_t length,
     556                 :                              HeapSlot **fixedStart, HeapSlot **fixedEnd,
     557                 :                              HeapSlot **slotsStart, HeapSlot **slotsEnd);
     558                 : 
     559                 :   protected:
     560                 :     friend struct GCMarker;
     561                 :     friend struct Shape;
     562                 :     friend class NewObjectCache;
     563                 : 
     564                 :     inline bool hasContiguousSlots(uint32_t start, uint32_t count) const;
     565                 : 
     566                 :     inline void invalidateSlotRange(uint32_t start, uint32_t count);
     567                 :     inline void initializeSlotRange(uint32_t start, uint32_t count);
     568                 : 
     569                 :     /*
     570                 :      * Initialize a flat array of slots to this object at a start slot.  The
     571                 :      * caller must ensure that are enough slots.
     572                 :      */
     573                 :     void initSlotRange(uint32_t start, const Value *vector, uint32_t length);
     574                 : 
     575                 :     /*
     576                 :      * Copy a flat array of slots to this object at a start slot. Caller must
     577                 :      * ensure there are enough slots in this object.
     578                 :      */
     579                 :     void copySlotRange(uint32_t start, const Value *vector, uint32_t length);
     580                 : 
     581                 : #ifdef DEBUG
     582                 :     enum SentinelAllowed {
     583                 :         SENTINEL_NOT_ALLOWED,
     584                 :         SENTINEL_ALLOWED
     585                 :     };
     586                 : 
     587                 :     /*
     588                 :      * Check that slot is in range for the object's allocated slots.
     589                 :      * If sentinelAllowed then slot may equal the slot capacity.
     590                 :      */
     591                 :     bool slotInRange(uint32_t slot, SentinelAllowed sentinel = SENTINEL_NOT_ALLOWED) const;
     592                 : #endif
     593                 : 
     594                 :     /* Minimum size for dynamically allocated slots. */
     595                 :     static const uint32_t SLOT_CAPACITY_MIN = 8;
     596                 : 
     597       296858016 :     HeapSlot *fixedSlots() const {
     598       296858016 :         return reinterpret_cast<HeapSlot *>(uintptr_t(this) + sizeof(ObjectImpl));
     599                 :     }
     600                 : 
     601                 :     friend class ElementsHeader;
     602                 :     friend class DenseElementsHeader;
     603                 :     friend class SparseElementsHeader;
     604                 : 
     605                 :     enum DenseElementsResult {
     606                 :         Failure,
     607                 :         ConvertToSparse,
     608                 :         Succeeded
     609                 :     };
     610                 : 
     611               0 :     DenseElementsResult ensureDenseElementsInitialized(JSContext *cx, uint32_t index,
     612                 :                                                        uint32_t extra)
     613                 :     {
     614               0 :         NEW_OBJECT_REPRESENTATION_ONLY();
     615                 : 
     616                 :         MOZ_NOT_REACHED("NYI");
     617                 :         return Failure;
     618                 :     }
     619                 : 
     620                 :     /*
     621                 :      * These functions are currently public for simplicity; in the long run
     622                 :      * it may make sense to make at least some of them private.
     623                 :      */
     624                 : 
     625                 :   public:
     626              -1 :     Shape * lastProperty() const {
     627              -1 :         MOZ_ASSERT(shape_);
     628              -1 :         return shape_;
     629                 :     }
     630                 : 
     631                 :     inline bool isNative() const;
     632                 : 
     633        99318882 :     types::TypeObject *type() const {
     634        99318882 :         MOZ_ASSERT(!hasLazyType());
     635        99318882 :         return type_;
     636                 :     }
     637                 : 
     638      1657710731 :     uint32_t numFixedSlots() const {
     639      1657710731 :         return reinterpret_cast<const shadow::Object *>(this)->numFixedSlots();
     640                 :     }
     641                 : 
     642                 :     /*
     643                 :      * Whether this is the only object which has its specified type. This
     644                 :      * object will have its type constructed lazily as needed by analysis.
     645                 :      */
     646        95737434 :     bool hasSingletonType() const { return !!type_->singleton; }
     647                 : 
     648                 :     /*
     649                 :      * Whether the object's type has not been constructed yet. If an object
     650                 :      * might have a lazy type, use getType() below, otherwise type().
     651                 :      */
     652       146917424 :     bool hasLazyType() const { return type_->lazy(); }
     653                 : 
     654                 :     inline uint32_t slotSpan() const;
     655                 : 
     656                 :     /* Compute dynamicSlotsCount() for this object. */
     657                 :     inline uint32_t numDynamicSlots() const;
     658                 : 
     659                 :     const Shape * nativeLookup(JSContext *cx, jsid id);
     660                 : 
     661                 :     inline Class *getClass() const;
     662                 :     inline JSClass *getJSClass() const;
     663                 :     inline bool hasClass(const Class *c) const;
     664                 :     inline const ObjectOps *getOps() const;
     665                 : 
     666                 :     /*
     667                 :      * An object is a delegate if it is on another object's prototype or scope
     668                 :      * chain, and therefore the delegate might be asked implicitly to get or
     669                 :      * set a property on behalf of another object. Delegates may be accessed
     670                 :      * directly too, as may any object, but only those objects linked after the
     671                 :      * head of any prototype or scope chain are flagged as delegates. This
     672                 :      * definition helps to optimize shape-based property cache invalidation
     673                 :      * (see Purge{Scope,Proto}Chain in jsobj.cpp).
     674                 :      */
     675                 :     inline bool isDelegate() const;
     676                 : 
     677                 :     /*
     678                 :      * Return true if this object is a native one that has been converted from
     679                 :      * shared-immutable prototype-rooted shape storage to dictionary-shapes in
     680                 :      * a doubly-linked list.
     681                 :      */
     682                 :     inline bool inDictionaryMode() const;
     683                 : 
     684       179766087 :     const Value &getSlot(uint32_t slot) const {
     685       179766087 :         MOZ_ASSERT(slotInRange(slot));
     686       179766087 :         uint32_t fixed = numFixedSlots();
     687       179766087 :         if (slot < fixed)
     688        93023132 :             return fixedSlots()[slot];
     689        86742955 :         return slots[slot - fixed];
     690                 :     }
     691                 : 
     692       151526061 :     HeapSlot *getSlotAddressUnchecked(uint32_t slot) {
     693       151526061 :         uint32_t fixed = numFixedSlots();
     694       151526061 :         if (slot < fixed)
     695        68985043 :             return fixedSlots() + slot;
     696        82541018 :         return slots + (slot - fixed);
     697                 :     }
     698                 : 
     699       132882622 :     HeapSlot *getSlotAddress(uint32_t slot) {
     700                 :         /*
     701                 :          * This can be used to get the address of the end of the slots for the
     702                 :          * object, which may be necessary when fetching zero-length arrays of
     703                 :          * slots (e.g. for callObjVarArray).
     704                 :          */
     705       132882622 :         MOZ_ASSERT(slotInRange(slot, SENTINEL_ALLOWED));
     706       132882622 :         return getSlotAddressUnchecked(slot);
     707                 :     }
     708                 : 
     709       132328864 :     HeapSlot &getSlotRef(uint32_t slot) {
     710       132328864 :         MOZ_ASSERT(slotInRange(slot));
     711       132328864 :         return *getSlotAddress(slot);
     712                 :     }
     713                 : 
     714                 :     inline HeapSlot &nativeGetSlotRef(uint32_t slot);
     715                 :     inline const Value &nativeGetSlot(uint32_t slot) const;
     716                 : 
     717                 :     inline void setSlot(uint32_t slot, const Value &value);
     718                 :     inline void initSlot(uint32_t slot, const Value &value);
     719                 :     inline void initSlotUnchecked(uint32_t slot, const Value &value);
     720                 : 
     721                 :     /* For slots which are known to always be fixed, due to the way they are allocated. */
     722                 : 
     723              47 :     HeapSlot &getFixedSlotRef(uint32_t slot) {
     724              47 :         MOZ_ASSERT(slot < numFixedSlots());
     725              47 :         return fixedSlots()[slot];
     726                 :     }
     727                 : 
     728        46031823 :     const Value &getFixedSlot(uint32_t slot) const {
     729        46031823 :         MOZ_ASSERT(slot < numFixedSlots());
     730        46031823 :         return fixedSlots()[slot];
     731                 :     }
     732                 : 
     733                 :     inline void setFixedSlot(uint32_t slot, const Value &value);
     734                 :     inline void initFixedSlot(uint32_t slot, const Value &value);
     735                 : 
     736                 :     /*
     737                 :      * Get the number of dynamic slots to allocate to cover the properties in
     738                 :      * an object with the given number of fixed slots and slot span. The slot
     739                 :      * capacity is not stored explicitly, and the allocated size of the slot
     740                 :      * array is kept in sync with this count.
     741                 :      */
     742                 :     static inline uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span);
     743                 : 
     744                 :     /* Memory usage functions. */
     745                 :     inline size_t sizeOfThis() const;
     746                 : 
     747                 :     /* Elements accessors. */
     748                 : 
     749       224608873 :     ObjectElements * getElementsHeader() const {
     750       224608873 :         return ObjectElements::fromElements(elements);
     751                 :     }
     752                 : 
     753               0 :     ElementsHeader & elementsHeader() const {
     754               0 :         NEW_OBJECT_REPRESENTATION_ONLY();
     755                 :         return *ElementsHeader::fromElements(elements);
     756                 :     }
     757                 : 
     758         8755742 :     inline HeapSlot *fixedElements() const {
     759                 :         MOZ_STATIC_ASSERT(2 * sizeof(Value) == sizeof(ObjectElements),
     760                 :                           "when elements are stored inline, the first two "
     761                 :                           "slots will hold the ObjectElements header");
     762         8755742 :         return &fixedSlots()[2];
     763                 :     }
     764                 : 
     765         2266237 :     void setFixedElements() { this->elements = fixedElements(); }
     766                 : 
     767        33975208 :     inline bool hasDynamicElements() const {
     768                 :         /*
     769                 :          * Note: for objects with zero fixed slots this could potentially give
     770                 :          * a spurious 'true' result, if the end of this object is exactly
     771                 :          * aligned with the end of its arena and dynamic slots are allocated
     772                 :          * immediately afterwards. Such cases cannot occur for dense arrays
     773                 :          * (which have at least two fixed slots) and can only result in a leak.
     774                 :          */
     775        33975208 :         return elements != emptyObjectElements && elements != fixedElements();
     776                 :     }
     777                 : 
     778                 :     /* GC support. */
     779                 :     static inline void readBarrier(ObjectImpl *obj);
     780                 :     static inline void writeBarrierPre(ObjectImpl *obj);
     781                 :     static inline void writeBarrierPost(ObjectImpl *obj, void *addr);
     782                 :     inline void privateWriteBarrierPre(void **oldval);
     783                 :     inline void privateWriteBarrierPost(void **oldval);
     784                 :     void markChildren(JSTracer *trc);
     785                 : 
     786                 :     /* Private data accessors. */
     787                 : 
     788                 :     inline void *&privateRef(uint32_t nfixed) const; /* XXX should be private, not protected! */
     789                 : 
     790                 :     inline bool hasPrivate() const;
     791                 :     inline void *getPrivate() const;
     792                 :     inline void setPrivate(void *data);
     793                 :     inline void setPrivateUnbarriered(void *data);
     794                 :     inline void initPrivate(void *data);
     795                 : 
     796                 :     /* Access private data for an object with a known number of fixed slots. */
     797                 :     inline void *getPrivate(uint32_t nfixed) const;
     798                 : 
     799                 :     /* JIT Accessors */
     800          326661 :     static size_t offsetOfShape() { return offsetof(ObjectImpl, shape_); }
     801          663478 :     HeapPtrShape *addressOfShape() { return &shape_; }
     802                 : 
     803          112495 :     static size_t offsetOfType() { return offsetof(ObjectImpl, type_); }
     804          244412 :     HeapPtrTypeObject *addressOfType() { return &type_; }
     805                 : 
     806          153830 :     static size_t offsetOfElements() { return offsetof(ObjectImpl, elements); }
     807           17924 :     static size_t offsetOfFixedElements() {
     808           17924 :         return sizeof(ObjectImpl) + sizeof(ObjectElements);
     809                 :     }
     810                 : 
     811          130653 :     static size_t getFixedSlotOffset(size_t slot) {
     812          130653 :         return sizeof(ObjectImpl) + slot * sizeof(Value);
     813                 :     }
     814           31610 :     static size_t getPrivateDataOffset(size_t nfixed) { return getFixedSlotOffset(nfixed); }
     815          571997 :     static size_t offsetOfSlots() { return offsetof(ObjectImpl, slots); }
     816                 : };
     817                 : 
     818                 : extern bool
     819                 : DefineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const Value &value,
     820                 :               PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     821                 : 
     822                 : } /* namespace js */
     823                 : 
     824                 : #endif /* ObjectImpl_h__ */

Generated by: LCOV version 1.7