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

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