LCOV - app.info - js/src/vm/ObjectImpl.h

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