js/src/vm/Shape-inl.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial