js/src/vm/Shape-inl.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     7 #ifndef vm_Shape_inl_h
     8 #define vm_Shape_inl_h
    10 #include "vm/Shape.h"
    12 #include "mozilla/TypeTraits.h"
    14 #include "jsobj.h"
    16 #include "vm/Interpreter.h"
    17 #include "vm/ScopeObject.h"
    18 #include "vm/TypedArrayObject.h"
    20 #include "jsatominlines.h"
    21 #include "jscntxtinlines.h"
    22 #include "jsgcinlines.h"
    24 namespace js {
    26 inline
    27 StackBaseShape::StackBaseShape(ThreadSafeContext *cx, const Class *clasp,
    28                                JSObject *parent, JSObject *metadata, uint32_t objectFlags)
    29   : flags(objectFlags),
    30     clasp(clasp),
    31     parent(parent),
    32     metadata(metadata),
    33     rawGetter(nullptr),
    34     rawSetter(nullptr),
    35     compartment(cx->compartment_)
    36 {}
    38 inline bool
    39 Shape::get(JSContext* cx, HandleObject receiver, JSObject* obj, JSObject *pobj,
    40            MutableHandleValue vp)
    41 {
    42     JS_ASSERT(!hasDefaultGetter());
    44     if (hasGetterValue()) {
    45         Value fval = getterValue();
    46         return InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
    47     }
    49     RootedId id(cx, propid());
    50     return CallJSPropertyOp(cx, getterOp(), receiver, id, vp);
    51 }
    53 inline Shape *
    54 Shape::search(ExclusiveContext *cx, jsid id)
    55 {
    56     Shape **_;
    57     return search(cx, this, id, &_);
    58 }
    60 inline Shape *
    61 Shape::searchThreadLocal(ThreadSafeContext *cx, Shape *start, jsid id,
    62                          Shape ***pspp, bool adding)
    63 {
    64     /*
    65      * Note that adding is a best-effort attempt to claim an entry in a shape
    66      * table. In the sequential case, this can be done either when the object
    67      * is in dictionary mode, or when it has been hashified.
    68      *
    69      * In parallel, an object that is in dictionary mode may be thread
    70      * local. That is, it was converted to a dictionary in the current thread,
    71      * with all its shapes cloned into the current thread, and its shape table
    72      * allocated thread locally. In that case, we may add to the
    73      * table. Otherwise it is not allowed.
    74      */
    75     JS_ASSERT_IF(adding, cx->isThreadLocal(start) && start->inDictionary());
    77     if (start->inDictionary()) {
    78         *pspp = start->table().search(id, adding);
    79         return SHAPE_FETCH(*pspp);
    80     }
    82     *pspp = nullptr;
    84     return searchNoHashify(start, id);
    85 }
    87 inline bool
    88 Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict,
    89            MutableHandleValue vp)
    90 {
    91     JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
    93     if (attrs & JSPROP_SETTER) {
    94         Value fval = setterValue();
    95         return InvokeGetterOrSetter(cx, receiver, fval, 1, vp.address(), vp);
    96     }
    98     if (attrs & JSPROP_GETTER)
    99         return js_ReportGetterOnlyAssignment(cx, strict);
   101     RootedId id(cx, propid());
   103     /*
   104      * |with (it) color='red';| ends up here.
   105      * Avoid exposing the With object to native setters.
   106      */
   107     if (obj->is<DynamicWithObject>()) {
   108         RootedObject nobj(cx, &obj->as<DynamicWithObject>().object());
   109         return CallJSPropertyOpSetter(cx, setterOp(), nobj, id, strict, vp);
   110     }
   112     return CallJSPropertyOpSetter(cx, setterOp(), obj, id, strict, vp);
   113 }
   115 /* static */ inline Shape *
   116 Shape::search(ExclusiveContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
   117 {
   118     if (start->inDictionary()) {
   119         *pspp = start->table().search(id, adding);
   120         return SHAPE_FETCH(*pspp);
   121     }
   123     *pspp = nullptr;
   125     if (start->hasTable()) {
   126         Shape **spp = start->table().search(id, adding);
   127         return SHAPE_FETCH(spp);
   128     }
   130     if (start->numLinearSearches() == LINEAR_SEARCHES_MAX) {
   131         if (start->isBigEnoughForAShapeTable()) {
   132             if (Shape::hashify(cx, start)) {
   133                 Shape **spp = start->table().search(id, adding);
   134                 return SHAPE_FETCH(spp);
   135             } else {
   136                 cx->recoverFromOutOfMemory();
   137             }
   138         }
   139         /*
   140          * No table built -- there weren't enough entries, or OOM occurred.
   141          * Don't increment numLinearSearches, to keep hasTable() false.
   142          */
   143         JS_ASSERT(!start->hasTable());
   144     } else {
   145         start->incrementNumLinearSearches();
   146     }
   148     for (Shape *shape = start; shape; shape = shape->parent) {
   149         if (shape->propidRef() == id)
   150             return shape;
   151     }
   153     return nullptr;
   154 }
   156 template<class ObjectSubclass>
   157 /* static */ inline bool
   158 EmptyShape::ensureInitialCustomShape(ExclusiveContext *cx, Handle<ObjectSubclass*> obj)
   159 {
   160     static_assert(mozilla::IsBaseOf<JSObject, ObjectSubclass>::value,
   161                   "ObjectSubclass must be a subclass of JSObject");
   163     // If the provided object has a non-empty shape, it was given the cached
   164     // initial shape when created: nothing to do.
   165     if (!obj->nativeEmpty())
   166         return true;
   168     // If no initial shape was assigned, do so.
   169     RootedShape shape(cx, ObjectSubclass::assignInitialShape(cx, obj));
   170     if (!shape)
   171         return false;
   172     MOZ_ASSERT(!obj->nativeEmpty());
   174     // If the object is a standard prototype -- |RegExp.prototype|,
   175     // |String.prototype|, |RangeError.prototype|, &c. -- GlobalObject.cpp's
   176     // |CreateBlankProto| marked it as a delegate.  These are the only objects
   177     // of this class that won't use the standard prototype, and there's no
   178     // reason to pollute the initial shape cache with entries for them.
   179     if (obj->isDelegate())
   180         return true;
   182     // Cache the initial shape for non-prototype objects, however, so that
   183     // future instances will begin life with that shape.
   184     RootedObject proto(cx, obj->getProto());
   185     EmptyShape::insertInitialShape(cx, shape, proto);
   186     return true;
   187 }
   189 inline
   190 AutoRooterGetterSetter::Inner::Inner(ThreadSafeContext *cx, uint8_t attrs,
   191                                      PropertyOp *pgetter_, StrictPropertyOp *psetter_)
   192   : CustomAutoRooter(cx), attrs(attrs),
   193     pgetter(pgetter_), psetter(psetter_)
   194 {
   195     JS_ASSERT_IF(attrs & JSPROP_GETTER, !IsPoisonedPtr(*pgetter));
   196     JS_ASSERT_IF(attrs & JSPROP_SETTER, !IsPoisonedPtr(*psetter));
   197 }
   199 inline
   200 AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
   201                                                PropertyOp *pgetter, StrictPropertyOp *psetter
   202                                                MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   203 {
   204     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
   205         inner.construct(cx, attrs, pgetter, psetter);
   206     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   207 }
   209 static inline uint8_t
   210 GetShapeAttributes(JSObject *obj, Shape *shape)
   211 {
   212     JS_ASSERT(obj->isNative());
   214     if (IsImplicitDenseOrTypedArrayElement(shape)) {
   215         if (obj->is<TypedArrayObject>())
   216             return JSPROP_ENUMERATE | JSPROP_PERMANENT;
   217         return JSPROP_ENUMERATE;
   218     }
   220     return shape->attributes();
   221 }
   223 } /* namespace js */
   225 #endif /* vm_Shape_inl_h */

mercurial