LCOV - code coverage report
Current view: directory - js/src/vm - ObjectImpl.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 116 42 36.2 %
Date: 2012-04-07 Functions: 14 8 57.1 %

       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                 : #include "mozilla/Assertions.h"
       9                 : #include "mozilla/Attributes.h"
      10                 : 
      11                 : #include "jsscope.h"
      12                 : #include "jsobjinlines.h"
      13                 : 
      14                 : #include "ObjectImpl.h"
      15                 : 
      16                 : #include "gc/Barrier-inl.h"
      17                 : 
      18                 : #include "ObjectImpl-inl.h"
      19                 : 
      20                 : using namespace js;
      21                 : 
      22           18667 : static ObjectElements emptyElementsHeader(0, 0);
      23                 : 
      24                 : /* Objects with no elements share one empty set of elements. */
      25                 : HeapSlot *js::emptyObjectElements =
      26                 :     reinterpret_cast<HeapSlot *>(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements));
      27                 : 
      28                 : #ifdef DEBUG
      29                 : void
      30        30224190 : js::ObjectImpl::checkShapeConsistency()
      31                 : {
      32                 :     static int throttle = -1;
      33        30224190 :     if (throttle < 0) {
      34           18667 :         if (const char *var = getenv("JS_CHECK_SHAPE_THROTTLE"))
      35               0 :             throttle = atoi(var);
      36           18667 :         if (throttle < 0)
      37           18667 :             throttle = 0;
      38                 :     }
      39        30224190 :     if (throttle == 0)
      40        30224190 :         return;
      41                 : 
      42               0 :     MOZ_ASSERT(isNative());
      43                 : 
      44               0 :     Shape *shape = lastProperty();
      45               0 :     Shape *prev = NULL;
      46                 : 
      47               0 :     if (inDictionaryMode()) {
      48               0 :         MOZ_ASSERT(shape->hasTable());
      49                 : 
      50               0 :         PropertyTable &table = shape->table();
      51               0 :         for (uint32_t fslot = table.freelist; fslot != SHAPE_INVALID_SLOT;
      52               0 :              fslot = getSlot(fslot).toPrivateUint32()) {
      53               0 :             MOZ_ASSERT(fslot < slotSpan());
      54                 :         }
      55                 : 
      56               0 :         for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) {
      57               0 :             MOZ_ASSERT_IF(shape != lastProperty(), !shape->hasTable());
      58                 : 
      59               0 :             Shape **spp = table.search(shape->propid(), false);
      60               0 :             MOZ_ASSERT(SHAPE_FETCH(spp) == shape);
      61                 :         }
      62                 : 
      63               0 :         shape = lastProperty();
      64               0 :         for (int n = throttle; --n >= 0 && shape; shape = shape->parent) {
      65               0 :             MOZ_ASSERT_IF(shape->slot() != SHAPE_INVALID_SLOT, shape->slot() < slotSpan());
      66               0 :             if (!prev) {
      67               0 :                 MOZ_ASSERT(shape == lastProperty());
      68               0 :                 MOZ_ASSERT(shape->listp == &shape_);
      69                 :             } else {
      70               0 :                 MOZ_ASSERT(shape->listp == &prev->parent);
      71                 :             }
      72               0 :             prev = shape;
      73                 :         }
      74                 :     } else {
      75               0 :         for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) {
      76               0 :             if (shape->hasTable()) {
      77               0 :                 PropertyTable &table = shape->table();
      78               0 :                 MOZ_ASSERT(shape->parent);
      79               0 :                 for (Shape::Range r(shape); !r.empty(); r.popFront()) {
      80               0 :                     Shape **spp = table.search(r.front().propid(), false);
      81               0 :                     MOZ_ASSERT(SHAPE_FETCH(spp) == &r.front());
      82                 :                 }
      83                 :             }
      84               0 :             if (prev) {
      85               0 :                 MOZ_ASSERT(prev->maybeSlot() >= shape->maybeSlot());
      86               0 :                 shape->kids.checkConsistency(prev);
      87                 :             }
      88               0 :             prev = shape;
      89                 :         }
      90                 :     }
      91                 : }
      92                 : #endif
      93                 : 
      94                 : void
      95            2235 : js::ObjectImpl::initSlotRange(uint32_t start, const Value *vector, uint32_t length)
      96                 : {
      97            2235 :     JSCompartment *comp = compartment();
      98                 :     HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
      99            2235 :     getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
     100            2235 :     for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
     101               0 :         sp->init(comp, this->asObjectPtr(), start++, *vector++);
     102            5898 :     for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
     103            3663 :         sp->init(comp, this->asObjectPtr(), start++, *vector++);
     104            2235 : }
     105                 : 
     106                 : void
     107          376467 : js::ObjectImpl::copySlotRange(uint32_t start, const Value *vector, uint32_t length)
     108                 : {
     109          376467 :     JSCompartment *comp = compartment();
     110                 :     HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
     111          376467 :     getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
     112          894623 :     for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
     113          518156 :         sp->set(comp, this->asObjectPtr(), start++, *vector++);
     114         1057556 :     for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
     115          681089 :         sp->set(comp, this->asObjectPtr(), start++, *vector++);
     116          376467 : }
     117                 : 
     118                 : #ifdef DEBUG
     119                 : bool
     120       505690759 : js::ObjectImpl::slotInRange(uint32_t slot, SentinelAllowed sentinel) const
     121                 : {
     122       505690759 :     uint32_t capacity = numFixedSlots() + numDynamicSlots();
     123       505690759 :     if (sentinel == SENTINEL_ALLOWED)
     124       134002811 :         return slot <= capacity;
     125       371687948 :     return slot < capacity;
     126                 : }
     127                 : #endif /* DEBUG */
     128                 : 
     129                 : #if defined(_MSC_VER) && _MSC_VER >= 1500
     130                 : /*
     131                 :  * Work around a compiler bug in MSVC9 and above, where inlining this function
     132                 :  * causes stack pointer offsets to go awry and spp to refer to something higher
     133                 :  * up the stack.
     134                 :  */
     135                 : MOZ_NEVER_INLINE
     136                 : #endif
     137                 : const Shape *
     138        65493592 : js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
     139                 : {
     140        65493592 :     MOZ_ASSERT(isNative());
     141                 :     Shape **spp;
     142        65493592 :     return Shape::search(cx, lastProperty(), id, &spp);
     143                 : }
     144                 : 
     145                 : void
     146         2872168 : js::ObjectImpl::markChildren(JSTracer *trc)
     147                 : {
     148         2872168 :     MarkTypeObject(trc, &type_, "type");
     149                 : 
     150         2872168 :     MarkShape(trc, &shape_, "shape");
     151                 : 
     152         2872168 :     Class *clasp = shape_->getObjectClass();
     153         2872168 :     JSObject *obj = asObjectPtr();
     154         2872168 :     if (clasp->trace)
     155         2439286 :         clasp->trace(trc, obj);
     156                 : 
     157         2872168 :     if (shape_->isNative())
     158         2840717 :         MarkObjectSlots(trc, obj, 0, obj->slotSpan());
     159         2872168 : }
     160                 : 
     161                 : bool
     162               0 : js::SparseElementsHeader::defineElement(JSContext *cx, ObjectImpl *obj,
     163                 :                                         uint32_t index, const Value &value,
     164                 :                                         PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
     165                 : {
     166               0 :     MOZ_ASSERT(this == &obj->elementsHeader());
     167                 : 
     168               0 :     MOZ_NOT_REACHED("NYI");
     169                 :     return false;
     170                 : }
     171                 : 
     172                 : bool
     173               0 : js::DenseElementsHeader::defineElement(JSContext *cx, ObjectImpl *obj,
     174                 :                                        uint32_t index, const Value &value,
     175                 :                                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
     176                 : {
     177               0 :     MOZ_ASSERT(this == &obj->elementsHeader());
     178                 : 
     179                 :     /*
     180                 :      * If the new property doesn't have the right attributes, or an atypical
     181                 :      * getter or setter is being used, go sparse.
     182                 :      */
     183               0 :     if (attrs != JSPROP_ENUMERATE ||
     184                 :         (attrs & (JSPROP_GETTER | JSPROP_SETTER)) || getter || setter)
     185                 :     {
     186               0 :         if (!obj->makeElementsSparse(cx))
     187               0 :             return false;
     188               0 :         SparseElementsHeader &elts = obj->elementsHeader().asSparseElements();
     189               0 :         return elts.defineElement(cx, obj, index, value, getter, setter, attrs);
     190                 :     }
     191                 : 
     192                 :     /* If space for the dense element already exists, we only need set it. */
     193               0 :     uint32_t initLen = initializedLength();
     194               0 :     if (index < initLen) {
     195               0 :         obj->elements[index].set(obj->asObjectPtr(), index, value);
     196               0 :         return true;
     197                 :     }
     198                 : 
     199                 :     /* Otherwise we ensure space for it exists and that it's initialized. */
     200               0 :     ObjectImpl::DenseElementsResult res = obj->ensureDenseElementsInitialized(cx, index, 0);
     201                 : 
     202                 :     /* Propagate any error. */
     203               0 :     if (res == ObjectImpl::Failure)
     204               0 :         return false;
     205                 : 
     206                 :     /* Otherwise, if the index was too far out of range, go sparse. */
     207               0 :     if (res == ObjectImpl::ConvertToSparse) {
     208               0 :         if (!obj->makeElementsSparse(cx))
     209               0 :             return false;
     210               0 :         SparseElementsHeader &elts = obj->elementsHeader().asSparseElements();
     211               0 :         return elts.defineElement(cx, obj, index, value, getter, setter, attrs);
     212                 :     }
     213                 : 
     214                 :     /* But if we were able to ensure the element's existence, we're good. */
     215               0 :     MOZ_ASSERT(res == ObjectImpl::Succeeded);
     216               0 :     obj->elements[index].set(obj->asObjectPtr(), index, value);
     217               0 :     return true;
     218                 : }
     219                 : 
     220                 : static JSObject *
     221               0 : ArrayBufferDelegate(JSContext *cx, ObjectImpl *obj)
     222                 : {
     223               0 :     MOZ_ASSERT(obj->hasClass(&ArrayBufferClass));
     224               0 :     if (obj->getPrivate())
     225               0 :         return static_cast<JSObject *>(obj->getPrivate());
     226               0 :     JSObject *delegate = NewObjectWithGivenProto(cx, &ObjectClass, obj->getProto(), NULL);
     227               0 :     obj->setPrivate(delegate);
     228               0 :     return delegate;
     229                 : }
     230                 : 
     231                 : template <typename T>
     232                 : bool
     233                 : js::TypedElementsHeader<T>::defineElement(JSContext *cx, ObjectImpl *obj,
     234                 :                                        uint32_t index, const Value &value,
     235                 :                                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
     236                 : {
     237                 :     /*
     238                 :      * XXX This isn't really a good error message, if this is even how typed
     239                 :      *     arrays should behave...
     240                 :      */
     241                 :     js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_OBJECT_NOT_EXTENSIBLE,
     242                 :                              JSDVG_IGNORE_STACK, ObjectValue(*(JSObject*)obj), // XXX
     243                 :                              NULL, NULL, NULL);
     244                 :     return false;
     245                 : }
     246                 : 
     247                 : bool
     248               0 : js::ArrayBufferElementsHeader::defineElement(JSContext *cx, ObjectImpl *obj,
     249                 :                                              uint32_t index, const Value &value,
     250                 :                                              PropertyOp getter, StrictPropertyOp setter,
     251                 :                                              unsigned attrs)
     252                 : {
     253               0 :     MOZ_ASSERT(this == &obj->elementsHeader());
     254                 : 
     255               0 :     JSObject *delegate = ArrayBufferDelegate(cx, obj);
     256               0 :     if (!delegate)
     257               0 :         return false;
     258               0 :     return DefineElement(cx, delegate, index, value, getter, setter, attrs);
     259                 : }
     260                 : 
     261                 : bool
     262               0 : js::DefineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const Value &value,
     263                 :                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
     264                 : {
     265               0 :     NEW_OBJECT_REPRESENTATION_ONLY();
     266                 : 
     267                 :     ElementsHeader &header = obj->elementsHeader();
     268                 : 
     269                 :     switch (header.kind()) {
     270                 :       case DenseElements:
     271                 :         return header.asDenseElements().defineElement(cx, obj, index, value, getter, setter,
     272                 :                                                       attrs);
     273                 :       case SparseElements:
     274                 :         return header.asSparseElements().defineElement(cx, obj, index, value, getter, setter,
     275                 :                                                        attrs);
     276                 :       case Uint8Elements:
     277                 :         return header.asUint8Elements().defineElement(cx, obj, index, value, getter, setter,
     278                 :                                                       attrs);
     279                 :       case Int8Elements:
     280                 :         return header.asInt8Elements().defineElement(cx, obj, index, value, getter, setter,
     281                 :                                                      attrs);
     282                 :       case Uint16Elements:
     283                 :         return header.asUint16Elements().defineElement(cx, obj, index, value, getter, setter,
     284                 :                                                        attrs);
     285                 :       case Int16Elements:
     286                 :         return header.asInt16Elements().defineElement(cx, obj, index, value, getter, setter,
     287                 :                                                       attrs);
     288                 :       case Uint32Elements:
     289                 :         return header.asUint32Elements().defineElement(cx, obj, index, value, getter, setter,
     290                 :                                                        attrs);
     291                 :       case Int32Elements:
     292                 :         return header.asInt32Elements().defineElement(cx, obj, index, value, getter, setter,
     293                 :                                                       attrs);
     294                 :       case Uint8ClampedElements:
     295                 :         return header.asUint8ClampedElements().defineElement(cx, obj, index, value,
     296                 :                                                              getter, setter, attrs);
     297                 :       case Float32Elements:
     298                 :         return header.asFloat32Elements().defineElement(cx, obj, index, value, getter, setter,
     299                 :                                                         attrs);
     300                 :       case Float64Elements:
     301                 :         return header.asFloat64Elements().defineElement(cx, obj, index, value, getter, setter,
     302                 :                                                         attrs);
     303                 :       case ArrayBufferElements:
     304                 :         return header.asArrayBufferElements().defineElement(cx, obj, index, value, getter, setter,
     305                 :                                                             attrs);
     306                 :     }
     307                 : 
     308                 :     MOZ_NOT_REACHED("bad elements kind!");
     309                 :     return false;
     310           56001 : }

Generated by: LCOV version 1.7