LCOV - code coverage report
Current view: top level - js/src - jsobjinlines.h (source / functions) Hit Total Coverage
Test: output.info Lines: 274 338 81.1 %
Date: 2017-07-14 16:53:18 Functions: 101 141 71.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jsobjinlines_h
       8             : #define jsobjinlines_h
       9             : 
      10             : #include "jsobj.h"
      11             : 
      12             : #include "mozilla/DebugOnly.h"
      13             : 
      14             : #include "jsfriendapi.h"
      15             : #include "jsfun.h"
      16             : 
      17             : #include "builtin/MapObject.h"
      18             : #include "builtin/TypedObject.h"
      19             : #include "gc/Allocator.h"
      20             : #include "vm/ArrayObject.h"
      21             : #include "vm/DateObject.h"
      22             : #include "vm/EnvironmentObject.h"
      23             : #include "vm/NumberObject.h"
      24             : #include "vm/Probes.h"
      25             : #include "vm/StringObject.h"
      26             : #include "vm/TypedArrayObject.h"
      27             : 
      28             : #include "jsatominlines.h"
      29             : #include "jscompartmentinlines.h"
      30             : #include "jsgcinlines.h"
      31             : 
      32             : #include "vm/ShapedObject-inl.h"
      33             : #include "vm/TypeInference-inl.h"
      34             : 
      35             : namespace js {
      36             : 
      37             : // This is needed here for ensureShape() below.
      38             : inline bool
      39       13435 : MaybeConvertUnboxedObjectToNative(JSContext* cx, JSObject* obj)
      40             : {
      41       13435 :     if (obj->is<UnboxedPlainObject>())
      42           0 :         return UnboxedPlainObject::convertToNative(cx, obj);
      43       13435 :     if (obj->is<UnboxedArrayObject>())
      44           0 :         return UnboxedArrayObject::convertToNative(cx, obj);
      45       13435 :     return true;
      46             : }
      47             : 
      48             : static MOZ_ALWAYS_INLINE bool
      49       13561 : ClassMayResolveId(const JSAtomState& names, const Class* clasp, jsid id, JSObject* maybeObj)
      50             : {
      51       13561 :     MOZ_ASSERT_IF(maybeObj, maybeObj->getClass() == clasp);
      52             : 
      53       13561 :     if (!clasp->getResolve()) {
      54             :         // Sanity check: we should only have a mayResolve hook if we have a
      55             :         // resolve hook.
      56       12124 :         MOZ_ASSERT(!clasp->getMayResolve(), "Class with mayResolve hook but no resolve hook");
      57       12124 :         return false;
      58             :     }
      59             : 
      60        1437 :     if (JSMayResolveOp mayResolve = clasp->getMayResolve()) {
      61             :         // Tell the analysis our mayResolve hooks won't trigger GC.
      62         300 :         JS::AutoSuppressGCAnalysis nogc;
      63         283 :         if (!mayResolve(names, id, maybeObj))
      64         266 :             return false;
      65             :     }
      66             : 
      67        1171 :     return true;
      68             : }
      69             : 
      70             : } // namespace js
      71             : 
      72             : inline js::Shape*
      73      728433 : JSObject::maybeShape() const
      74             : {
      75      728433 :     if (!is<js::ShapedObject>())
      76         197 :         return nullptr;
      77             : 
      78      728236 :     return as<js::ShapedObject>().shape();
      79             : }
      80             : 
      81             : inline js::Shape*
      82       10037 : JSObject::ensureShape(JSContext* cx)
      83             : {
      84       10037 :     if (!js::MaybeConvertUnboxedObjectToNative(cx, this))
      85           0 :         return nullptr;
      86       10037 :     js::Shape* shape = maybeShape();
      87       10037 :     MOZ_ASSERT(shape);
      88       10037 :     return shape;
      89             : }
      90             : 
      91             : inline void
      92           0 : JSObject::finalize(js::FreeOp* fop)
      93             : {
      94           0 :     js::probes::FinalizeObject(this);
      95             : 
      96             : #ifdef DEBUG
      97           0 :     MOZ_ASSERT(isTenured());
      98           0 :     if (!IsBackgroundFinalized(asTenured().getAllocKind())) {
      99             :         /* Assert we're on the active thread. */
     100           0 :         MOZ_ASSERT(CurrentThreadCanAccessZone(zone()));
     101             :     }
     102             : #endif
     103             : 
     104           0 :     const js::Class* clasp = getClass();
     105           0 :     js::NativeObject* nobj = nullptr;
     106           0 :     if (clasp->isNative())
     107           0 :         nobj = &as<js::NativeObject>();
     108           0 :     if (clasp->hasFinalize())
     109           0 :         clasp->doFinalize(fop, this);
     110             : 
     111           0 :     if (!nobj)
     112           0 :         return;
     113             : 
     114           0 :     if (nobj->hasDynamicSlots())
     115           0 :         fop->free_(nobj->slots_);
     116             : 
     117           0 :     if (nobj->hasDynamicElements()) {
     118           0 :         js::ObjectElements* elements = nobj->getElementsHeader();
     119           0 :         if (elements->isCopyOnWrite()) {
     120           0 :             if (elements->ownerObject() == this) {
     121             :                 // Don't free the elements until object finalization finishes,
     122             :                 // so that other objects can access these elements while they
     123             :                 // are themselves finalized.
     124           0 :                 MOZ_ASSERT(elements->numShiftedElements() == 0);
     125           0 :                 fop->freeLater(elements);
     126             :             }
     127             :         } else {
     128           0 :             fop->free_(nobj->getUnshiftedElementsHeader());
     129             :         }
     130             :     }
     131             : 
     132           0 :     nobj->sweepDictionaryListPointer();
     133             : }
     134             : 
     135             : MOZ_ALWAYS_INLINE void
     136           0 : js::NativeObject::sweepDictionaryListPointer()
     137             : {
     138             :     // For dictionary objects (which must be native), it's possible that
     139             :     // unreachable shapes may be marked whose listp points into this object.  In
     140             :     // case this happens, null out the shape's pointer so that a moving GC will
     141             :     // not try to access the dead object.
     142           0 :     if (shape_->listp == &shape_)
     143           0 :         shape_->listp = nullptr;
     144           0 : }
     145             : 
     146             : /* static */ inline bool
     147       78619 : JSObject::setSingleton(JSContext* cx, js::HandleObject obj)
     148             : {
     149       78619 :     MOZ_ASSERT(!IsInsideNursery(obj));
     150             : 
     151       78619 :     js::ObjectGroup* group = js::ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
     152      157237 :                                                                  obj->taggedProto());
     153       78618 :     if (!group)
     154           0 :         return false;
     155             : 
     156       78618 :     obj->group_ = group;
     157       78619 :     return true;
     158             : }
     159             : 
     160             : /* static */ inline js::ObjectGroup*
     161        9199 : JSObject::getGroup(JSContext* cx, js::HandleObject obj)
     162             : {
     163        9199 :     MOZ_ASSERT(cx->compartment() == obj->compartment());
     164        9199 :     if (obj->hasLazyGroup()) {
     165        3862 :         if (cx->compartment() != obj->compartment())
     166           0 :             MOZ_CRASH();
     167        3862 :         return makeLazyGroup(cx, obj);
     168             :     }
     169        5337 :     return obj->group_;
     170             : }
     171             : 
     172             : inline void
     173       43274 : JSObject::setGroup(js::ObjectGroup* group)
     174             : {
     175       43274 :     MOZ_RELEASE_ASSERT(group);
     176       43274 :     MOZ_ASSERT(!isSingleton());
     177       43274 :     group_ = group;
     178       43274 : }
     179             : 
     180             : 
     181             : /*** Standard internal methods *******************************************************************/
     182             : 
     183             : inline bool
     184        2904 : js::GetPrototype(JSContext* cx, js::HandleObject obj, js::MutableHandleObject protop)
     185             : {
     186        2904 :     if (obj->hasDynamicPrototype()) {
     187         440 :         MOZ_ASSERT(obj->is<js::ProxyObject>());
     188         440 :         return js::Proxy::getPrototype(cx, obj, protop);
     189             :     }
     190             : 
     191        2464 :     protop.set(obj->taggedProto().toObjectOrNull());
     192        2464 :     return true;
     193             : }
     194             : 
     195             : inline bool
     196         724 : js::IsExtensible(JSContext* cx, HandleObject obj, bool* extensible)
     197             : {
     198         724 :     if (obj->is<ProxyObject>()) {
     199           0 :         MOZ_ASSERT(!cx->helperThread());
     200           0 :         return Proxy::isExtensible(cx, obj, extensible);
     201             :     }
     202             : 
     203         724 :     *extensible = obj->nonProxyIsExtensible();
     204         724 :     return true;
     205             : }
     206             : 
     207             : inline bool
     208           0 : js::HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* found)
     209             : {
     210           0 :     RootedId id(cx, NameToId(name));
     211           0 :     return HasProperty(cx, obj, id, found);
     212             : }
     213             : 
     214             : inline bool
     215        1888 : js::GetElement(JSContext* cx, HandleObject obj, HandleValue receiver, uint32_t index,
     216             :                MutableHandleValue vp)
     217             : {
     218        3776 :     RootedId id(cx);
     219        1888 :     if (!IndexToId(cx, index, &id))
     220           0 :         return false;
     221        1888 :     return GetProperty(cx, obj, receiver, id, vp);
     222             : }
     223             : 
     224             : inline bool
     225        1797 : js::GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
     226             :                MutableHandleValue vp)
     227             : {
     228        3594 :     RootedValue receiverValue(cx, ObjectValue(*receiver));
     229        3594 :     return GetElement(cx, obj, receiverValue, index, vp);
     230             : }
     231             : 
     232             : inline bool
     233        1504 : js::GetElementNoGC(JSContext* cx, JSObject* obj, const Value& receiver, uint32_t index, Value* vp)
     234             : {
     235        1504 :     if (obj->getOpsGetProperty())
     236          77 :         return false;
     237             : 
     238        1427 :     if (index > JSID_INT_MAX)
     239           0 :         return false;
     240        1427 :     return GetPropertyNoGC(cx, obj, receiver, INT_TO_JSID(index), vp);
     241             : }
     242             : 
     243             : inline bool
     244             : js::GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index, Value* vp)
     245             : {
     246             :     return GetElementNoGC(cx, obj, ObjectValue(*receiver), index, vp);
     247             : }
     248             : 
     249             : inline bool
     250         874 : js::DeleteProperty(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result)
     251             : {
     252         874 :     MarkTypePropertyNonData(cx, obj, id);
     253         874 :     if (DeletePropertyOp op = obj->getOpsDeleteProperty())
     254         414 :         return op(cx, obj, id, result);
     255         460 :     return NativeDeleteProperty(cx, obj.as<NativeObject>(), id, result);
     256             : }
     257             : 
     258             : inline bool
     259           0 : js::DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResult& result)
     260             : {
     261           0 :     RootedId id(cx);
     262           0 :     if (!IndexToId(cx, index, &id))
     263           0 :         return false;
     264           0 :     return DeleteProperty(cx, obj, id, result);
     265             : }
     266             : 
     267             : MOZ_ALWAYS_INLINE bool
     268         942 : js::MaybeHasInterestingSymbolProperty(JSContext* cx, JSObject* obj, Symbol* symbol,
     269             :                                       JSObject** holder)
     270             : {
     271         942 :     MOZ_ASSERT(symbol->isInterestingSymbol());
     272             : 
     273         942 :     jsid id = SYMBOL_TO_JSID(symbol);
     274         184 :     do {
     275        3342 :         if (obj->maybeHasInterestingSymbolProperty() ||
     276        2475 :             obj->hasDynamicPrototype() ||
     277        1349 :             MOZ_UNLIKELY(ClassMayResolveId(cx->names(), obj->getClass(), id, obj) ||
     278             :                          obj->getClass()->getGetProperty()))
     279             :         {
     280         867 :             if (holder)
     281         867 :                 *holder = obj;
     282         867 :             return true;
     283             :         }
     284         259 :         obj = obj->staticPrototype();
     285         259 :     } while (obj);
     286             : 
     287          75 :     return false;
     288             : }
     289             : 
     290             : MOZ_ALWAYS_INLINE bool
     291         942 : js::GetInterestingSymbolProperty(JSContext* cx, HandleObject obj, Symbol* sym, MutableHandleValue vp)
     292             : {
     293             :     JSObject* holder;
     294         942 :     if (!MaybeHasInterestingSymbolProperty(cx, obj, sym, &holder)) {
     295             : #ifdef DEBUG
     296         150 :         RootedValue receiver(cx, ObjectValue(*obj));
     297         150 :         RootedId id(cx, SYMBOL_TO_JSID(sym));
     298          75 :         if (!GetProperty(cx, obj, receiver, id, vp))
     299           0 :             return false;
     300          75 :         MOZ_ASSERT(vp.isUndefined());
     301             : #endif
     302          75 :         vp.setUndefined();
     303          75 :         return true;
     304             :     }
     305             : 
     306        1734 :     RootedObject holderRoot(cx, holder);
     307        1734 :     RootedValue receiver(cx, ObjectValue(*obj));
     308        1734 :     RootedId id(cx, SYMBOL_TO_JSID(sym));
     309         867 :     return GetProperty(cx, holderRoot, receiver, id, vp);
     310             : }
     311             : 
     312             : /* * */
     313             : 
     314             : inline bool
     315        7849 : JSObject::isQualifiedVarObj() const
     316             : {
     317        7849 :     if (is<js::DebugEnvironmentProxy>())
     318           0 :         return as<js::DebugEnvironmentProxy>().environment().isQualifiedVarObj();
     319        7849 :     bool rv = hasAllFlags(js::BaseShape::QUALIFIED_VAROBJ);
     320        7849 :     MOZ_ASSERT_IF(rv,
     321             :                   is<js::GlobalObject>() ||
     322             :                   is<js::CallObject>() ||
     323             :                   is<js::VarEnvironmentObject>() ||
     324             :                   is<js::ModuleEnvironmentObject>() ||
     325             :                   is<js::NonSyntacticVariablesObject>() ||
     326             :                   (is<js::WithEnvironmentObject>() &&
     327             :                    !as<js::WithEnvironmentObject>().isSyntactic()));
     328        7849 :     return rv;
     329             : }
     330             : 
     331             : inline bool
     332        2871 : JSObject::isUnqualifiedVarObj() const
     333             : {
     334        2871 :     if (is<js::DebugEnvironmentProxy>())
     335           0 :         return as<js::DebugEnvironmentProxy>().environment().isUnqualifiedVarObj();
     336        2871 :     return is<js::GlobalObject>() || is<js::NonSyntacticVariablesObject>();
     337             : }
     338             : 
     339             : namespace js {
     340             : 
     341             : inline bool
     342      265010 : ClassCanHaveFixedData(const Class* clasp)
     343             : {
     344             :     // Normally, the number of fixed slots given an object is the maximum
     345             :     // permitted for its size class. For array buffers and non-shared typed
     346             :     // arrays we only use enough to cover the class reserved slots, so that
     347             :     // the remaining space in the object's allocation is available for the
     348             :     // buffer's data.
     349      265010 :     return !clasp->isNative()
     350      255625 :         || clasp == &js::ArrayBufferObject::class_
     351      520637 :         || js::IsTypedArrayClass(clasp);
     352             : }
     353             : 
     354             : // This function is meant to be called from allocation fast paths.
     355             : //
     356             : // If we do have an allocation metadata builder, it can cause a GC, so the object
     357             : // must be rooted. The usual way to do this would be to make our callers pass a
     358             : // HandleObject, but that would require them to pay the cost of rooting the
     359             : // object unconditionally, even though collecting metadata is rare. Instead,
     360             : // SetNewObjectMetadata's contract is that the caller must use the pointer
     361             : // returned in place of the pointer passed. If a GC occurs, the returned pointer
     362             : // may be the passed pointer, relocated by GC. If no GC could occur, it's just
     363             : // passed through. We root nothing unless necessary.
     364             : template <typename T>
     365             : static MOZ_ALWAYS_INLINE MOZ_MUST_USE T*
     366      168426 : SetNewObjectMetadata(JSContext* cx, T* obj)
     367             : {
     368      168426 :     MOZ_ASSERT(!cx->compartment()->hasObjectPendingMetadata());
     369             : 
     370             :     // The metadata builder is invoked for each object created on the active
     371             :     // thread, except when analysis/compilation is active, to avoid recursion.
     372      168426 :     if (!cx->helperThread()) {
     373      160729 :         if (MOZ_UNLIKELY((size_t)cx->compartment()->hasAllocationMetadataBuilder()) &&
     374           0 :             !cx->zone()->suppressAllocationMetadataBuilder)
     375             :         {
     376             :             // Don't collect metadata on objects that represent metadata.
     377           0 :             AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
     378             : 
     379           0 :             Rooted<T*> rooted(cx, obj);
     380           0 :             cx->compartment()->setNewObjectMetadata(cx, rooted);
     381           0 :             return rooted;
     382             :         }
     383             :     }
     384             : 
     385      168426 :     return obj;
     386             : }
     387             : 
     388             : } // namespace js
     389             : 
     390             : inline void
     391      168669 : JSObject::setInitialSlotsMaybeNonNative(js::HeapSlot* slots)
     392             : {
     393      168669 :     static_cast<js::NativeObject*>(this)->slots_ = slots;
     394      168669 : }
     395             : 
     396             : inline void
     397      131360 : JSObject::setInitialElementsMaybeNonNative(js::HeapSlot* elements)
     398             : {
     399      131360 :     static_cast<js::NativeObject*>(this)->elements_ = elements;
     400      131360 : }
     401             : 
     402             : inline js::GlobalObject&
     403      123826 : JSObject::global() const
     404             : {
     405             :     /*
     406             :      * The global is read-barriered so that it is kept live by access through
     407             :      * the JSCompartment. When accessed through a JSObject, however, the global
     408             :      * will be already be kept live by the black JSObject's parent pointer, so
     409             :      * does not need to be read-barriered.
     410             :      */
     411      123826 :     return *compartment()->unsafeUnbarrieredMaybeGlobal();
     412             : }
     413             : 
     414             : inline js::GlobalObject*
     415          26 : JSObject::globalForTracing(JSTracer*) const
     416             : {
     417          26 :     return compartment()->unsafeUnbarrieredMaybeGlobal();
     418             : }
     419             : 
     420             : inline bool
     421          26 : JSObject::isOwnGlobal(JSTracer* trc) const
     422             : {
     423          26 :     return globalForTracing(trc) == this;
     424             : }
     425             : 
     426             : inline bool
     427      687546 : JSObject::hasAllFlags(js::BaseShape::Flag flags) const
     428             : {
     429      687546 :     MOZ_ASSERT(flags);
     430      687546 :     if (js::Shape* shape = maybeShape())
     431      687424 :         return shape->hasAllObjectFlags(flags);
     432         130 :     return false;
     433             : }
     434             : 
     435             : inline bool
     436      279942 : JSObject::nonProxyIsExtensible() const
     437             : {
     438      279942 :     MOZ_ASSERT(!uninlinedIsProxy());
     439             : 
     440             :     // [[Extensible]] for ordinary non-proxy objects is an object flag.
     441      279944 :     return !hasAllFlags(js::BaseShape::NOT_EXTENSIBLE);
     442             : }
     443             : 
     444             : inline bool
     445         973 : JSObject::isBoundFunction() const
     446             : {
     447         973 :     return is<JSFunction>() && as<JSFunction>().isBoundFunction();
     448             : }
     449             : 
     450             : inline bool
     451       13101 : JSObject::watched() const
     452             : {
     453       13101 :     return hasAllFlags(js::BaseShape::WATCHED);
     454             : }
     455             : 
     456             : inline bool
     457      217512 : JSObject::isDelegate() const
     458             : {
     459      217512 :     return hasAllFlags(js::BaseShape::DELEGATE);
     460             : }
     461             : 
     462             : inline bool
     463        2773 : JSObject::hasUncacheableProto() const
     464             : {
     465        2773 :     return hasAllFlags(js::BaseShape::UNCACHEABLE_PROTO);
     466             : }
     467             : 
     468             : inline bool
     469      115885 : JSObject::hadElementsAccess() const
     470             : {
     471      115885 :     return hasAllFlags(js::BaseShape::HAD_ELEMENTS_ACCESS);
     472             : }
     473             : 
     474             : inline bool
     475       18326 : JSObject::isIndexed() const
     476             : {
     477       18326 :     return hasAllFlags(js::BaseShape::INDEXED);
     478             : }
     479             : 
     480             : MOZ_ALWAYS_INLINE bool
     481        1126 : JSObject::maybeHasInterestingSymbolProperty() const
     482             : {
     483             :     const js::NativeObject* nobj;
     484        1126 :     if (isNative()) {
     485        1125 :         nobj = &as<js::NativeObject>();
     486           1 :     } else if (is<js::UnboxedPlainObject>()) {
     487           0 :         nobj = as<js::UnboxedPlainObject>().maybeExpando();
     488           0 :         if (!nobj)
     489           0 :             return false;
     490             :     } else {
     491           1 :         return true;
     492             :     }
     493             : 
     494        1125 :     return nobj->hasAllFlags(js::BaseShape::HAS_INTERESTING_SYMBOL);
     495             : }
     496             : 
     497             : inline bool
     498        6716 : JSObject::staticPrototypeIsImmutable() const
     499             : {
     500        6716 :     MOZ_ASSERT(hasStaticPrototype());
     501        6716 :     return hasAllFlags(js::BaseShape::IMMUTABLE_PROTOTYPE);
     502             : }
     503             : 
     504             : inline bool
     505        3859 : JSObject::isIteratedSingleton() const
     506             : {
     507        3859 :     return hasAllFlags(js::BaseShape::ITERATED_SINGLETON);
     508             : }
     509             : 
     510             : inline bool
     511        6419 : JSObject::isNewGroupUnknown() const
     512             : {
     513        6419 :     return hasAllFlags(js::BaseShape::NEW_GROUP_UNKNOWN);
     514             : }
     515             : 
     516             : inline bool
     517         528 : JSObject::wasNewScriptCleared() const
     518             : {
     519         528 :     return hasAllFlags(js::BaseShape::NEW_SCRIPT_CLEARED);
     520             : }
     521             : 
     522             : namespace js {
     523             : 
     524             : static MOZ_ALWAYS_INLINE bool
     525           8 : IsFunctionObject(const js::Value& v)
     526             : {
     527           8 :     return v.isObject() && v.toObject().is<JSFunction>();
     528             : }
     529             : 
     530             : static MOZ_ALWAYS_INLINE bool
     531       32515 : IsFunctionObject(const js::Value& v, JSFunction** fun)
     532             : {
     533       32515 :     if (v.isObject() && v.toObject().is<JSFunction>()) {
     534       29270 :         *fun = &v.toObject().as<JSFunction>();
     535       29270 :         return true;
     536             :     }
     537        3245 :     return false;
     538             : }
     539             : 
     540             : static MOZ_ALWAYS_INLINE bool
     541             : IsNativeFunction(const js::Value& v)
     542             : {
     543             :     JSFunction* fun;
     544             :     return IsFunctionObject(v, &fun) && fun->isNative();
     545             : }
     546             : 
     547             : static MOZ_ALWAYS_INLINE bool
     548             : IsNativeFunction(const js::Value& v, JSFunction** fun)
     549             : {
     550             :     return IsFunctionObject(v, fun) && (*fun)->isNative();
     551             : }
     552             : 
     553             : static MOZ_ALWAYS_INLINE bool
     554         437 : IsNativeFunction(const js::Value& v, JSNative native)
     555             : {
     556             :     JSFunction* fun;
     557         437 :     return IsFunctionObject(v, &fun) && fun->maybeNative() == native;
     558             : }
     559             : 
     560             : 
     561             : // Return whether looking up a method on 'obj' definitely resolves to the
     562             : // original specified native function. The method may conservatively return
     563             : // 'false' in the case of proxies or other non-native objects.
     564             : static MOZ_ALWAYS_INLINE bool
     565           1 : HasNativeMethodPure(JSObject* obj, PropertyName* name, JSNative native, JSContext* cx)
     566             : {
     567           1 :     Value v;
     568           1 :     if (!GetPropertyPure(cx, obj, NameToId(name), &v))
     569           0 :         return false;
     570             : 
     571           1 :     return IsNativeFunction(v, native);
     572             : }
     573             : 
     574             : // Return whether 'obj' definitely has no @@toPrimitive method.
     575             : static MOZ_ALWAYS_INLINE bool
     576           1 : HasNoToPrimitiveMethodPure(JSObject* obj, JSContext* cx)
     577             : {
     578           1 :     jsid id = SYMBOL_TO_JSID(cx->wellKnownSymbols().toPrimitive);
     579             :     JSObject* pobj;
     580           1 :     PropertyResult prop;
     581           1 :     if (!LookupPropertyPure(cx, obj, id, &pobj, &prop))
     582           0 :         return false;
     583             : 
     584           1 :     return !prop;
     585             : }
     586             : 
     587             : /* ES6 draft rev 28 (2014 Oct 14) 7.1.14 */
     588             : inline bool
     589        8227 : ToPropertyKey(JSContext* cx, HandleValue argument, MutableHandleId result)
     590             : {
     591             :     // Steps 1-2.
     592       16454 :     RootedValue key(cx, argument);
     593        8227 :     if (!ToPrimitive(cx, JSTYPE_STRING, &key))
     594           0 :         return false;
     595             : 
     596             :     // Steps 3-4.
     597        8227 :     return ValueToId<CanGC>(cx, key, result);
     598             : }
     599             : 
     600             : /*
     601             :  * Return true if this is a compiler-created internal function accessed by
     602             :  * its own object. Such a function object must not be accessible to script
     603             :  * or embedding code.
     604             :  */
     605             : inline bool
     606        2641 : IsInternalFunctionObject(JSObject& funobj)
     607             : {
     608        2641 :     JSFunction& fun = funobj.as<JSFunction>();
     609        2641 :     return fun.isInterpreted() && !fun.environment();
     610             : }
     611             : 
     612             : /*
     613             :  * Make an object with the specified prototype. If parent is null, it will
     614             :  * default to the prototype's global if the prototype is non-null.
     615             :  */
     616             : JSObject*
     617             : NewObjectWithGivenTaggedProto(JSContext* cx, const Class* clasp, Handle<TaggedProto> proto,
     618             :                               gc::AllocKind allocKind, NewObjectKind newKind,
     619             :                               uint32_t initialShapeFlags = 0);
     620             : 
     621             : inline JSObject*
     622       22544 : NewObjectWithGivenTaggedProto(JSContext* cx, const Class* clasp, Handle<TaggedProto> proto,
     623             :                               NewObjectKind newKind = GenericObject,
     624             :                               uint32_t initialShapeFlags = 0)
     625             : {
     626       22544 :     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
     627       22544 :     return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind, initialShapeFlags);
     628             : }
     629             : 
     630             : template <typename T>
     631             : inline T*
     632        5816 : NewObjectWithGivenTaggedProto(JSContext* cx, Handle<TaggedProto> proto,
     633             :                               NewObjectKind newKind = GenericObject,
     634             :                               uint32_t initialShapeFlags = 0)
     635             : {
     636             :     JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind,
     637        5816 :                                                   initialShapeFlags);
     638        5816 :     return obj ? &obj->as<T>() : nullptr;
     639             : }
     640             : 
     641             : template <typename T>
     642             : inline T*
     643        1634 : NewObjectWithNullTaggedProto(JSContext* cx, NewObjectKind newKind = GenericObject,
     644             :                              uint32_t initialShapeFlags = 0)
     645             : {
     646        3268 :     Rooted<TaggedProto> nullProto(cx, TaggedProto(nullptr));
     647        3268 :     return NewObjectWithGivenTaggedProto<T>(cx, nullProto, newKind, initialShapeFlags);
     648             : }
     649             : 
     650             : inline JSObject*
     651          62 : NewObjectWithGivenProto(JSContext* cx, const Class* clasp, HandleObject proto,
     652             :                         gc::AllocKind allocKind, NewObjectKind newKind)
     653             : {
     654          62 :     return NewObjectWithGivenTaggedProto(cx, clasp, AsTaggedProto(proto), allocKind,
     655          62 :                                          newKind);
     656             : }
     657             : 
     658             : inline JSObject*
     659       16727 : NewObjectWithGivenProto(JSContext* cx, const Class* clasp, HandleObject proto,
     660             :                         NewObjectKind newKind = GenericObject)
     661             : {
     662       16727 :     return NewObjectWithGivenTaggedProto(cx, clasp, AsTaggedProto(proto), newKind);
     663             : }
     664             : 
     665             : template <typename T>
     666             : inline T*
     667        4182 : NewObjectWithGivenProto(JSContext* cx, HandleObject proto,
     668             :                         NewObjectKind newKind = GenericObject)
     669             : {
     670        4182 :     return NewObjectWithGivenTaggedProto<T>(cx, AsTaggedProto(proto), newKind);
     671             : }
     672             : 
     673             : template <typename T>
     674             : inline T*
     675          66 : NewObjectWithGivenProto(JSContext* cx, HandleObject proto,
     676             :                         gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
     677             : {
     678          66 :     JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, AsTaggedProto(proto),
     679          66 :                                                   allocKind, newKind);
     680          66 :     return obj ? &obj->as<T>() : nullptr;
     681             : }
     682             : 
     683             : // Make an object with the prototype set according to the cached prototype or
     684             : // Object.prototype.
     685             : JSObject*
     686             : NewObjectWithClassProtoCommon(JSContext* cx, const Class* clasp, HandleObject proto,
     687             :                               gc::AllocKind allocKind, NewObjectKind newKind);
     688             : 
     689             : inline JSObject*
     690      117050 : NewObjectWithClassProto(JSContext* cx, const Class* clasp, HandleObject proto,
     691             :                         gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
     692             : {
     693      117050 :     return NewObjectWithClassProtoCommon(cx, clasp, proto, allocKind, newKind);
     694             : }
     695             : 
     696             : inline JSObject*
     697        2153 : NewObjectWithClassProto(JSContext* cx, const Class* clasp, HandleObject proto,
     698             :                         NewObjectKind newKind = GenericObject)
     699             : {
     700        2153 :     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
     701        2153 :     return NewObjectWithClassProto(cx, clasp, proto, allocKind, newKind);
     702             : }
     703             : 
     704             : template<class T>
     705             : inline T*
     706        2000 : NewObjectWithClassProto(JSContext* cx, HandleObject proto = nullptr,
     707             :                         NewObjectKind newKind = GenericObject)
     708             : {
     709        2000 :     JSObject* obj = NewObjectWithClassProto(cx, &T::class_, proto, newKind);
     710        2000 :     return obj ? &obj->as<T>() : nullptr;
     711             : }
     712             : 
     713             : template <class T>
     714             : inline T*
     715           0 : NewObjectWithClassProto(JSContext* cx, HandleObject proto, gc::AllocKind allocKind,
     716             :                         NewObjectKind newKind = GenericObject)
     717             : {
     718           0 :     JSObject* obj = NewObjectWithClassProto(cx, &T::class_, proto, allocKind, newKind);
     719           0 :     return obj ? &obj->as<T>() : nullptr;
     720             : }
     721             : 
     722             : /*
     723             :  * Create a native instance of the given class with parent and proto set
     724             :  * according to the context's active global.
     725             :  */
     726             : inline JSObject*
     727        7507 : NewBuiltinClassInstance(JSContext* cx, const Class* clasp, gc::AllocKind allocKind,
     728             :                         NewObjectKind newKind = GenericObject)
     729             : {
     730        7507 :     return NewObjectWithClassProto(cx, clasp, nullptr, allocKind, newKind);
     731             : }
     732             : 
     733             : inline JSObject*
     734        1020 : NewBuiltinClassInstance(JSContext* cx, const Class* clasp, NewObjectKind newKind = GenericObject)
     735             : {
     736        1020 :     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
     737        1020 :     return NewBuiltinClassInstance(cx, clasp, allocKind, newKind);
     738             : }
     739             : 
     740             : template<typename T>
     741             : inline T*
     742        1019 : NewBuiltinClassInstance(JSContext* cx, NewObjectKind newKind = GenericObject)
     743             : {
     744        1019 :     JSObject* obj = NewBuiltinClassInstance(cx, &T::class_, newKind);
     745        1019 :     return obj ? &obj->as<T>() : nullptr;
     746             : }
     747             : 
     748             : template<typename T>
     749             : inline T*
     750        6487 : NewBuiltinClassInstance(JSContext* cx, gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
     751             : {
     752        6487 :     JSObject* obj = NewBuiltinClassInstance(cx, &T::class_, allocKind, newKind);
     753        6487 :     return obj ? &obj->as<T>() : nullptr;
     754             : }
     755             : 
     756             : // Used to optimize calls to (new Object())
     757             : bool
     758             : NewObjectScriptedCall(JSContext* cx, MutableHandleObject obj);
     759             : 
     760             : JSObject*
     761             : NewObjectWithGroupCommon(JSContext* cx, HandleObjectGroup group,
     762             :                          gc::AllocKind allocKind, NewObjectKind newKind);
     763             : 
     764             : template <typename T>
     765             : inline T*
     766        5699 : NewObjectWithGroup(JSContext* cx, HandleObjectGroup group,
     767             :                    gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
     768             : {
     769        5699 :     JSObject* obj = NewObjectWithGroupCommon(cx, group, allocKind, newKind);
     770        5699 :     return obj ? &obj->as<T>() : nullptr;
     771             : }
     772             : 
     773             : template <typename T>
     774             : inline T*
     775         223 : NewObjectWithGroup(JSContext* cx, HandleObjectGroup group,
     776             :                    NewObjectKind newKind = GenericObject)
     777             : {
     778         223 :     gc::AllocKind allocKind = gc::GetGCObjectKind(group->clasp());
     779         223 :     return NewObjectWithGroup<T>(cx, group, allocKind, newKind);
     780             : }
     781             : 
     782             : /*
     783             :  * As for gc::GetGCObjectKind, where numElements is a guess at the final size of
     784             :  * the object, zero if the final size is unknown. This should only be used for
     785             :  * objects that do not require any fixed slots.
     786             :  */
     787             : static inline gc::AllocKind
     788         577 : GuessObjectGCKind(size_t numElements)
     789             : {
     790         577 :     if (numElements)
     791         446 :         return gc::GetGCObjectKind(numElements);
     792         131 :     return gc::AllocKind::OBJECT4;
     793             : }
     794             : 
     795             : static inline gc::AllocKind
     796        5815 : GuessArrayGCKind(size_t numElements)
     797             : {
     798        5815 :     if (numElements)
     799        4288 :         return gc::GetGCArrayKind(numElements);
     800        1527 :     return gc::AllocKind::OBJECT8;
     801             : }
     802             : 
     803             : // Returns ESClass::Other if the value isn't an object, or if the object
     804             : // isn't of one of the enumerated classes.  Otherwise returns the appropriate
     805             : // class.
     806             : inline bool
     807           2 : GetClassOfValue(JSContext* cx, HandleValue v, ESClass* cls)
     808             : {
     809           2 :     if (!v.isObject()) {
     810           2 :         *cls = ESClass::Other;
     811           2 :         return true;
     812             :     }
     813             : 
     814           0 :     RootedObject obj(cx, &v.toObject());
     815           0 :     return GetBuiltinClass(cx, obj, cls);
     816             : }
     817             : 
     818             : extern NativeObject*
     819             : InitClass(JSContext* cx, HandleObject obj, HandleObject parent_proto,
     820             :           const Class* clasp, JSNative constructor, unsigned nargs,
     821             :           const JSPropertySpec* ps, const JSFunctionSpec* fs,
     822             :           const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs,
     823             :           NativeObject** ctorp = nullptr,
     824             :           gc::AllocKind ctorKind = gc::AllocKind::FUNCTION);
     825             : 
     826             : MOZ_ALWAYS_INLINE const char*
     827           1 : GetObjectClassName(JSContext* cx, HandleObject obj)
     828             : {
     829           1 :     assertSameCompartment(cx, obj);
     830             : 
     831           1 :     if (obj->is<ProxyObject>())
     832           0 :         return Proxy::className(cx, obj);
     833             : 
     834           1 :     return obj->getClass()->name;
     835             : }
     836             : 
     837             : inline bool
     838        4993 : IsCallable(const Value& v)
     839             : {
     840        4993 :     return v.isObject() && v.toObject().isCallable();
     841             : }
     842             : 
     843             : // ES6 rev 24 (2014 April 27) 7.2.5 IsConstructor
     844             : inline bool
     845        4133 : IsConstructor(const Value& v)
     846             : {
     847        4133 :     return v.isObject() && v.toObject().isConstructor();
     848             : }
     849             : 
     850             : } /* namespace js */
     851             : 
     852             : MOZ_ALWAYS_INLINE bool
     853       26087 : JSObject::isCallable() const
     854             : {
     855       26087 :     if (is<JSFunction>())
     856       24758 :         return true;
     857        1329 :     return callHook() != nullptr;
     858             : }
     859             : 
     860             : MOZ_ALWAYS_INLINE bool
     861        4813 : JSObject::isConstructor() const
     862             : {
     863        4813 :     if (is<JSFunction>()) {
     864        3924 :         const JSFunction& fun = as<JSFunction>();
     865        3924 :         return fun.isConstructor();
     866             :     }
     867         889 :     return constructHook() != nullptr;
     868             : }
     869             : 
     870             : MOZ_ALWAYS_INLINE JSNative
     871        6371 : JSObject::callHook() const
     872             : {
     873        6371 :     const js::Class* clasp = getClass();
     874             : 
     875        6371 :     if (JSNative call = clasp->getCall())
     876         116 :         return call;
     877             : 
     878        6255 :     if (is<js::ProxyObject>()) {
     879        5546 :         const js::ProxyObject& p = as<js::ProxyObject>();
     880        5546 :         if (p.handler()->isCallable(const_cast<JSObject*>(this)))
     881        5312 :             return js::proxy_Call;
     882             :     }
     883         943 :     return nullptr;
     884             : }
     885             : 
     886             : MOZ_ALWAYS_INLINE JSNative
     887        1141 : JSObject::constructHook() const
     888             : {
     889        1141 :     const js::Class* clasp = getClass();
     890             : 
     891        1141 :     if (JSNative construct = clasp->getConstruct())
     892         226 :         return construct;
     893             : 
     894         915 :     if (is<js::ProxyObject>()) {
     895         900 :         const js::ProxyObject& p = as<js::ProxyObject>();
     896         900 :         if (p.handler()->isConstructor(const_cast<JSObject*>(this)))
     897         882 :             return js::proxy_Construct;
     898             :     }
     899          33 :     return nullptr;
     900             : }
     901             : 
     902             : #endif /* jsobjinlines_h */

Generated by: LCOV version 1.13