Shape-inl.h (3337B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 vm_Shape_inl_h 8 #define vm_Shape_inl_h 9 10 #include "vm/Shape.h" 11 12 #include "vm/JSObject.h" 13 #include "vm/PropertyResult.h" 14 #include "vm/TypedArrayObject.h" 15 16 #include "gc/GCContext-inl.h" 17 #include "gc/Marking-inl.h" 18 #include "vm/PropMap-inl.h" 19 20 namespace js { 21 22 template <class ObjectSubclass> 23 /* static */ inline bool SharedShape::ensureInitialCustomShape( 24 JSContext* cx, Handle<ObjectSubclass*> obj) { 25 static_assert(std::is_base_of_v<JSObject, ObjectSubclass>, 26 "ObjectSubclass must be a subclass of JSObject"); 27 28 // If the provided object has a non-empty shape, it was given the cached 29 // initial shape when created: nothing to do. 30 if (!obj->empty()) { 31 return true; 32 } 33 34 // Ensure the initial shape isn't collected under assignInitialShape, to 35 // simplify insertInitialShape. 36 Rooted<Shape*> emptyShape(cx, obj->shape()); 37 38 // If no initial shape was assigned, do so. 39 Rooted<SharedShape*> shape(cx, ObjectSubclass::assignInitialShape(cx, obj)); 40 if (!shape) { 41 return false; 42 } 43 MOZ_ASSERT(!obj->empty()); 44 45 // Cache the initial shape, so that future instances will begin life with that 46 // shape. 47 SharedShape::insertInitialShape(cx, shape); 48 return true; 49 } 50 51 MOZ_ALWAYS_INLINE PropMap* NativeShape::lookup(JSContext* cx, PropertyKey key, 52 uint32_t* index) { 53 uint32_t len = propMapLength(); 54 return len > 0 ? propMap_->lookup(cx, len, key, index) : nullptr; 55 } 56 57 MOZ_ALWAYS_INLINE PropMap* NativeShape::lookupPure(PropertyKey key, 58 uint32_t* index) { 59 uint32_t len = propMapLength(); 60 return len > 0 ? propMap_->lookupPure(len, key, index) : nullptr; 61 } 62 63 inline void Shape::purgeCache(JS::GCContext* gcx) { 64 if (cache_.isShapeSetForAdd()) { 65 gcx->delete_(this, cache_.toShapeSetForAdd(), MemoryUse::ShapeSetForAdd); 66 } 67 cache_.setNone(); 68 } 69 70 inline void Shape::finalize(JS::GCContext* gcx) { 71 if (!cache_.isNone()) { 72 purgeCache(gcx); 73 } 74 if (isWasmGC()) { 75 asWasmGC().finalize(gcx); 76 } 77 } 78 79 inline void WasmGCShape::init() { recGroup_->AddRef(); } 80 81 inline void WasmGCShape::finalize(JS::GCContext* gcx) { recGroup_->Release(); } 82 83 inline SharedPropMap* SharedShape::propMapMaybeForwarded() const { 84 MOZ_ASSERT(isShared()); 85 PropMap* propMap = propMap_; 86 return propMap ? MaybeForwarded(propMap)->asShared() : nullptr; 87 } 88 89 static inline JS::PropertyAttributes GetPropertyAttributes( 90 JSObject* obj, PropertyResult prop) { 91 MOZ_ASSERT(obj->is<NativeObject>()); 92 93 if (prop.isDenseElement()) { 94 return obj->as<NativeObject>().getElementsHeader()->elementAttributes(); 95 } 96 if (prop.isTypedArrayElement()) { 97 if (obj->is<ImmutableTypedArrayObject>()) { 98 return {JS::PropertyAttribute::Enumerable}; 99 } 100 return {JS::PropertyAttribute::Configurable, 101 JS::PropertyAttribute::Enumerable, JS::PropertyAttribute::Writable}; 102 } 103 104 return prop.propertyInfo().propAttributes(); 105 } 106 107 } /* namespace js */ 108 109 #endif /* vm_Shape_inl_h */