name.h 9.62 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_NAME_H_
#define V8_OBJECTS_NAME_H_

8
#include "src/base/bit-field.h"
9
#include "src/objects/objects.h"
10
#include "src/objects/primitive-heap-object.h"
11
#include "torque-generated/bit-fields.h"
12 13 14 15 16 17 18

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

19 20
#include "torque-generated/src/objects/name-tq.inc"

21 22
class SharedStringAccessGuardIfNeeded;

23 24
// The Name abstract class captures anything that can be used as a property
// name, i.e., strings and symbols.  All names store a hash value.
25
class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> {
26 27
 public:
  // Tells whether the hash code has been computed.
28 29
  // Note: Use TryGetHash() whenever you want to use the hash, instead of a
  // combination of HashHashCode() and hash() for thread-safety.
30
  inline bool HasHashCode() const;
31 32 33
  // Tells whether the name contains a forwarding index pointing to a row
  // in the string forwarding table.
  inline bool HasForwardingIndex() const;
34

35 36
  // Returns a hash value used for the property table. Ensures that the hash
  // value is computed.
37 38 39
  //
  // The overload without SharedStringAccessGuardIfNeeded can only be called on
  // the main thread.
40
  inline uint32_t EnsureHash();
41
  inline uint32_t EnsureHash(const SharedStringAccessGuardIfNeeded&);
42

43 44 45 46
  inline uint32_t raw_hash_field() const {
    return RELAXED_READ_UINT32_FIELD(*this, kRawHashFieldOffset);
  }

47 48 49 50
  inline uint32_t raw_hash_field(AcquireLoadTag) const {
    return ACQUIRE_READ_UINT32_FIELD(*this, kRawHashFieldOffset);
  }

51 52 53 54
  inline void set_raw_hash_field(uint32_t hash) {
    RELAXED_WRITE_UINT32_FIELD(*this, kRawHashFieldOffset, hash);
  }

55 56 57 58 59 60 61
  inline void set_raw_hash_field(uint32_t hash, ReleaseStoreTag) {
    RELEASE_WRITE_UINT32_FIELD(*this, kRawHashFieldOffset, hash);
  }

  // Sets the hash field only if it is empty. Otherwise does nothing.
  inline void set_raw_hash_field_if_empty(uint32_t hash);

62 63 64 65
  // Returns a hash value used for the property table (same as Hash()), assumes
  // the hash is already computed.
  inline uint32_t hash() const;

66 67 68 69
  // Returns true if the hash has been computed, and sets the computed hash
  // as out-parameter.
  inline bool TryGetHash(uint32_t* hash) const;

70
  // Equality operations.
71
  inline bool Equals(Name other);
72 73
  inline static bool Equals(Isolate* isolate, Handle<Name> one,
                            Handle<Name> two);
74 75 76

  // Conversion.
  inline bool AsArrayIndex(uint32_t* index);
77
  inline bool AsIntegerIndex(size_t* index);
78

79 80 81 82 83
  // An "interesting symbol" is a well-known symbol, like @@toStringTag,
  // that's often looked up on random objects but is usually not present.
  // We optimize this by setting a flag on the object's map when such
  // symbol properties are added, so we can optimize lookups on objects
  // that don't have the flag.
84
  DECL_GETTER(IsInterestingSymbol, bool)
85

86
  // If the name is private, it can only name own properties.
87
  DECL_GETTER(IsPrivate, bool)
88

89
  // If the name is a private name, it should behave like a private
90
  // symbol but also throw on property access miss.
91
  DECL_GETTER(IsPrivateName, bool)
92

93 94
  // If the name is a private brand, it should behave like a private name
  // symbol but is filtered out when generating list of private fields.
95
  DECL_GETTER(IsPrivateBrand, bool)
96

97
  DECL_GETTER(IsUniqueName, bool)
98

99 100
  static inline bool ContainsCachedArrayIndex(uint32_t hash);

101 102
  // Return a string version of this name that is converted according to the
  // rules described in ES6 section 9.2.11.
103
  V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName(
104
      Isolate* isolate, Handle<Name> name);
105
  V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName(
106
      Isolate* isolate, Handle<Name> name, Handle<String> prefix);
107

108
  DECL_PRINTER(Name)
109
  void NameShortPrint();
110
  int NameShortPrint(base::Vector<char> str);
111

Patrick Thier's avatar
Patrick Thier committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
  // Mask constant for checking if a name has a computed hash code and the type
  // of information stored in the hash field. The least significant bit
  // indicates whether the value can be used as a hash (i.e. different values
  // imply different strings).
  enum class HashFieldType : uint32_t {
    kHash = 0b10,
    kIntegerIndex = 0b00,
    kForwardingIndex = 0b01,
    kEmpty = 0b11
  };

  using HashFieldTypeBits = base::BitField<HashFieldType, 0, 2>;
  using HashBits =
      HashFieldTypeBits::Next<uint32_t, kBitsPerInt - HashFieldTypeBits::kSize>;

  static constexpr int kHashNotComputedMask = 1;
  // Value of empty hash field indicating that the hash is not computed.
  static constexpr int kEmptyHashField =
      HashFieldTypeBits::encode(HashFieldType::kEmpty);

  // Empty hash and forwarding indices can not be used as hash.
133 134
  static_assert((kEmptyHashField & kHashNotComputedMask) != 0);
  static_assert((HashFieldTypeBits::encode(HashFieldType::kForwardingIndex) &
Patrick Thier's avatar
Patrick Thier committed
135
                 kHashNotComputedMask) != 0);
136 137 138 139 140 141 142

  // Array index strings this short can keep their index in the hash field.
  static const int kMaxCachedArrayIndexLength = 7;

  // Maximum number of characters to consider when trying to convert a string
  // value into an array index.
  static const int kMaxArrayIndexSize = 10;
143 144 145 146 147 148 149
  // Maximum number of characters in a string that can possibly be an
  // "integer index" in the spec sense, i.e. a canonical representation of a
  // number in the range up to MAX_SAFE_INTEGER. We parse these into a size_t,
  // so the size of that type also factors in as a limit: 10 characters per
  // 32 bits of size_t width.
  static const int kMaxIntegerIndexSize =
      std::min(16, int{10 * (sizeof(size_t) / 4)});
150 151 152 153 154 155

  // For strings which are array indexes the hash value has the string length
  // mixed into the hash, mainly to avoid a hash value of zero which would be
  // the case for the string '0'. 24 bits are used for the array index value.
  static const int kArrayIndexValueBits = 24;
  static const int kArrayIndexLengthBits =
Patrick Thier's avatar
Patrick Thier committed
156
      kBitsPerInt - kArrayIndexValueBits - HashFieldTypeBits::kSize;
157

158 159
  static_assert(kArrayIndexLengthBits > 0);
  static_assert(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
160

161
  using ArrayIndexValueBits =
Patrick Thier's avatar
Patrick Thier committed
162
      HashFieldTypeBits::Next<unsigned int, kArrayIndexValueBits>;
163
  using ArrayIndexLengthBits =
Patrick Thier's avatar
Patrick Thier committed
164
      ArrayIndexValueBits::Next<unsigned int, kArrayIndexLengthBits>;
165 166 167 168

  // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
  // could use a mask to test if the length of string is less than or equal to
  // kMaxCachedArrayIndexLength.
169 170
  static_assert(base::bits::IsPowerOfTwo(kMaxCachedArrayIndexLength + 1),
                "(kMaxCachedArrayIndexLength + 1) must be power of two");
171

172 173
  // When any of these bits is set then the hash field does not contain a cached
  // array index.
174
  static_assert(HashFieldTypeBits::encode(HashFieldType::kIntegerIndex) == 0);
175
  static const unsigned int kDoesNotContainCachedArrayIndexMask =
176 177
      (~static_cast<unsigned>(kMaxCachedArrayIndexLength)
       << ArrayIndexLengthBits::kShift) |
Patrick Thier's avatar
Patrick Thier committed
178
      HashFieldTypeBits::kMask;
179

180
  static inline bool IsHashFieldComputed(uint32_t raw_hash_field);
Patrick Thier's avatar
Patrick Thier committed
181 182 183 184 185 186
  static inline bool IsHash(uint32_t raw_hash_field);
  static inline bool IsIntegerIndex(uint32_t raw_hash_field);
  static inline bool IsForwardingIndex(uint32_t raw_hash_field);

  static inline uint32_t CreateHashFieldValue(uint32_t hash,
                                              HashFieldType type);
187

188
  TQ_OBJECT_CONSTRUCTORS(Name)
189 190 191
};

// ES6 symbols.
192
class Symbol : public TorqueGeneratedSymbol<Symbol, Name> {
193
 public:
194 195
  DEFINE_TORQUE_GENERATED_SYMBOL_FLAGS()

196 197 198 199 200 201 202 203 204
  // [is_private]: Whether this is a private symbol.  Private symbols can only
  // be used to designate own properties of objects.
  DECL_BOOLEAN_ACCESSORS(is_private)

  // [is_well_known_symbol]: Whether this is a spec-defined well-known symbol,
  // or not. Well-known symbols do not throw when an access check fails during
  // a load.
  DECL_BOOLEAN_ACCESSORS(is_well_known_symbol)

205 206 207 208 209 210
  // [is_interesting_symbol]: Whether this is an "interesting symbol", which
  // is a well-known symbol like @@toStringTag that's often looked up on
  // random objects but is usually not present. See Name::IsInterestingSymbol()
  // for a detailed description.
  DECL_BOOLEAN_ACCESSORS(is_interesting_symbol)

211 212 213 214
  // [is_in_public_symbol_table]: Whether this is a symbol created by
  // Symbol.for. Calling Symbol.keyFor on such a symbol simply needs
  // to return the attached name.
  DECL_BOOLEAN_ACCESSORS(is_in_public_symbol_table)
215

216
  // [is_private_name]: Whether this is a private name.  Private names
217 218 219 220
  // are the same as private symbols except they throw on missing
  // property access.
  //
  // This also sets the is_private bit.
221 222
  inline bool is_private_name() const;
  inline void set_is_private_name();
223

224 225 226 227 228 229 230 231
  // [is_private_name]: Whether this is a brand symbol.  Brand symbols are
  // private name symbols that are used for validating access to
  // private methods and storing information about the private methods.
  //
  // This also sets the is_private bit.
  inline bool is_private_brand() const;
  inline void set_is_private_brand();

232
  // Dispatched behavior.
233
  DECL_PRINTER(Symbol)
234
  DECL_VERIFIER(Symbol)
235

236
  using BodyDescriptor = FixedBodyDescriptor<kDescriptionOffset, kSize, kSize>;
237 238 239 240

  void SymbolShortPrint(std::ostream& os);

 private:
241
  const char* PrivateSymbolToName() const;
242

243
  // TODO(cbruni): remove once the new maptracer is in place.
244 245
  friend class Name;  // For PrivateSymbolToName.

246
  TQ_OBJECT_CONSTRUCTORS(Symbol)
247 248 249 250 251 252 253 254
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_NAME_H_