LCOV - code coverage report
Current view: directory - js/src - jsobjinlines.h (source / functions) Found Hit Coverage
Test: app.info Lines: 741 664 89.6 %
Date: 2012-04-07 Functions: 193 179 92.7 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=99:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #ifndef jsobjinlines_h___
      42                 : #define jsobjinlines_h___
      43                 : 
      44                 : #include <new>
      45                 : 
      46                 : #include "jsapi.h"
      47                 : #include "jsarray.h"
      48                 : #include "jsbool.h"
      49                 : #include "jscntxt.h"
      50                 : #include "jsdate.h"
      51                 : #include "jsfun.h"
      52                 : #include "jsgcmark.h"
      53                 : #include "jsiter.h"
      54                 : #include "jslock.h"
      55                 : #include "jsnum.h"
      56                 : #include "jsobj.h"
      57                 : #include "jsprobes.h"
      58                 : #include "jspropertytree.h"
      59                 : #include "jsproxy.h"
      60                 : #include "jsscope.h"
      61                 : #include "jsstr.h"
      62                 : #include "jstypedarray.h"
      63                 : #include "jsxml.h"
      64                 : #include "jswrapper.h"
      65                 : 
      66                 : #include "gc/Barrier.h"
      67                 : #include "js/TemplateLib.h"
      68                 : 
      69                 : #include "vm/BooleanObject.h"
      70                 : #include "vm/GlobalObject.h"
      71                 : #include "vm/NumberObject.h"
      72                 : #include "vm/RegExpStatics.h"
      73                 : #include "vm/StringObject.h"
      74                 : 
      75                 : #include "jsatominlines.h"
      76                 : #include "jsfuninlines.h"
      77                 : #include "jsgcinlines.h"
      78                 : #include "jsinferinlines.h"
      79                 : #include "jsscopeinlines.h"
      80                 : #include "jsscriptinlines.h"
      81                 : 
      82                 : #include "gc/Barrier-inl.h"
      83                 : 
      84                 : #include "vm/ObjectImpl-inl.h"
      85                 : #include "vm/RegExpStatics-inl.h"
      86                 : #include "vm/String-inl.h"
      87                 : 
      88                 : inline bool
      89        38700612 : JSObject::enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp)
      90                 : {
      91        38700612 :     JSNewEnumerateOp op = getOps()->enumerate;
      92        38700612 :     return (op ? op : JS_EnumerateState)(cx, this, iterop, statep, idp);
      93                 : }
      94                 : 
      95                 : inline bool
      96          892635 : JSObject::defaultValue(JSContext *cx, JSType hint, js::Value *vp)
      97                 : {
      98          892635 :     JSConvertOp op = getClass()->convert;
      99          892635 :     bool ok = (op == JS_ConvertStub ? js::DefaultValue : op)(cx, this, hint, vp);
     100          892635 :     JS_ASSERT_IF(ok, vp->isPrimitive());
     101          892635 :     return ok;
     102                 : }
     103                 : 
     104                 : inline JSType
     105           28137 : JSObject::typeOf(JSContext *cx)
     106                 : {
     107           28137 :     js::TypeOfOp op = getOps()->typeOf;
     108           28137 :     return (op ? op : js_TypeOf)(cx, this);
     109                 : }
     110                 : 
     111                 : inline JSObject *
     112         1620169 : JSObject::thisObject(JSContext *cx)
     113                 : {
     114         1620169 :     JSObjectOp op = getOps()->thisObject;
     115         1620169 :     return op ? op(cx, this) : this;
     116                 : }
     117                 : 
     118                 : inline JSBool
     119         2812112 : JSObject::setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
     120                 : {
     121         2812112 :     if (getOps()->setGeneric)
     122         1761478 :         return nonNativeSetProperty(cx, id, vp, strict);
     123         1050634 :     return js_SetPropertyHelper(cx, this, id, 0, vp, strict);
     124                 : }
     125                 : 
     126                 : inline JSBool
     127           14138 : JSObject::setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict)
     128                 : {
     129           14138 :     return setGeneric(cx, ATOM_TO_JSID(name), vp, strict);
     130                 : }
     131                 : 
     132                 : inline JSBool
     133           22239 : JSObject::setElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict)
     134                 : {
     135           22239 :     if (getOps()->setElement)
     136           22238 :         return nonNativeSetElement(cx, index, vp, strict);
     137               1 :     return js_SetElementHelper(cx, this, index, 0, vp, strict);
     138                 : }
     139                 : 
     140                 : inline JSBool
     141               0 : JSObject::setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict)
     142                 : {
     143               0 :     return setGeneric(cx, SPECIALID_TO_JSID(sid), vp, strict);
     144                 : }
     145                 : 
     146                 : inline JSBool
     147           31914 : JSObject::setGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp)
     148                 : {
     149           31914 :     js::types::MarkTypePropertyConfigured(cx, this, id);
     150           31914 :     js::GenericAttributesOp op = getOps()->setGenericAttributes;
     151           31914 :     return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
     152                 : }
     153                 : 
     154                 : inline JSBool
     155               0 : JSObject::setPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp)
     156                 : {
     157               0 :     return setGenericAttributes(cx, ATOM_TO_JSID(name), attrsp);
     158                 : }
     159                 : 
     160                 : inline JSBool
     161               0 : JSObject::setElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp)
     162                 : {
     163               0 :     js::ElementAttributesOp op = getOps()->setElementAttributes;
     164               0 :     return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp);
     165                 : }
     166                 : 
     167                 : inline JSBool
     168               0 : JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
     169                 : {
     170               0 :     return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
     171                 : }
     172                 : 
     173                 : inline bool
     174           31914 : JSObject::changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs)
     175                 : {
     176           31914 :     return !!changeProperty(cx, shape, attrs, 0, shape->getter(), shape->setter());
     177                 : }
     178                 : 
     179                 : inline JSBool
     180        21028366 : JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
     181                 : {
     182        21028366 :     js::GenericIdOp op = getOps()->getGeneric;
     183        21028366 :     if (op) {
     184         2282341 :         if (!op(cx, this, receiver, id, vp))
     185              18 :             return false;
     186                 :     } else {
     187        18746025 :         if (!js_GetProperty(cx, this, receiver, id, vp))
     188              54 :             return false;
     189                 :     }
     190        21028294 :     return true;
     191                 : }
     192                 : 
     193                 : inline JSBool
     194         2379523 : JSObject::getProperty(JSContext *cx, JSObject *receiver, js::PropertyName *name, js::Value *vp)
     195                 : {
     196         2379523 :     return getGeneric(cx, receiver, ATOM_TO_JSID(name), vp);
     197                 : }
     198                 : 
     199                 : inline JSBool
     200        17624106 : JSObject::getGeneric(JSContext *cx, jsid id, js::Value *vp)
     201                 : {
     202        17624106 :     return getGeneric(cx, this, id, vp);
     203                 : }
     204                 : 
     205                 : inline JSBool
     206         2850927 : JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp)
     207                 : {
     208         2850927 :     return getGeneric(cx, ATOM_TO_JSID(name), vp);
     209                 : }
     210                 : 
     211                 : inline bool
     212            1548 : JSObject::deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict)
     213                 : {
     214            1548 :     jsid id = js_CheckForStringIndex(ATOM_TO_JSID(name));
     215            1548 :     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     216            1548 :     js::types::MarkTypePropertyConfigured(cx, this, id);
     217            1548 :     js::DeletePropertyOp op = getOps()->deleteProperty;
     218            1548 :     return (op ? op : js_DeleteProperty)(cx, this, name, rval, strict);
     219                 : }
     220                 : 
     221                 : inline bool
     222          195138 : JSObject::deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict)
     223                 : {
     224                 :     jsid id;
     225          195138 :     if (!js::IndexToId(cx, index, &id))
     226               0 :         return false;
     227          195138 :     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     228          195138 :     js::types::MarkTypePropertyConfigured(cx, this, id);
     229          195138 :     js::DeleteElementOp op = getOps()->deleteElement;
     230          195138 :     return (op ? op : js_DeleteElement)(cx, this, index, rval, strict);
     231                 : }
     232                 : 
     233                 : inline bool
     234               0 : JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict)
     235                 : {
     236               0 :     jsid id = SPECIALID_TO_JSID(sid);
     237               0 :     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     238               0 :     js::types::MarkTypePropertyConfigured(cx, this, id);
     239               0 :     js::DeleteSpecialOp op = getOps()->deleteSpecial;
     240               0 :     return (op ? op : js_DeleteSpecial)(cx, this, sid, rval, strict);
     241                 : }
     242                 : 
     243                 : inline void
     244        30978300 : JSObject::finalize(js::FreeOp *fop)
     245                 : {
     246        30978300 :     js::Probes::finalizeObject(this);
     247                 : 
     248        30978300 :     if (!fop->onBackgroundThread()) {
     249                 :         /*
     250                 :          * Finalize obj first, in case it needs map and slots. Objects with
     251                 :          * finalize hooks are not finalized in the background, as the class is
     252                 :          * stored in the object's shape, which may have already been destroyed.
     253                 :          */
     254        30444269 :         js::Class *clasp = getClass();
     255        30444269 :         if (clasp->finalize)
     256         1831884 :             clasp->finalize(fop, this);
     257                 :     }
     258                 : 
     259        30978300 :     finish(fop);
     260        30978300 : }
     261                 : 
     262                 : inline JSObject *
     263      1043233097 : JSObject::getParent() const
     264                 : {
     265      1043233097 :     return lastProperty()->getObjectParent();
     266                 : }
     267                 : 
     268                 : inline JSObject *
     269         1989979 : JSObject::enclosingScope()
     270                 : {
     271         1989979 :     return isScope() ? &asScope().enclosingScope() : getParent();
     272                 : }
     273                 : 
     274                 : inline bool
     275           67617 : JSObject::isFixedSlot(size_t slot)
     276                 : {
     277           67617 :     JS_ASSERT(!isDenseArray());
     278           67617 :     return slot < numFixedSlots();
     279                 : }
     280                 : 
     281                 : inline size_t
     282          229294 : JSObject::dynamicSlotIndex(size_t slot)
     283                 : {
     284          229294 :     JS_ASSERT(!isDenseArray() && slot >= numFixedSlots());
     285          229294 :     return slot - numFixedSlots();
     286                 : }
     287                 : 
     288                 : inline void
     289           12034 : JSObject::setLastPropertyInfallible(const js::Shape *shape)
     290                 : {
     291           12034 :     JS_ASSERT(!shape->inDictionary());
     292           12034 :     JS_ASSERT(shape->compartment() == compartment());
     293           12034 :     JS_ASSERT(!inDictionaryMode());
     294           12034 :     JS_ASSERT(slotSpan() == shape->slotSpan());
     295           12034 :     JS_ASSERT(numFixedSlots() == shape->numFixedSlots());
     296                 : 
     297           12034 :     shape_ = const_cast<js::Shape *>(shape);
     298           12034 : }
     299                 : 
     300                 : inline void
     301            1224 : JSObject::removeLastProperty(JSContext *cx)
     302                 : {
     303            1224 :     JS_ASSERT(canRemoveLastProperty());
     304            1224 :     JS_ALWAYS_TRUE(setLastProperty(cx, lastProperty()->previous()));
     305            1224 : }
     306                 : 
     307                 : inline bool
     308            2457 : JSObject::canRemoveLastProperty()
     309                 : {
     310                 :     /*
     311                 :      * Check that the information about the object stored in the last
     312                 :      * property's base shape is consistent with that stored in the previous
     313                 :      * shape. If not consistent, then the last property cannot be removed as it
     314                 :      * will induce a change in the object itself, and the object must be
     315                 :      * converted to dictionary mode instead. See BaseShape comment in jsscope.h
     316                 :      */
     317            2457 :     JS_ASSERT(!inDictionaryMode());
     318            2457 :     const js::Shape *previous = lastProperty()->previous();
     319            2457 :     return previous->getObjectParent() == lastProperty()->getObjectParent()
     320            2457 :         && previous->getObjectFlags() == lastProperty()->getObjectFlags();
     321                 : }
     322                 : 
     323                 : inline const js::HeapSlot *
     324          182670 : JSObject::getRawSlots()
     325                 : {
     326          182670 :     JS_ASSERT(isGlobal());
     327          182670 :     return slots;
     328                 : }
     329                 : 
     330                 : inline const js::Value &
     331        24636283 : JSObject::getReservedSlot(unsigned index) const
     332                 : {
     333        24636283 :     JS_ASSERT(index < JSSLOT_FREE(getClass()));
     334        24636283 :     return getSlot(index);
     335                 : }
     336                 : 
     337                 : inline js::HeapSlot &
     338          146957 : JSObject::getReservedSlotRef(unsigned index)
     339                 : {
     340          146957 :     JS_ASSERT(index < JSSLOT_FREE(getClass()));
     341          146957 :     return getSlotRef(index);
     342                 : }
     343                 : 
     344                 : inline void
     345         6111062 : JSObject::setReservedSlot(unsigned index, const js::Value &v)
     346                 : {
     347         6111062 :     JS_ASSERT(index < JSSLOT_FREE(getClass()));
     348         6111062 :     setSlot(index, v);
     349         6111062 : }
     350                 : 
     351                 : inline void
     352          100595 : JSObject::initReservedSlot(unsigned index, const js::Value &v)
     353                 : {
     354          100595 :     JS_ASSERT(index < JSSLOT_FREE(getClass()));
     355          100595 :     initSlot(index, v);
     356          100595 : }
     357                 : 
     358                 : inline void
     359             450 : JSObject::prepareSlotRangeForOverwrite(size_t start, size_t end)
     360                 : {
     361             900 :     for (size_t i = start; i < end; i++)
     362             450 :         getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot();
     363             450 : }
     364                 : 
     365                 : inline void
     366          558739 : JSObject::prepareElementRangeForOverwrite(size_t start, size_t end)
     367                 : {
     368          558739 :     JS_ASSERT(isDenseArray());
     369          558739 :     JS_ASSERT(end <= getDenseArrayInitializedLength());
     370          628087 :     for (size_t i = start; i < end; i++)
     371           69348 :         elements[i].js::HeapSlot::~HeapSlot();
     372          558739 : }
     373                 : 
     374                 : inline uint32_t
     375        41919127 : JSObject::getArrayLength() const
     376                 : {
     377        41919127 :     JS_ASSERT(isArray());
     378        41919127 :     return getElementsHeader()->length;
     379                 : }
     380                 : 
     381                 : inline void
     382         3410042 : JSObject::setArrayLength(JSContext *cx, uint32_t length)
     383                 : {
     384         3410042 :     JS_ASSERT(isArray());
     385                 : 
     386         3410042 :     if (length > INT32_MAX) {
     387                 :         /*
     388                 :          * Mark the type of this object as possibly not a dense array, per the
     389                 :          * requirements of OBJECT_FLAG_NON_DENSE_ARRAY.
     390                 :          */
     391                 :         js::types::MarkTypeObjectFlags(cx, this,
     392                 :                                        js::types::OBJECT_FLAG_NON_PACKED_ARRAY |
     393              36 :                                        js::types::OBJECT_FLAG_NON_DENSE_ARRAY);
     394              36 :         jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
     395                 :         js::types::AddTypePropertyId(cx, this, lengthId,
     396              36 :                                      js::types::Type::DoubleType());
     397                 :     }
     398                 : 
     399         3410042 :     getElementsHeader()->length = length;
     400         3410042 : }
     401                 : 
     402                 : inline void
     403         6105891 : JSObject::setDenseArrayLength(uint32_t length)
     404                 : {
     405                 :     /* Variant of setArrayLength for use on dense arrays where the length cannot overflow int32. */
     406         6105891 :     JS_ASSERT(isDenseArray());
     407         6105891 :     JS_ASSERT(length <= INT32_MAX);
     408         6105891 :     getElementsHeader()->length = length;
     409         6105891 : }
     410                 : 
     411                 : inline void
     412          558739 : JSObject::setDenseArrayInitializedLength(uint32_t length)
     413                 : {
     414          558739 :     JS_ASSERT(isDenseArray());
     415          558739 :     JS_ASSERT(length <= getDenseArrayCapacity());
     416          558739 :     prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength);
     417          558739 :     getElementsHeader()->initializedLength = length;
     418          558739 : }
     419                 : 
     420                 : inline uint32_t
     421        31303295 : JSObject::getDenseArrayCapacity()
     422                 : {
     423        31303295 :     JS_ASSERT(isDenseArray());
     424        31303295 :     return getElementsHeader()->capacity;
     425                 : }
     426                 : 
     427                 : inline bool
     428         2593552 : JSObject::ensureElements(JSContext *cx, uint32_t capacity)
     429                 : {
     430         2593552 :     if (capacity > getDenseArrayCapacity())
     431           24751 :         return growElements(cx, capacity);
     432         2568801 :     return true;
     433                 : }
     434                 : 
     435                 : inline void
     436        23073278 : JSObject::setDenseArrayElement(unsigned idx, const js::Value &val)
     437                 : {
     438        23073278 :     JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
     439        23073278 :     elements[idx].set(this, idx, val);
     440        23073278 : }
     441                 : 
     442                 : inline void
     443          487065 : JSObject::initDenseArrayElement(unsigned idx, const js::Value &val)
     444                 : {
     445          487065 :     JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
     446          487065 :     elements[idx].init(this, idx, val);
     447          487065 : }
     448                 : 
     449                 : inline void
     450        23025481 : JSObject::setDenseArrayElementWithType(JSContext *cx, unsigned idx, const js::Value &val)
     451                 : {
     452        23025481 :     js::types::AddTypePropertyId(cx, this, JSID_VOID, val);
     453        23025481 :     setDenseArrayElement(idx, val);
     454        23025481 : }
     455                 : 
     456                 : inline void
     457          487065 : JSObject::initDenseArrayElementWithType(JSContext *cx, unsigned idx, const js::Value &val)
     458                 : {
     459          487065 :     js::types::AddTypePropertyId(cx, this, JSID_VOID, val);
     460          487065 :     initDenseArrayElement(idx, val);
     461          487065 : }
     462                 : 
     463                 : inline void
     464           42995 : JSObject::copyDenseArrayElements(unsigned dstStart, const js::Value *src, unsigned count)
     465                 : {
     466           42995 :     JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
     467           42995 :     JSCompartment *comp = compartment();
     468          181196 :     for (unsigned i = 0; i < count; ++i)
     469          138201 :         elements[dstStart + i].set(comp, this, dstStart + i, src[i]);
     470           42995 : }
     471                 : 
     472                 : inline void
     473           43384 : JSObject::initDenseArrayElements(unsigned dstStart, const js::Value *src, unsigned count)
     474                 : {
     475           43384 :     JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
     476           43384 :     JSCompartment *comp = compartment();
     477          345103 :     for (unsigned i = 0; i < count; ++i)
     478          301719 :         elements[dstStart + i].init(comp, this, dstStart + i, src[i]);
     479           43384 : }
     480                 : 
     481                 : inline void
     482            1386 : JSObject::moveDenseArrayElements(unsigned dstStart, unsigned srcStart, unsigned count)
     483                 : {
     484            1386 :     JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
     485            1386 :     JS_ASSERT(srcStart + count <= getDenseArrayInitializedLength());
     486                 : 
     487                 :     /*
     488                 :      * Using memmove here would skip write barriers. Also, we need to consider
     489                 :      * an array containing [A, B, C], in the following situation:
     490                 :      *
     491                 :      * 1. Incremental GC marks slot 0 of array (i.e., A), then returns to JS code.
     492                 :      * 2. JS code moves slots 1..2 into slots 0..1, so it contains [B, C, C].
     493                 :      * 3. Incremental GC finishes by marking slots 1 and 2 (i.e., C).
     494                 :      *
     495                 :      * Since normal marking never happens on B, it is very important that the
     496                 :      * write barrier is invoked here on B, despite the fact that it exists in
     497                 :      * the array before and after the move.
     498                 :     */
     499            1386 :     JSCompartment *comp = compartment();
     500            1386 :     if (comp->needsBarrier()) {
     501              23 :         if (dstStart < srcStart) {
     502              23 :             js::HeapSlot *dst = elements + dstStart;
     503              23 :             js::HeapSlot *src = elements + srcStart;
     504              30 :             for (unsigned i = 0; i < count; i++, dst++, src++)
     505               7 :                 dst->set(comp, this, dst - elements, *src);
     506                 :         } else {
     507               0 :             js::HeapSlot *dst = elements + dstStart + count - 1;
     508               0 :             js::HeapSlot *src = elements + srcStart + count - 1;
     509               0 :             for (unsigned i = 0; i < count; i++, dst--, src--)
     510               0 :                 dst->set(comp, this, dst - elements, *src);
     511                 :         }
     512                 :     } else {
     513            1363 :         memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
     514            1363 :         SlotRangeWriteBarrierPost(comp, this, dstStart, count);
     515                 :     }
     516            1386 : }
     517                 : 
     518                 : inline void
     519              66 : JSObject::moveDenseArrayElementsUnbarriered(unsigned dstStart, unsigned srcStart, unsigned count)
     520                 : {
     521              66 :     JS_ASSERT(!compartment()->needsBarrier());
     522                 : 
     523              66 :     JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
     524              66 :     JS_ASSERT(srcStart + count <= getDenseArrayCapacity());
     525                 : 
     526              66 :     memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
     527              66 : }
     528                 : 
     529                 : inline bool
     530                 : JSObject::denseArrayHasInlineSlots() const
     531                 : {
     532                 :     JS_ASSERT(isDenseArray());
     533                 :     return elements == fixedElements();
     534                 : }
     535                 : 
     536                 : namespace js {
     537                 : 
     538                 : /*
     539                 :  * Any name atom for a function which will be added as a DeclEnv object to the
     540                 :  * scope chain above call objects for fun.
     541                 :  */
     542                 : static inline JSAtom *
     543          782484 : CallObjectLambdaName(JSFunction *fun)
     544                 : {
     545          782484 :     return (fun->flags & JSFUN_LAMBDA) ? fun->atom.get() : NULL;
     546                 : }
     547                 : 
     548                 : } /* namespace js */
     549                 : 
     550                 : inline const js::Value &
     551           91305 : JSObject::getDateUTCTime() const
     552                 : {
     553           91305 :     JS_ASSERT(isDate());
     554           91305 :     return getFixedSlot(JSSLOT_DATE_UTC_TIME);
     555                 : }
     556                 : 
     557                 : inline void
     558           52158 : JSObject::setDateUTCTime(const js::Value &time)
     559                 : {
     560           52158 :     JS_ASSERT(isDate());
     561           52158 :     setFixedSlot(JSSLOT_DATE_UTC_TIME, time);
     562           52158 : }
     563                 : 
     564                 : inline js::NativeIterator *
     565        31206563 : JSObject::getNativeIterator() const
     566                 : {
     567        31206563 :     return (js::NativeIterator *) getPrivate();
     568                 : }
     569                 : 
     570                 : inline void
     571          397137 : JSObject::setNativeIterator(js::NativeIterator *ni)
     572                 : {
     573          397137 :     setPrivate(ni);
     574          397137 : }
     575                 : 
     576                 : inline JSLinearString *
     577         4732751 : JSObject::getNamePrefix() const
     578                 : {
     579         4732751 :     JS_ASSERT(isNamespace() || isQName());
     580         4732751 :     const js::Value &v = getSlot(JSSLOT_NAME_PREFIX);
     581         4732751 :     return !v.isUndefined() ? &v.toString()->asLinear() : NULL;
     582                 : }
     583                 : 
     584                 : inline jsval
     585         4735284 : JSObject::getNamePrefixVal() const
     586                 : {
     587         4735284 :     JS_ASSERT(isNamespace() || isQName());
     588         4735284 :     return getSlot(JSSLOT_NAME_PREFIX);
     589                 : }
     590                 : 
     591                 : inline void
     592         4735783 : JSObject::setNamePrefix(JSLinearString *prefix)
     593                 : {
     594         4735783 :     JS_ASSERT(isNamespace() || isQName());
     595         4735783 :     setSlot(JSSLOT_NAME_PREFIX, prefix ? js::StringValue(prefix) : js::UndefinedValue());
     596         4735783 : }
     597                 : 
     598                 : inline void
     599               0 : JSObject::clearNamePrefix()
     600                 : {
     601               0 :     JS_ASSERT(isNamespace() || isQName());
     602               0 :     setSlot(JSSLOT_NAME_PREFIX, js::UndefinedValue());
     603               0 : }
     604                 : 
     605                 : inline JSLinearString *
     606         4746261 : JSObject::getNameURI() const
     607                 : {
     608         4746261 :     JS_ASSERT(isNamespace() || isQName());
     609         4746261 :     const js::Value &v = getSlot(JSSLOT_NAME_URI);
     610         4746261 :     return !v.isUndefined() ? &v.toString()->asLinear() : NULL;
     611                 : }
     612                 : 
     613                 : inline jsval
     614         4735284 : JSObject::getNameURIVal() const
     615                 : {
     616         4735284 :     JS_ASSERT(isNamespace() || isQName());
     617         4735284 :     return getSlot(JSSLOT_NAME_URI);
     618                 : }
     619                 : 
     620                 : inline void
     621         4735810 : JSObject::setNameURI(JSLinearString *uri)
     622                 : {
     623         4735810 :     JS_ASSERT(isNamespace() || isQName());
     624         4735810 :     setSlot(JSSLOT_NAME_URI, uri ? js::StringValue(uri) : js::UndefinedValue());
     625         4735810 : }
     626                 : 
     627                 : inline jsval
     628         4720258 : JSObject::getNamespaceDeclared() const
     629                 : {
     630         4720258 :     JS_ASSERT(isNamespace());
     631         4720258 :     return getSlot(JSSLOT_NAMESPACE_DECLARED);
     632                 : }
     633                 : 
     634                 : inline void
     635            2009 : JSObject::setNamespaceDeclared(jsval decl)
     636                 : {
     637            2009 :     JS_ASSERT(isNamespace());
     638            2009 :     setSlot(JSSLOT_NAMESPACE_DECLARED, decl);
     639            2009 : }
     640                 : 
     641                 : inline JSAtom *
     642         2362923 : JSObject::getQNameLocalName() const
     643                 : {
     644         2362923 :     JS_ASSERT(isQName());
     645         2362923 :     const js::Value &v = getSlot(JSSLOT_QNAME_LOCAL_NAME);
     646         2362923 :     return !v.isUndefined() ? &v.toString()->asAtom() : NULL;
     647                 : }
     648                 : 
     649                 : inline jsval
     650         2374457 : JSObject::getQNameLocalNameVal() const
     651                 : {
     652         2374457 :     JS_ASSERT(isQName());
     653         2374457 :     return getSlot(JSSLOT_QNAME_LOCAL_NAME);
     654                 : }
     655                 : 
     656                 : inline void
     657         2374457 : JSObject::setQNameLocalName(JSAtom *name)
     658                 : {
     659         2374457 :     JS_ASSERT(isQName());
     660         2374457 :     setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
     661         2374457 : }
     662                 : 
     663                 : inline bool
     664         7343372 : JSObject::setSingletonType(JSContext *cx)
     665                 : {
     666         7343372 :     if (!cx->typeInferenceEnabled())
     667         3262284 :         return true;
     668                 : 
     669         4081088 :     JS_ASSERT(!hasLazyType());
     670         4081088 :     JS_ASSERT_IF(getProto(), type() == getProto()->getNewType(cx, NULL));
     671                 : 
     672         4081088 :     js::types::TypeObject *type = cx->compartment->getLazyType(cx, getProto());
     673         4081088 :     if (!type)
     674               0 :         return false;
     675                 : 
     676         4081088 :     type_ = type;
     677         4081088 :     return true;
     678                 : }
     679                 : 
     680                 : inline js::types::TypeObject *
     681         1234446 : JSObject::getType(JSContext *cx)
     682                 : {
     683         1234446 :     if (hasLazyType())
     684           51868 :         makeLazyType(cx);
     685         1234446 :     return type_;
     686                 : }
     687                 : 
     688                 : inline bool
     689            3003 : JSObject::clearType(JSContext *cx)
     690                 : {
     691            3003 :     JS_ASSERT(!hasSingletonType());
     692                 : 
     693            3003 :     js::types::TypeObject *type = cx->compartment->getEmptyType(cx);
     694            3003 :     if (!type)
     695               0 :         return false;
     696                 : 
     697            3003 :     type_ = type;
     698            3003 :     return true;
     699                 : }
     700                 : 
     701                 : inline void
     702         4806628 : JSObject::setType(js::types::TypeObject *newType)
     703                 : {
     704                 : #ifdef DEBUG
     705         4806628 :     JS_ASSERT(newType);
     706        12351999 :     for (JSObject *obj = newType->proto; obj; obj = obj->getProto())
     707         7545371 :         JS_ASSERT(obj != this);
     708                 : #endif
     709         4806628 :     JS_ASSERT_IF(hasSpecialEquality(),
     710         4806628 :                  newType->hasAnyFlags(js::types::OBJECT_FLAG_SPECIAL_EQUALITY));
     711         4806628 :     JS_ASSERT(!hasSingletonType());
     712         4806628 :     type_ = newType;
     713         4806628 : }
     714                 : 
     715           80355 : inline bool JSObject::setIteratedSingleton(JSContext *cx)
     716                 : {
     717           80355 :     return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
     718                 : }
     719                 : 
     720               0 : inline bool JSObject::isSystem() const
     721                 : {
     722               0 :     return lastProperty()->hasObjectFlag(js::BaseShape::SYSTEM);
     723                 : }
     724                 : 
     725               0 : inline bool JSObject::setSystem(JSContext *cx)
     726                 : {
     727               0 :     return setFlag(cx, js::BaseShape::SYSTEM);
     728                 : }
     729                 : 
     730         1022851 : inline bool JSObject::setDelegate(JSContext *cx)
     731                 : {
     732         1022851 :     return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
     733                 : }
     734                 : 
     735          201842 : inline bool JSObject::isVarObj() const
     736                 : {
     737          201842 :     return lastProperty()->hasObjectFlag(js::BaseShape::VAROBJ);
     738                 : }
     739                 : 
     740           81043 : inline bool JSObject::setVarObj(JSContext *cx)
     741                 : {
     742           81043 :     return setFlag(cx, js::BaseShape::VAROBJ);
     743                 : }
     744                 : 
     745            3672 : inline bool JSObject::setWatched(JSContext *cx)
     746                 : {
     747            3672 :     return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
     748                 : }
     749                 : 
     750          812081 : inline bool JSObject::hasUncacheableProto() const
     751                 : {
     752          812081 :     return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
     753                 : }
     754                 : 
     755           31940 : inline bool JSObject::setUncacheableProto(JSContext *cx)
     756                 : {
     757           31940 :     return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
     758                 : }
     759                 : 
     760         1786707 : inline bool JSObject::isBoundFunction() const
     761                 : {
     762         1786707 :     return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
     763                 : }
     764                 : 
     765         4009507 : inline bool JSObject::isIndexed() const
     766                 : {
     767         4009507 :     return lastProperty()->hasObjectFlag(js::BaseShape::INDEXED);
     768                 : }
     769                 : 
     770         4656027 : inline bool JSObject::watched() const
     771                 : {
     772         4656027 :     return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
     773                 : }
     774                 : 
     775         4919641 : inline bool JSObject::hasSpecialEquality() const
     776                 : {
     777         4919641 :     return !!getClass()->ext.equality;
     778                 : }
     779                 : 
     780        23117301 : inline bool JSObject::isArguments() const { return isNormalArguments() || isStrictArguments(); }
     781           20627 : inline bool JSObject::isArrayBuffer() const { return hasClass(&js::ArrayBufferClass); }
     782        31128734 : inline bool JSObject::isBlock() const { return hasClass(&js::BlockClass); }
     783            6955 : inline bool JSObject::isBoolean() const { return hasClass(&js::BooleanClass); }
     784        29586770 : inline bool JSObject::isCall() const { return hasClass(&js::CallClass); }
     785            8717 : inline bool JSObject::isClonedBlock() const { return isBlock() && !!getProto(); }
     786          760155 : inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
     787        10472065 : inline bool JSObject::isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
     788           25151 : inline bool JSObject::isElementIterator() const { return hasClass(&js::ElementIteratorClass); }
     789          113459 : inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
     790       207372408 : inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
     791                 : inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
     792            7510 : inline bool JSObject::isGenerator() const { return hasClass(&js::GeneratorClass); }
     793        31192408 : inline bool JSObject::isIterator() const { return hasClass(&js::IteratorClass); }
     794        33143440 : inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
     795        10156139 : inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
     796        23491953 : inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
     797          160596 : inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
     798         2077309 : inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
     799                 : inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
     800         3491324 : inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
     801                 : inline bool JSObject::isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
     802        15894602 : inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
     803         3175370 : inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
     804          197561 : inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
     805        21761582 : inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
     806         1259051 : inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
     807               0 : inline bool JSObject::isTypedArray() const { return IsFastTypedArrayClass(getClass()); }
     808            1463 : inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
     809        27346180 : inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
     810         6161199 : inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
     811                 : 
     812                 : inline bool
     813              72 : JSObject::isXMLId() const
     814                 : {
     815              72 :     return hasClass(&js::QNameClass)
     816              36 :         || hasClass(&js::AttributeNameClass)
     817             108 :         || hasClass(&js::AnyNameClass);
     818                 : }
     819                 : 
     820                 : inline bool
     821        23715503 : JSObject::isQName() const
     822                 : {
     823        23715503 :     return hasClass(&js::QNameClass)
     824            1179 :         || hasClass(&js::AttributeNameClass)
     825        23716682 :         || hasClass(&js::AnyNameClass);
     826                 : }
     827                 : 
     828                 : /* static */ inline JSObject *
     829         6560997 : JSObject::create(JSContext *cx, js::gc::AllocKind kind,
     830                 :                  js::HandleShape shape, js::HandleTypeObject type, js::HeapSlot *slots)
     831                 : {
     832                 :     /*
     833                 :      * Callers must use dynamicSlotsCount to size the initial slot array of the
     834                 :      * object. We can't check the allocated capacity of the dynamic slots, but
     835                 :      * make sure their presence is consistent with the shape.
     836                 :      */
     837         6560997 :     JS_ASSERT(shape && type);
     838         6560997 :     JS_ASSERT(!!dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()) == !!slots);
     839         6560997 :     JS_ASSERT(js::gc::GetGCKindSlots(kind, shape->getObjectClass()) == shape->numFixedSlots());
     840                 : 
     841         6560997 :     JSObject *obj = js_NewGCObject(cx, kind);
     842         6560997 :     if (!obj)
     843               0 :         return NULL;
     844                 : 
     845         6560997 :     obj->shape_.init(shape);
     846         6560997 :     obj->type_.init(type);
     847         6560997 :     obj->slots = slots;
     848         6560997 :     obj->elements = js::emptyObjectElements;
     849                 : 
     850         6560997 :     if (shape->getObjectClass()->hasPrivate())
     851         1572307 :         obj->privateRef(shape->numFixedSlots()) = NULL;
     852                 : 
     853         6560997 :     if (size_t span = shape->slotSpan())
     854         1620839 :         obj->initializeSlotRange(0, span);
     855                 : 
     856         6560997 :     return obj;
     857                 : }
     858                 : 
     859                 : /* static */ inline JSObject *
     860          220517 : JSObject::createDenseArray(JSContext *cx, js::gc::AllocKind kind,
     861                 :                            js::HandleShape shape, js::HandleTypeObject type,
     862                 :                            uint32_t length)
     863                 : {
     864          220517 :     JS_ASSERT(shape && type);
     865          220517 :     JS_ASSERT(shape->getObjectClass() == &js::ArrayClass);
     866                 : 
     867                 :     /*
     868                 :      * Dense arrays are non-native, and never have properties to store.
     869                 :      * The number of fixed slots in the shape of such objects is zero.
     870                 :      */
     871          220517 :     JS_ASSERT(shape->numFixedSlots() == 0);
     872                 : 
     873                 :     /*
     874                 :      * The array initially stores its elements inline, there must be enough
     875                 :      * space for an elements header.
     876                 :      */
     877          220517 :     JS_ASSERT(js::gc::GetGCKindSlots(kind) >= js::ObjectElements::VALUES_PER_HEADER);
     878                 : 
     879          220517 :     uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;
     880                 : 
     881          220517 :     JSObject *obj = js_NewGCObject(cx, kind);
     882          220517 :     if (!obj) {
     883               0 :         js_ReportOutOfMemory(cx);
     884               0 :         return NULL;
     885                 :     }
     886                 : 
     887          220517 :     obj->shape_.init(shape);
     888          220517 :     obj->type_.init(type);
     889          220517 :     obj->slots = NULL;
     890          220517 :     obj->setFixedElements();
     891          220517 :     new (obj->getElementsHeader()) js::ObjectElements(capacity, length);
     892                 : 
     893          220517 :     return obj;
     894                 : }
     895                 : 
     896                 : inline void
     897        30978300 : JSObject::finish(js::FreeOp *fop)
     898                 : {
     899        30978300 :     if (hasDynamicSlots())
     900         4039887 :         fop->free_(slots);
     901        30978300 :     if (hasDynamicElements())
     902          274298 :         fop->free_(getElementsHeader());
     903        30978300 : }
     904                 : 
     905                 : inline bool
     906         3099479 : JSObject::hasProperty(JSContext *cx, jsid id, bool *foundp, unsigned flags)
     907                 : {
     908                 :     JSObject *pobj;
     909                 :     JSProperty *prop;
     910         6198958 :     JSAutoResolveFlags rf(cx, flags);
     911         3099479 :     if (!lookupGeneric(cx, id, &pobj, &prop))
     912               0 :         return false;
     913         3099479 :     *foundp = !!prop;
     914         3099479 :     return true;
     915                 : }
     916                 : 
     917                 : inline bool
     918         2088610 : JSObject::isCallable()
     919                 : {
     920         2088610 :     return isFunction() || getClass()->call;
     921                 : }
     922                 : 
     923                 : inline JSPrincipals *
     924          106377 : JSObject::principals(JSContext *cx)
     925                 : {
     926          106377 :     if (JSObjectPrincipalsFinder find = cx->runtime->securityCallbacks->findObjectPrincipals)
     927              25 :         return find(this);
     928          106352 :     return cx->compartment ? cx->compartment->principals : NULL;
     929                 : }
     930                 : 
     931                 : inline void
     932        38356032 : JSObject::nativeSetSlot(unsigned slot, const js::Value &value)
     933                 : {
     934        38356032 :     JS_ASSERT(isNative());
     935        38356032 :     JS_ASSERT(slot < slotSpan());
     936        38356032 :     return setSlot(slot, value);
     937                 : }
     938                 : 
     939                 : inline void
     940        14750119 : JSObject::nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value)
     941                 : {
     942        14750119 :     nativeSetSlot(shape->slot(), value);
     943        14750119 :     js::types::AddTypePropertyId(cx, this, shape->propid(), value);
     944        14750119 : }
     945                 : 
     946                 : inline bool
     947          146111 : JSObject::nativeContains(JSContext *cx, jsid id)
     948                 : {
     949          146111 :     return nativeLookup(cx, id) != NULL;
     950                 : }
     951                 : 
     952                 : inline bool
     953        17331637 : JSObject::nativeContains(JSContext *cx, const js::Shape &shape)
     954                 : {
     955        17331637 :     return nativeLookup(cx, shape.propid()) == &shape;
     956                 : }
     957                 : 
     958                 : inline bool
     959         3012027 : JSObject::nativeEmpty() const
     960                 : {
     961         3012027 :     return lastProperty()->isEmptyShape();
     962                 : }
     963                 : 
     964                 : inline uint32_t
     965         1590457 : JSObject::propertyCount() const
     966                 : {
     967         1590457 :     return lastProperty()->entryCount();
     968                 : }
     969                 : 
     970                 : inline bool
     971               0 : JSObject::hasPropertyTable() const
     972                 : {
     973               0 :     return lastProperty()->hasTable();
     974                 : }
     975                 : 
     976                 : inline size_t
     977               0 : JSObject::computedSizeOfThisSlotsElements() const
     978                 : {
     979               0 :     size_t n = sizeOfThis();
     980                 : 
     981               0 :     if (hasDynamicSlots())
     982               0 :         n += numDynamicSlots() * sizeof(js::Value);
     983                 : 
     984               0 :     if (hasDynamicElements())
     985               0 :         n += (js::ObjectElements::VALUES_PER_HEADER + getElementsHeader()->capacity) *
     986               0 :              sizeof(js::Value);
     987                 : 
     988               0 :     return n;
     989                 : }
     990                 : 
     991                 : inline void
     992                 : JSObject::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
     993                 :                               size_t *slotsSize, size_t *elementsSize,
     994                 :                               size_t *miscSize) const
     995                 : {
     996                 :     *slotsSize = 0;
     997                 :     if (hasDynamicSlots()) {
     998                 :         *slotsSize += mallocSizeOf(slots);
     999                 :     }
    1000                 : 
    1001                 :     *elementsSize = 0;
    1002                 :     if (hasDynamicElements()) {
    1003                 :         *elementsSize += mallocSizeOf(getElementsHeader());
    1004                 :     }
    1005                 : 
    1006                 :     /* Other things may be measured in the future if DMD indicates it is worthwhile. */
    1007                 :     *miscSize = 0;
    1008                 :     if (isArguments()) {
    1009                 :         *miscSize += asArguments().sizeOfMisc(mallocSizeOf);
    1010                 :     } else if (isRegExpStatics()) {
    1011                 :         *miscSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf);
    1012                 :     }
    1013                 : }
    1014                 : 
    1015                 : inline JSBool
    1016         5645865 : JSObject::lookupGeneric(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp)
    1017                 : {
    1018         5645865 :     js::LookupGenericOp op = getOps()->lookupGeneric;
    1019         5645865 :     return (op ? op : js_LookupProperty)(cx, this, id, objp, propp);
    1020                 : }
    1021                 : 
    1022                 : inline JSBool
    1023          169734 : JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, JSProperty **propp)
    1024                 : {
    1025          169734 :     return lookupGeneric(cx, ATOM_TO_JSID(name), objp, propp);
    1026                 : }
    1027                 : 
    1028                 : inline JSBool
    1029        18826122 : JSObject::defineGeneric(JSContext *cx, jsid id, const js::Value &value,
    1030                 :                         JSPropertyOp getter /* = JS_PropertyStub */,
    1031                 :                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
    1032                 :                         unsigned attrs /* = JSPROP_ENUMERATE */)
    1033                 : {
    1034        18826122 :     JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
    1035        18826122 :     js::DefineGenericOp op = getOps()->defineGeneric;
    1036        18826122 :     return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs);
    1037                 : }
    1038                 : 
    1039                 : inline JSBool
    1040         1267885 : JSObject::defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
    1041                 :                         JSPropertyOp getter /* = JS_PropertyStub */,
    1042                 :                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
    1043                 :                         unsigned attrs /* = JSPROP_ENUMERATE */)
    1044                 : {
    1045         1267885 :     return defineGeneric(cx, ATOM_TO_JSID(name), value, getter, setter, attrs);
    1046                 : }
    1047                 : 
    1048                 : inline JSBool
    1049            8359 : JSObject::defineElement(JSContext *cx, uint32_t index, const js::Value &value,
    1050                 :                         JSPropertyOp getter /* = JS_PropertyStub */,
    1051                 :                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
    1052                 :                         unsigned attrs /* = JSPROP_ENUMERATE */)
    1053                 : {
    1054            8359 :     js::DefineElementOp op = getOps()->defineElement;
    1055            8359 :     return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs);
    1056                 : }
    1057                 : 
    1058                 : inline JSBool
    1059             325 : JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
    1060                 :                         JSPropertyOp getter /* = JS_PropertyStub */,
    1061                 :                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
    1062                 :                         unsigned attrs /* = JSPROP_ENUMERATE */)
    1063                 : {
    1064             325 :     return defineGeneric(cx, SPECIALID_TO_JSID(sid), value, getter, setter, attrs);
    1065                 : }
    1066                 : 
    1067                 : inline JSBool
    1068               0 : JSObject::lookupElement(JSContext *cx, uint32_t index, JSObject **objp, JSProperty **propp)
    1069                 : {
    1070               0 :     js::LookupElementOp op = getOps()->lookupElement;
    1071               0 :     return (op ? op : js_LookupElement)(cx, this, index, objp, propp);
    1072                 : }
    1073                 : 
    1074                 : inline JSBool
    1075                 : JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, JSObject **objp, JSProperty **propp)
    1076                 : {
    1077                 :     return lookupGeneric(cx, SPECIALID_TO_JSID(sid), objp, propp);
    1078                 : }
    1079                 : 
    1080                 : inline JSBool
    1081         1637345 : JSObject::getElement(JSContext *cx, JSObject *receiver, uint32_t index, js::Value *vp)
    1082                 : {
    1083         1637345 :     js::ElementIdOp op = getOps()->getElement;
    1084         1637345 :     if (op)
    1085          700755 :         return op(cx, this, receiver, index, vp);
    1086                 : 
    1087                 :     jsid id;
    1088          936590 :     if (!js::IndexToId(cx, index, &id))
    1089               0 :         return false;
    1090          936590 :     return getGeneric(cx, receiver, id, vp);
    1091                 : }
    1092                 : 
    1093                 : inline JSBool
    1094         1134831 : JSObject::getElement(JSContext *cx, uint32_t index, js::Value *vp)
    1095                 : {
    1096         1134831 :     return getElement(cx, this, index, vp);
    1097                 : }
    1098                 : 
    1099                 : inline JSBool
    1100          505294 : JSObject::getElementIfPresent(JSContext *cx, JSObject *receiver, uint32_t index, js::Value *vp,
    1101                 :                               bool *present)
    1102                 : {
    1103          505294 :     js::ElementIfPresentOp op = getOps()->getElementIfPresent;
    1104          505294 :     if (op)
    1105             513 :         return op(cx, this, receiver, index, vp, present);
    1106                 : 
    1107                 :     /* For now, do the index-to-id conversion just once, then use
    1108                 :      * lookupGeneric/getGeneric.  Once lookupElement and getElement stop both
    1109                 :      * doing index-to-id conversions, we can use those here.
    1110                 :      */
    1111                 :     jsid id;
    1112          504781 :     if (!js::IndexToId(cx, index, &id))
    1113               0 :         return false;
    1114                 : 
    1115                 :     JSObject *obj2;
    1116                 :     JSProperty *prop;
    1117          504781 :     if (!lookupGeneric(cx, id, &obj2, &prop))
    1118               0 :         return false;
    1119                 : 
    1120          504781 :     if (!prop) {
    1121          503134 :         *present = false;
    1122          503134 :         js::Debug_SetValueRangeToCrashOnTouch(vp, 1);
    1123          503134 :         return true;
    1124                 :     }
    1125                 : 
    1126            1647 :     *present = true;
    1127            1647 :     return getGeneric(cx, receiver, id, vp);
    1128                 : }
    1129                 : 
    1130                 : inline JSBool
    1131           13267 : JSObject::getSpecial(JSContext *cx, JSObject *receiver, js::SpecialId sid, js::Value *vp)
    1132                 : {
    1133           13267 :     return getGeneric(cx, receiver, SPECIALID_TO_JSID(sid), vp);
    1134                 : }
    1135                 : 
    1136                 : inline JSBool
    1137           83259 : JSObject::getGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp)
    1138                 : {
    1139           83259 :     js::GenericAttributesOp op = getOps()->getGenericAttributes;
    1140           83259 :     return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
    1141                 : }
    1142                 : 
    1143                 : inline JSBool
    1144            1127 : JSObject::getPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp)
    1145                 : {
    1146            1127 :     return getGenericAttributes(cx, ATOM_TO_JSID(name), attrsp);
    1147                 : }
    1148                 : 
    1149                 : inline JSBool
    1150               0 : JSObject::getElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp)
    1151                 : {
    1152                 :     jsid id;
    1153               0 :     if (!js::IndexToId(cx, index, &id))
    1154               0 :         return false;
    1155               0 :     return getGenericAttributes(cx, id, attrsp);
    1156                 : }
    1157                 : 
    1158                 : inline JSBool
    1159               0 : JSObject::getSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
    1160                 : {
    1161               0 :     return getGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
    1162                 : }
    1163                 : 
    1164                 : inline bool
    1165        49848464 : JSObject::isProxy() const
    1166                 : {
    1167        49848464 :     return js::IsProxy(this);
    1168                 : }
    1169                 : 
    1170                 : inline bool
    1171           66044 : JSObject::isCrossCompartmentWrapper() const
    1172                 : {
    1173           66044 :     return js::IsCrossCompartmentWrapper(this);
    1174                 : }
    1175                 : 
    1176                 : inline bool
    1177        59282117 : JSObject::isWrapper() const
    1178                 : {
    1179        59282117 :     return js::IsWrapper(this);
    1180                 : }
    1181                 : 
    1182                 : inline js::GlobalObject &
    1183       998848527 : JSObject::global() const
    1184                 : {
    1185       998848527 :     JSObject *obj = const_cast<JSObject *>(this);
    1186      1059866463 :     while (JSObject *parent = obj->getParent())
    1187        30508968 :         obj = parent;
    1188       998848527 :     return obj->asGlobal();
    1189                 : }
    1190                 : 
    1191                 : static inline bool
    1192         2372375 : js_IsCallable(const js::Value &v)
    1193                 : {
    1194         2372375 :     return v.isObject() && v.toObject().isCallable();
    1195                 : }
    1196                 : 
    1197                 : namespace js {
    1198                 : 
    1199                 : inline void
    1200          512198 : OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
    1201                 : {
    1202          512198 :     if (JSObjectOp op = obj->getClass()->ext.innerObject)
    1203               0 :         obj = op(cx, obj);
    1204          512198 : }
    1205                 : 
    1206                 : inline void
    1207           97865 : OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
    1208                 : {
    1209           97865 :     if (JSObjectOp op = obj->getClass()->ext.outerObject)
    1210               0 :         obj = op(cx, obj);
    1211           97865 : }
    1212                 : 
    1213                 : /*
    1214                 :  * Methods to test whether an object or a value is of type "xml" (per typeof).
    1215                 :  */
    1216                 : 
    1217                 : #define VALUE_IS_XML(v)      (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isXML())
    1218                 : 
    1219                 : static inline bool
    1220         9602804 : IsXML(const js::Value &v)
    1221                 : {
    1222         9602804 :     return v.isObject() && v.toObject().isXML();
    1223                 : }
    1224                 : 
    1225                 : static inline bool
    1226            3362 : IsStopIteration(const js::Value &v)
    1227                 : {
    1228            3362 :     return v.isObject() && v.toObject().isStopIteration();
    1229                 : }
    1230                 : 
    1231                 : /* ES5 9.1 ToPrimitive(input). */
    1232                 : static JS_ALWAYS_INLINE bool
    1233        25267777 : ToPrimitive(JSContext *cx, Value *vp)
    1234                 : {
    1235        25267777 :     if (vp->isPrimitive())
    1236        24735260 :         return true;
    1237          532517 :     return vp->toObject().defaultValue(cx, JSTYPE_VOID, vp);
    1238                 : }
    1239                 : 
    1240                 : /* ES5 9.1 ToPrimitive(input, PreferredType). */
    1241                 : static JS_ALWAYS_INLINE bool
    1242        10576798 : ToPrimitive(JSContext *cx, JSType preferredType, Value *vp)
    1243                 : {
    1244        10576798 :     JS_ASSERT(preferredType != JSTYPE_VOID); /* Use the other ToPrimitive! */
    1245        10576798 :     if (vp->isPrimitive())
    1246        10216680 :         return true;
    1247          360118 :     return vp->toObject().defaultValue(cx, preferredType, vp);
    1248                 : }
    1249                 : 
    1250                 : /*
    1251                 :  * Return true if this is a compiler-created internal function accessed by
    1252                 :  * its own object. Such a function object must not be accessible to script
    1253                 :  * or embedding code.
    1254                 :  */
    1255                 : inline bool
    1256          951597 : IsInternalFunctionObject(JSObject *funobj)
    1257                 : {
    1258          951597 :     JSFunction *fun = funobj->toFunction();
    1259          951597 :     return (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
    1260                 : }
    1261                 : 
    1262                 : class AutoPropDescArrayRooter : private AutoGCRooter
    1263          301484 : {
    1264                 :   public:
    1265          301484 :     AutoPropDescArrayRooter(JSContext *cx)
    1266          301484 :       : AutoGCRooter(cx, DESCRIPTORS), descriptors(cx)
    1267          301484 :     { }
    1268                 : 
    1269          301529 :     PropDesc *append() {
    1270          301529 :         if (!descriptors.append(PropDesc()))
    1271               0 :             return NULL;
    1272          301529 :         return &descriptors.back();
    1273                 :     }
    1274                 : 
    1275             549 :     PropDesc& operator[](size_t i) {
    1276             549 :         JS_ASSERT(i < descriptors.length());
    1277             549 :         return descriptors[i];
    1278                 :     }
    1279                 : 
    1280                 :     friend void AutoGCRooter::trace(JSTracer *trc);
    1281                 : 
    1282                 :   private:
    1283                 :     PropDescArray descriptors;
    1284                 : };
    1285                 : 
    1286                 : class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescriptor
    1287           14960 : {
    1288                 :   public:
    1289           14933 :     AutoPropertyDescriptorRooter(JSContext *cx) : AutoGCRooter(cx, DESCRIPTOR) {
    1290           14933 :         obj = NULL;
    1291           14933 :         attrs = 0;
    1292           14933 :         getter = (PropertyOp) NULL;
    1293           14933 :         setter = (StrictPropertyOp) NULL;
    1294           14933 :         value.setUndefined();
    1295           14933 :     }
    1296                 : 
    1297              27 :     AutoPropertyDescriptorRooter(JSContext *cx, PropertyDescriptor *desc)
    1298              27 :       : AutoGCRooter(cx, DESCRIPTOR)
    1299                 :     {
    1300              27 :         obj = desc->obj;
    1301              27 :         attrs = desc->attrs;
    1302              27 :         getter = desc->getter;
    1303              27 :         setter = desc->setter;
    1304              27 :         value = desc->value;
    1305              27 :     }
    1306                 : 
    1307                 :     friend void AutoGCRooter::trace(JSTracer *trc);
    1308                 : };
    1309                 : 
    1310                 : inline bool
    1311        19896288 : NewObjectCache::lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry)
    1312                 : {
    1313        19896288 :     uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + kind;
    1314        19896288 :     *pentry = hash % js::ArrayLength(entries);
    1315                 : 
    1316        19896288 :     Entry *entry = &entries[*pentry];
    1317                 : 
    1318                 :     /* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
    1319        19896288 :     return (entry->clasp == clasp && entry->key == key);
    1320                 : }
    1321                 : 
    1322                 : inline bool
    1323         2090502 : NewObjectCache::lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
    1324                 : {
    1325         2090502 :     JS_ASSERT(!proto->isGlobal());
    1326         2090502 :     return lookup(clasp, proto, kind, pentry);
    1327                 : }
    1328                 : 
    1329                 : inline bool
    1330        15279767 : NewObjectCache::lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
    1331                 : {
    1332        15279767 :     return lookup(clasp, global, kind, pentry);
    1333                 : }
    1334                 : 
    1335                 : inline bool
    1336         2526019 : NewObjectCache::lookupType(Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, EntryIndex *pentry)
    1337                 : {
    1338         2526019 :     return lookup(clasp, type, kind, pentry);
    1339                 : }
    1340                 : 
    1341                 : inline void
    1342          825038 : NewObjectCache::fill(EntryIndex entry_, Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj)
    1343                 : {
    1344          825038 :     JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
    1345          825038 :     Entry *entry = &entries[entry_];
    1346                 : 
    1347          825038 :     JS_ASSERT(!obj->hasDynamicSlots() && !obj->hasDynamicElements());
    1348                 : 
    1349          825038 :     entry->clasp = clasp;
    1350          825038 :     entry->key = key;
    1351          825038 :     entry->kind = kind;
    1352                 : 
    1353          825038 :     entry->nbytes = obj->sizeOfThis();
    1354          825038 :     js_memcpy(&entry->templateObject, obj, entry->nbytes);
    1355          825038 : }
    1356                 : 
    1357                 : inline void
    1358          281973 : NewObjectCache::fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj)
    1359                 : {
    1360          281973 :     JS_ASSERT(!proto->isGlobal());
    1361          281973 :     JS_ASSERT(obj->getProto() == proto);
    1362          281973 :     return fill(entry, clasp, proto, kind, obj);
    1363                 : }
    1364                 : 
    1365                 : inline void
    1366          539777 : NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
    1367                 : {
    1368                 :     //JS_ASSERT(global == obj->getGlobal());
    1369          539777 :     return fill(entry, clasp, global, kind, obj);
    1370                 : }
    1371                 : 
    1372                 : inline void
    1373            3288 : NewObjectCache::fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj)
    1374                 : {
    1375            3288 :     JS_ASSERT(obj->type() == type);
    1376            3288 :     return fill(entry, clasp, type, kind, obj);
    1377                 : }
    1378                 : 
    1379                 : inline void
    1380        19052049 : NewObjectCache::copyCachedToObject(JSObject *dst, JSObject *src)
    1381                 : {
    1382        19052049 :     js_memcpy(dst, src, dst->sizeOfThis());
    1383                 : #ifdef JSGC_GENERATIONAL
    1384                 :     Shape::writeBarrierPost(dst->shape_, &dst->shape_);
    1385                 :     types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
    1386                 : #endif
    1387        19052049 : }
    1388                 : 
    1389                 : inline JSObject *
    1390        19052050 : NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
    1391                 : {
    1392        19052050 :     JS_ASSERT(unsigned(entry_) < ArrayLength(entries));
    1393        19052050 :     Entry *entry = &entries[entry_];
    1394                 : 
    1395        19052050 :     JSObject *obj = js_TryNewGCObject(cx, entry->kind);
    1396        19052050 :     if (obj) {
    1397        18808869 :         copyCachedToObject(obj, &entry->templateObject);
    1398        18808869 :         Probes::createObject(cx, obj);
    1399        18808869 :         return obj;
    1400                 :     }
    1401                 : 
    1402                 :     /* Copy the entry to the stack first in case it is purged by a GC. */
    1403          243181 :     size_t nbytes = entry->nbytes;
    1404                 :     char stackObject[sizeof(JSObject_Slots16)];
    1405          243181 :     JS_ASSERT(nbytes <= sizeof(stackObject));
    1406          243181 :     js_memcpy(&stackObject, &entry->templateObject, nbytes);
    1407                 : 
    1408          243181 :     JSObject *baseobj = (JSObject *) stackObject;
    1409          486362 :     RootShape shapeRoot(cx, (Shape **) baseobj->addressOfShape());
    1410          486362 :     RootTypeObject typeRoot(cx, (types::TypeObject **) baseobj->addressOfType());
    1411                 : 
    1412          243181 :     obj = js_NewGCObject(cx, entry->kind);
    1413          243181 :     if (obj) {
    1414          243180 :         copyCachedToObject(obj, baseobj);
    1415          243180 :         Probes::createObject(cx, obj);
    1416          243180 :         return obj;
    1417                 :     }
    1418                 : 
    1419               1 :     return NULL;
    1420                 : }
    1421                 : 
    1422                 : static inline bool
    1423        24221252 : CanBeFinalizedInBackground(gc::AllocKind kind, Class *clasp)
    1424                 : {
    1425                 : #ifdef JS_THREADSAFE
    1426        24221252 :     JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST);
    1427                 :     /* If the class has no finalizer or a finalizer that is safe to call on
    1428                 :      * a different thread, we change the finalize kind. For example,
    1429                 :      * FINALIZE_OBJECT0 calls the finalizer on the main thread,
    1430                 :      * FINALIZE_OBJECT0_BACKGROUND calls the finalizer on the gcHelperThread.
    1431                 :      * IsBackgroundAllocKind is called to prevent recursively incrementing
    1432                 :      * the finalize kind; kind may already be a background finalize kind.
    1433                 :      */
    1434        24221252 :     if (!gc::IsBackgroundAllocKind(kind) && !clasp->finalize)
    1435        12487056 :         return true;
    1436                 : #endif
    1437        11734196 :     return false;
    1438                 : }
    1439                 : 
    1440                 : /*
    1441                 :  * Make an object with the specified prototype. If parent is null, it will
    1442                 :  * default to the prototype's global if the prototype is non-null.
    1443                 :  */
    1444                 : JSObject *
    1445                 : NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
    1446                 :                         gc::AllocKind kind);
    1447                 : 
    1448                 : inline JSObject *
    1449          508924 : NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
    1450                 : {
    1451          508924 :     gc::AllocKind kind = gc::GetGCObjectKind(clasp);
    1452          508924 :     return NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
    1453                 : }
    1454                 : 
    1455                 : inline JSProtoKey
    1456        21839267 : GetClassProtoKey(js::Class *clasp)
    1457                 : {
    1458        21839267 :     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
    1459        21839267 :     if (key != JSProto_Null)
    1460        21306285 :         return key;
    1461          532982 :     if (clasp->flags & JSCLASS_IS_ANONYMOUS)
    1462             846 :         return JSProto_Object;
    1463          532136 :     return JSProto_Null;
    1464                 : }
    1465                 : 
    1466                 : inline bool
    1467         4679669 : FindProto(JSContext *cx, js::Class *clasp, HandleObject parent, JSObject **proto)
    1468                 : {
    1469         4679669 :     JSProtoKey protoKey = GetClassProtoKey(clasp);
    1470         4679669 :     if (!js_GetClassPrototype(cx, parent, protoKey, proto, clasp))
    1471               0 :         return false;
    1472         4679669 :     if (!(*proto) && !js_GetClassPrototype(cx, parent, JSProto_Object, proto))
    1473               0 :         return false;
    1474         4679669 :     return true;
    1475                 : }
    1476                 : 
    1477                 : /*
    1478                 :  * Make an object with the prototype set according to the specified prototype or class:
    1479                 :  *
    1480                 :  * if proto is non-null:
    1481                 :  *   use the specified proto
    1482                 :  * for a built-in class:
    1483                 :  *   use the memoized original value of the class constructor .prototype
    1484                 :  *   property object
    1485                 :  * else if available
    1486                 :  *   the current value of .prototype
    1487                 :  * else
    1488                 :  *   Object.prototype.
    1489                 :  *
    1490                 :  * The class prototype will be fetched from the parent's global. If global is
    1491                 :  * null, the context's active global will be used, and the resulting object's
    1492                 :  * parent will be that global.
    1493                 :  */
    1494                 : JSObject *
    1495                 : NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
    1496                 :                         gc::AllocKind kind);
    1497                 : 
    1498                 : inline JSObject *
    1499         2075669 : NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent)
    1500                 : {
    1501         2075669 :     gc::AllocKind kind = gc::GetGCObjectKind(clasp);
    1502         2075669 :     return NewObjectWithClassProto(cx, clasp, proto, parent, kind);
    1503                 : }
    1504                 : 
    1505                 : /*
    1506                 :  * Create a native instance of the given class with parent and proto set
    1507                 :  * according to the context's active global.
    1508                 :  */
    1509                 : inline JSObject *
    1510         8868435 : NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind kind)
    1511                 : {
    1512         8868435 :     return NewObjectWithClassProto(cx, clasp, NULL, NULL, kind);
    1513                 : }
    1514                 : 
    1515                 : inline JSObject *
    1516         6234114 : NewBuiltinClassInstance(JSContext *cx, Class *clasp)
    1517                 : {
    1518         6234114 :     gc::AllocKind kind = gc::GetGCObjectKind(clasp);
    1519         6234114 :     return NewBuiltinClassInstance(cx, clasp, kind);
    1520                 : }
    1521                 : 
    1522                 : inline GlobalObject *
    1523        11315326 : GetCurrentGlobal(JSContext *cx)
    1524                 : {
    1525        11315326 :     JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
    1526        11315326 :     return scopeChain ? &scopeChain->global() : NULL;
    1527                 : }
    1528                 : 
    1529                 : bool
    1530                 : FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop,
    1531                 :                    Class *clasp);
    1532                 : 
    1533                 : /*
    1534                 :  * Create a plain object with the specified type. This bypasses getNewType to
    1535                 :  * avoid losing creation site information for objects made by scripted 'new'.
    1536                 :  */
    1537                 : JSObject *
    1538                 : NewObjectWithType(JSContext *cx, types::TypeObject *type, JSObject *parent, gc::AllocKind kind);
    1539                 : 
    1540                 : /* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
    1541                 : static inline JSObject *
    1542         2614024 : CopyInitializerObject(JSContext *cx, JSObject *baseobj)
    1543                 : {
    1544         2614024 :     JS_ASSERT(baseobj->getClass() == &ObjectClass);
    1545         2614024 :     JS_ASSERT(!baseobj->inDictionaryMode());
    1546                 : 
    1547         2614024 :     gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
    1548                 : #ifdef JS_THREADSAFE
    1549         2614024 :     kind = gc::GetBackgroundAllocKind(kind);
    1550                 : #endif
    1551         2614024 :     JS_ASSERT(kind == baseobj->getAllocKind());
    1552         2614024 :     JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
    1553                 : 
    1554         2614024 :     if (!obj)
    1555               1 :         return NULL;
    1556                 : 
    1557         2614023 :     if (!obj->setLastProperty(cx, baseobj->lastProperty()))
    1558               0 :         return NULL;
    1559                 : 
    1560         2614023 :     return obj;
    1561                 : }
    1562                 : 
    1563                 : JSObject *
    1564                 : NewReshapedObject(JSContext *cx, js::types::TypeObject *type, JSObject *parent,
    1565                 :                   gc::AllocKind kind, const Shape *shape);
    1566                 : 
    1567                 : /*
    1568                 :  * As for gc::GetGCObjectKind, where numSlots is a guess at the final size of
    1569                 :  * the object, zero if the final size is unknown. This should only be used for
    1570                 :  * objects that do not require any fixed slots.
    1571                 :  */
    1572                 : static inline gc::AllocKind
    1573           15211 : GuessObjectGCKind(size_t numSlots)
    1574                 : {
    1575           15211 :     if (numSlots)
    1576            8443 :         return gc::GetGCObjectKind(numSlots);
    1577            6768 :     return gc::FINALIZE_OBJECT4;
    1578                 : }
    1579                 : 
    1580                 : static inline gc::AllocKind
    1581         2266237 : GuessArrayGCKind(size_t numSlots)
    1582                 : {
    1583         2266237 :     if (numSlots)
    1584         2124663 :         return gc::GetGCArrayKind(numSlots);
    1585          141574 :     return gc::FINALIZE_OBJECT8;
    1586                 : }
    1587                 : 
    1588                 : /*
    1589                 :  * Get the GC kind to use for scripted 'new' on the given class.
    1590                 :  * FIXME bug 547327: estimate the size from the allocation site.
    1591                 :  */
    1592                 : static inline gc::AllocKind
    1593         2172923 : NewObjectGCKind(JSContext *cx, js::Class *clasp)
    1594                 : {
    1595         2172923 :     if (clasp == &ArrayClass || clasp == &SlowArrayClass)
    1596               0 :         return gc::FINALIZE_OBJECT8;
    1597         2172923 :     if (clasp == &FunctionClass)
    1598               0 :         return gc::FINALIZE_OBJECT2;
    1599         2172923 :     return gc::FINALIZE_OBJECT4;
    1600                 : }
    1601                 : 
    1602                 : /*
    1603                 :  * Fill slots with the initial slot array to use for a newborn object which
    1604                 :  * may or may not need dynamic slots.
    1605                 :  */
    1606                 : inline bool
    1607         5689289 : PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapSlot **slots)
    1608                 : {
    1609         5689289 :     if (size_t count = JSObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan())) {
    1610           32975 :         *slots = (HeapSlot *) cx->malloc_(count * sizeof(HeapSlot));
    1611           32975 :         if (!*slots)
    1612               0 :             return false;
    1613           32975 :         Debug_SetSlotRangeToCrashOnTouch(*slots, count);
    1614           32975 :         return true;
    1615                 :     }
    1616         5656314 :     *slots = NULL;
    1617         5656314 :     return true;
    1618                 : }
    1619                 : 
    1620                 : inline bool
    1621           70814 : DefineConstructorAndPrototype(JSContext *cx, GlobalObject *global,
    1622                 :                               JSProtoKey key, JSObject *ctor, JSObject *proto)
    1623                 : {
    1624           70814 :     JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
    1625           70814 :     JS_ASSERT(ctor);
    1626           70814 :     JS_ASSERT(proto);
    1627                 : 
    1628           70814 :     jsid id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
    1629           70814 :     JS_ASSERT(!global->nativeLookup(cx, id));
    1630                 : 
    1631                 :     /* Set these first in case AddTypePropertyId looks for this class. */
    1632           70814 :     global->setSlot(key, ObjectValue(*ctor));
    1633           70814 :     global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
    1634           70814 :     global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
    1635                 : 
    1636           70814 :     types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
    1637           70814 :     if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
    1638               0 :         global->setSlot(key, UndefinedValue());
    1639               0 :         global->setSlot(key + JSProto_LIMIT, UndefinedValue());
    1640               0 :         global->setSlot(key + JSProto_LIMIT * 2, UndefinedValue());
    1641               0 :         return false;
    1642                 :     }
    1643                 : 
    1644           70814 :     return true;
    1645                 : }
    1646                 : 
    1647                 : bool
    1648          299098 : PropDesc::checkGetter(JSContext *cx)
    1649                 : {
    1650          299098 :     if (hasGet && !js_IsCallable(get) && !get.isUndefined()) {
    1651                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
    1652              18 :                              js_getter_str);
    1653              18 :         return false;
    1654                 :     }
    1655          299080 :     return true;
    1656                 : }
    1657                 : 
    1658                 : bool
    1659            4313 : PropDesc::checkSetter(JSContext *cx)
    1660                 : {
    1661            4313 :     if (hasSet && !js_IsCallable(set) && !set.isUndefined()) {
    1662                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
    1663               0 :                              js_setter_str);
    1664               0 :         return false;
    1665                 :     }
    1666            4313 :     return true;
    1667                 : }
    1668                 : 
    1669                 : inline bool
    1670          726168 : ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx)
    1671                 : {
    1672          726168 :     if (JS_UNLIKELY(obj.isProxy()))
    1673             594 :         return Proxy::objectClassIs(&obj, classValue, cx);
    1674                 : 
    1675          725574 :     switch (classValue) {
    1676            1081 :       case ESClass_Array: return obj.isArray();
    1677             378 :       case ESClass_Number: return obj.isNumber();
    1678             369 :       case ESClass_String: return obj.isString();
    1679             342 :       case ESClass_Boolean: return obj.isBoolean();
    1680          723404 :       case ESClass_RegExp: return obj.isRegExp();
    1681                 :     }
    1682               0 :     JS_NOT_REACHED("bad classValue");
    1683                 :     return false;
    1684                 : }
    1685                 : 
    1686                 : inline bool
    1687          918829 : IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
    1688                 : {
    1689          918829 :     if (!v.isObject())
    1690          556722 :         return false;
    1691          362107 :     return ObjectClassIs(v.toObject(), classValue, cx);
    1692                 : }
    1693                 : 
    1694                 : static JS_ALWAYS_INLINE bool
    1695         3207311 : ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
    1696                 : {
    1697         3207311 :     if (!propval->isObject())
    1698         3207074 :         return false;
    1699                 : 
    1700                 : #if JS_HAS_XML_SUPPORT
    1701             237 :     if (obj->isXML()) {
    1702               0 :         *sidp = SpecialId(propval->toObject());
    1703               0 :         return true;
    1704                 :     }
    1705                 : 
    1706             237 :     JSObject &propobj = propval->toObject();
    1707                 :     JSAtom *name;
    1708             237 :     if (propobj.isQName() && GetLocalNameFromFunctionQName(&propobj, &name, cx)) {
    1709               0 :         propval->setString(name);
    1710               0 :         return false;
    1711                 :     }
    1712                 : #endif
    1713                 : 
    1714             237 :     return false;
    1715                 : }
    1716                 : 
    1717                 : JSObject *
    1718                 : DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
    1719                 :                               JSObject *protoProto, Class *clasp,
    1720                 :                               Native constructor, unsigned nargs,
    1721                 :                               JSPropertySpec *ps, JSFunctionSpec *fs,
    1722                 :                               JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
    1723                 :                               JSObject **ctorp = NULL,
    1724                 :                               gc::AllocKind ctorKind = JSFunction::FinalizeKind);
    1725                 : 
    1726                 : } /* namespace js */
    1727                 : 
    1728                 : extern JSObject *
    1729                 : js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
    1730                 :              js::Class *clasp, JSNative constructor, unsigned nargs,
    1731                 :              JSPropertySpec *ps, JSFunctionSpec *fs,
    1732                 :              JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
    1733                 :              JSObject **ctorp = NULL,
    1734                 :              js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);
    1735                 : 
    1736                 : inline JSObject *
    1737        20620590 : js_GetProtoIfDenseArray(JSObject *obj)
    1738                 : {
    1739        20620590 :     return obj->isDenseArray() ? obj->getProto() : obj;
    1740                 : }
    1741                 : 
    1742                 : /*
    1743                 :  * js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
    1744                 :  * scope, else it reshapes the scope and prototype chains it links. It calls
    1745                 :  * js_PurgeScopeChainHelper, which asserts that obj is flagged as a delegate
    1746                 :  * (i.e., obj has ever been on a prototype or parent chain).
    1747                 :  */
    1748                 : extern bool
    1749                 : js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id);
    1750                 : 
    1751                 : inline bool
    1752        31574075 : js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
    1753                 : {
    1754        31574075 :     if (obj->isDelegate())
    1755          626973 :         return js_PurgeScopeChainHelper(cx, obj, id);
    1756        30947102 :     return true;
    1757                 : }
    1758                 : 
    1759                 : inline void
    1760           25246 : js::DestroyIdArray(FreeOp *fop, JSIdArray *ida)
    1761                 : {
    1762           25246 :     fop->free_(ida);
    1763           25246 : }
    1764                 : 
    1765                 : #endif /* jsobjinlines_h___ */

Generated by: LCOV version 1.7