tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GetterSetter.h (4226B)


      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_GetterSetter_h
      8 #define vm_GetterSetter_h
      9 
     10 #include "gc/Barrier.h"  // js::GCPtr<JSObject*>
     11 #include "gc/Cell.h"     // js::gc::CellWithGCPointer
     12 
     13 #include "js/TypeDecls.h"  // JS::HandleObject
     14 #include "js/UbiNode.h"    // JS::ubi::TracerConcrete
     15 
     16 namespace js {
     17 
     18 // [SMDOC] Getter/Setter Properties
     19 //
     20 // Getter/setter properties are implemented similar to plain data properties:
     21 // the shape contains the property's key, attributes, and slot number, but the
     22 // getter/setter objects are stored separately as part of the object.
     23 //
     24 // To simplify the NativeObject and Shape code, a single slot is allocated for
     25 // each getter/setter property (again similar to data properties). This slot
     26 // contains a PrivateGCThingValue pointing to a js::GetterSetter instance.
     27 //
     28 // js::GetterSetter
     29 // ================
     30 // js::GetterSetter is an immutable type that stores the getter/setter objects.
     31 // Because accessor properties can be defined with only a getter or only a
     32 // setter, a GetterSetter's objects can be nullptr.
     33 //
     34 // JIT/IC Guards
     35 // =============
     36 // An object's shape implies a certain property is an accessor, but it does not
     37 // imply the identity of the getter/setter objects. This means IC code needs to
     38 // guard on the slot value (the GetterSetter*) when optimizing a call to a
     39 // particular getter/setter function.
     40 //
     41 // See EmitGuardGetterSetterSlot in jit/CacheIR.cpp.
     42 //
     43 // HadGetterSetterChange Optimization
     44 // ==================================
     45 // Some getters and setters defined on the prototype chain are very hot, for
     46 // example the 'length' getter for typed arrays. To avoid the GetterSetter guard
     47 // in the common case, when attaching a stub for a known 'holder' object, we
     48 // use the HadGetterSetterChange object flag.
     49 //
     50 // When this flag is not set, the object is guaranteed to get a different shape
     51 // when an accessor property is either deleted or mutated, because when that
     52 // happens the HadGetterSetterChange will be set which triggers a shape change.
     53 //
     54 // This means CacheIR does not have to guard on the GetterSetter slot for
     55 // accessors on the prototype chain until the first time an accessor property is
     56 // mutated or deleted.
     57 class GetterSetter : public gc::CellWithGCPointer<JSObject> {
     58  friend class gc::CellAllocator;
     59 
     60 public:
     61  // Getter object, stored in the cell header.
     62  JSObject* getter() const { return headerPtr(); }
     63 
     64  GCPtr<JSObject*> setter_;
     65 
     66 #ifndef JS_64BIT
     67  // Ensure size >= MinCellSize on 32-bit platforms.
     68  uint64_t padding_ = 0;
     69 #endif
     70 
     71 private:
     72  GetterSetter(HandleObject getter, HandleObject setter);
     73 
     74 public:
     75  static GetterSetter* create(JSContext* cx, Handle<NativeObject*> owner,
     76                              HandleObject getter, HandleObject setter);
     77 
     78  JSObject* setter() const { return setter_; }
     79 
     80  static const JS::TraceKind TraceKind = JS::TraceKind::GetterSetter;
     81 
     82  js::gc::AllocKind getAllocKind() const {
     83    return js::gc::AllocKind::GETTER_SETTER;
     84  }
     85  void fixupAfterMovingGC() {}
     86 
     87  static constexpr size_t offsetOfGetter() { return offsetOfHeaderPtr(); }
     88  static constexpr size_t offsetOfSetter() {
     89    return offsetof(GetterSetter, setter_);
     90  }
     91 
     92  void traceChildren(JSTracer* trc);
     93 };
     94 
     95 }  // namespace js
     96 
     97 // JS::ubi::Nodes can point to GetterSetters; they're js::gc::Cell instances
     98 // with no associated compartment.
     99 namespace JS {
    100 namespace ubi {
    101 
    102 template <>
    103 class Concrete<js::GetterSetter> : TracerConcrete<js::GetterSetter> {
    104 protected:
    105  explicit Concrete(js::GetterSetter* ptr)
    106      : TracerConcrete<js::GetterSetter>(ptr) {}
    107 
    108 public:
    109  static void construct(void* storage, js::GetterSetter* ptr) {
    110    new (storage) Concrete(ptr);
    111  }
    112 
    113  Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
    114 
    115  const char16_t* typeName() const override { return concreteTypeName; }
    116  static const char16_t concreteTypeName[];
    117 };
    118 
    119 }  // namespace ubi
    120 }  // namespace JS
    121 
    122 #endif  // vm_GetterSetter_h