tor-browser

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

SymbolType.h (5579B)


      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_SymbolType_h
      8 #define vm_SymbolType_h
      9 
     10 #include <stdio.h>
     11 
     12 #include "gc/Barrier.h"
     13 #include "gc/Tracer.h"
     14 #include "js/AllocPolicy.h"
     15 #include "js/GCHashTable.h"
     16 #include "js/RootingAPI.h"
     17 #include "js/shadow/Symbol.h"  // JS::shadow::Symbol
     18 #include "js/Symbol.h"
     19 #include "js/TypeDecls.h"
     20 #include "vm/StringType.h"
     21 
     22 namespace js {
     23 class JS_PUBLIC_API GenericPrinter;
     24 class JSONPrinter;
     25 } /* namespace js */
     26 
     27 namespace JS {
     28 
     29 class Symbol
     30    : public js::gc::CellWithTenuredGCPointer<js::gc::TenuredCell, JSAtom> {
     31  friend class js::gc::CellAllocator;
     32 
     33 public:
     34  // User description of symbol, stored in the cell header.
     35  JSAtom* description() const { return headerPtr(); }
     36 
     37 private:
     38  SymbolCode code_;
     39 
     40  // Each Symbol gets its own hash code so that we don't have to use
     41  // addresses as hash codes (a security hazard).
     42  js::HashNumber hash_;
     43 
     44  Symbol(SymbolCode code, js::HashNumber hash, Handle<JSAtom*> desc)
     45      : CellWithTenuredGCPointer(desc), code_(code), hash_(hash) {}
     46 
     47  Symbol(const Symbol&) = delete;
     48  void operator=(const Symbol&) = delete;
     49 
     50  static Symbol* newInternal(JSContext* cx, SymbolCode code,
     51                             js::HashNumber hash, Handle<JSAtom*> description);
     52 
     53  static void staticAsserts() {
     54    static_assert(uint32_t(SymbolCode::WellKnownAPILimit) ==
     55                      JS::shadow::Symbol::WellKnownAPILimit,
     56                  "JS::shadow::Symbol::WellKnownAPILimit must match "
     57                  "SymbolCode::WellKnownAPILimit");
     58    static_assert(
     59        offsetof(Symbol, code_) == offsetof(JS::shadow::Symbol, code_),
     60        "JS::shadow::Symbol::code_ offset must match SymbolCode::code_");
     61  }
     62 
     63 public:
     64  static Symbol* new_(JSContext* cx, SymbolCode code,
     65                      js::HandleString description);
     66  static Symbol* newWellKnown(JSContext* cx, SymbolCode code,
     67                              Handle<js::PropertyName*> description);
     68  static Symbol* for_(JSContext* cx, js::HandleString description);
     69 
     70  SymbolCode code() const { return code_; }
     71  js::HashNumber hash() const { return hash_; }
     72 
     73  bool isWellKnownSymbol() const {
     74    return uint32_t(code_) < WellKnownSymbolLimit;
     75  }
     76 
     77  // An "interesting symbol" is a well-known symbol, like @@toStringTag,
     78  // that's often looked up on random objects but is usually not present. We
     79  // optimize this by setting a flag on the object's BaseShape when such
     80  // symbol properties are added, so we can optimize lookups on objects that
     81  // don't have the BaseShape flag.
     82  bool isInterestingSymbol() const {
     83    return code_ == SymbolCode::toStringTag ||
     84           code_ == SymbolCode::toPrimitive ||
     85           code_ == SymbolCode::isConcatSpreadable;
     86  }
     87 
     88  // Symbol created for the #PrivateName syntax.
     89  bool isPrivateName() const { return code_ == SymbolCode::PrivateNameSymbol; }
     90 
     91  static const JS::TraceKind TraceKind = JS::TraceKind::Symbol;
     92 
     93  void traceChildren(JSTracer* trc);
     94 
     95  // Override base class implementation to tell GC about well-known symbols.
     96  bool isPermanentAndMayBeShared() const { return isWellKnownSymbol(); }
     97 
     98  size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     99    return mallocSizeOf(this);
    100  }
    101 
    102 #if defined(DEBUG) || defined(JS_JITSPEW)
    103  void dump() const;  // Debugger-friendly stderr dump.
    104  void dump(js::GenericPrinter& out) const;
    105  void dump(js::JSONPrinter& json) const;
    106 
    107  void dumpFields(js::JSONPrinter& json) const;
    108  void dumpStringContent(js::GenericPrinter& out) const;
    109  void dumpPropertyName(js::GenericPrinter& out) const;
    110 #endif
    111 
    112  static constexpr size_t offsetOfHash() { return offsetof(Symbol, hash_); }
    113  static constexpr size_t offsetOfCode() { return offsetof(Symbol, code_); }
    114 };
    115 
    116 } /* namespace JS */
    117 
    118 namespace js {
    119 
    120 /* Hash policy used by the SymbolRegistry. */
    121 struct HashSymbolsByDescription {
    122  using Key = JS::Symbol*;
    123  using Lookup = JSAtom*;
    124 
    125  static HashNumber hash(Lookup l) { return HashNumber(l->hash()); }
    126  static bool match(Key sym, Lookup l) { return sym->description() == l; }
    127 };
    128 
    129 /*
    130 * [SMDOC] Symbol.for() registry (ES6 GlobalSymbolRegistry)
    131 *
    132 * The runtime-wide symbol registry, used to implement Symbol.for().
    133 *
    134 * ES6 draft rev 25 (2014 May 22) calls this the GlobalSymbolRegistry List. In
    135 * our implementation, it is not global. There is one per JSRuntime. The
    136 * symbols in the symbol registry, like all symbols, are allocated in the atoms
    137 * compartment and can be directly referenced from any compartment. They are
    138 * never shared across runtimes.
    139 *
    140 * The memory management strategy here is modeled after js::AtomSet. It's like
    141 * a WeakSet. The registry itself does not keep any symbols alive; when a
    142 * symbol in the registry is collected, the registry entry is removed. No GC
    143 * nondeterminism is exposed to scripts, because there is no API for
    144 * enumerating the symbol registry, querying its size, etc.
    145 */
    146 class SymbolRegistry
    147    : public GCHashSet<WeakHeapPtr<JS::Symbol*>, HashSymbolsByDescription,
    148                       SystemAllocPolicy> {
    149 public:
    150  SymbolRegistry() = default;
    151 };
    152 
    153 // ES6 rev 27 (2014 Aug 24) 19.4.3.3
    154 bool SymbolDescriptiveString(JSContext* cx, JS::Symbol* sym,
    155                             JS::MutableHandleValue result);
    156 
    157 } /* namespace js */
    158 
    159 #endif /* vm_SymbolType_h */