name.h 7.45 KB
Newer Older
1 2 3 4 5 6 7 8
// 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_

#include "src/objects.h"
9
#include "src/objects/heap-object.h"
10 11 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 {

// 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.
19
class Name : public HeapObject {
20 21 22 23 24 25 26 27 28 29 30 31
 public:
  // Get and set the hash field of the name.
  inline uint32_t hash_field();
  inline void set_hash_field(uint32_t value);

  // Tells whether the hash code has been computed.
  inline bool HasHashCode();

  // Returns a hash value used for the property table
  inline uint32_t Hash();

  // Equality operations.
32
  inline bool Equals(Name other);
33 34
  inline static bool Equals(Isolate* isolate, Handle<Name> one,
                            Handle<Name> two);
35 36 37 38

  // Conversion.
  inline bool AsArrayIndex(uint32_t* index);

39 40 41 42 43 44 45
  // 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.
  inline bool IsInterestingSymbol() const;

46 47 48
  // If the name is private, it can only name own properties.
  inline bool IsPrivate();

49
  // If the name is a private name, it should behave like a private
50
  // symbol but also throw on property access miss.
51
  inline bool IsPrivateName();
52

53 54
  inline bool IsUniqueName() const;

55 56
  static inline bool ContainsCachedArrayIndex(uint32_t hash);

57 58
  // Return a string version of this name that is converted according to the
  // rules described in ES6 section 9.2.11.
59
  V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName(
60
      Isolate* isolate, Handle<Name> name);
61
  V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName(
62
      Isolate* isolate, Handle<Name> name, Handle<String> prefix);
63

64
  DECL_CAST(Name)
65

66
  DECL_PRINTER(Name)
67 68
  void NameShortPrint();
  int NameShortPrint(Vector<char> str);
69 70

  // Layout description.
71 72
  static const int kHashFieldOffset = HeapObject::kHeaderSize;
  static const int kHeaderSize = kHashFieldOffset + kInt32Size;
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

  // Mask constant for checking if a name has a computed hash code
  // and if it is a string that is an array index.  The least significant bit
  // indicates whether a hash code has been computed.  If the hash code has
  // been computed the 2nd bit tells whether the string can be used as an
  // array index.
  static const int kHashNotComputedMask = 1;
  static const int kIsNotArrayIndexMask = 1 << 1;
  static const int kNofHashBitFields = 2;

  // Shift constant retrieving hash code from hash field.
  static const int kHashShift = kNofHashBitFields;

  // Only these bits are relevant in the hash, since the top two are shifted
  // out.
  static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift;

  // 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;

  // 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 =
      kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;

  STATIC_ASSERT(kArrayIndexLengthBits > 0);
  STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));

  class ArrayIndexValueBits
      : public BitField<unsigned int, kNofHashBitFields, kArrayIndexValueBits> {
  };  // NOLINT
  class ArrayIndexLengthBits
      : public BitField<unsigned int, kNofHashBitFields + kArrayIndexValueBits,
                        kArrayIndexLengthBits> {};  // NOLINT

  // 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.
117 118
  static_assert(base::bits::IsPowerOfTwo(kMaxCachedArrayIndexLength + 1),
                "(kMaxCachedArrayIndexLength + 1) must be power of two");
119

120 121 122
  // When any of these bits is set then the hash field does not contain a cached
  // array index.
  static const unsigned int kDoesNotContainCachedArrayIndexMask =
123 124 125 126 127 128 129 130 131 132 133
      (~static_cast<unsigned>(kMaxCachedArrayIndexLength)
       << ArrayIndexLengthBits::kShift) |
      kIsNotArrayIndexMask;

  // Value of empty hash field indicating that the hash is not computed.
  static const int kEmptyHashField =
      kIsNotArrayIndexMask | kHashNotComputedMask;

 protected:
  static inline bool IsHashFieldComputed(uint32_t field);

134
  OBJECT_CONSTRUCTORS(Name, HeapObject);
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
};

// ES6 symbols.
class Symbol : public Name {
 public:
  // [name]: The print name of a symbol, or undefined if none.
  DECL_ACCESSORS(name, Object)

  DECL_INT_ACCESSORS(flags)

  // [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)

154 155 156 157 158 159
  // [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)

160 161 162 163
  // [is_public]: 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_public)

164
  // [is_private_name]: Whether this is a private name.  Private names
165 166 167 168
  // are the same as private symbols except they throw on missing
  // property access.
  //
  // This also sets the is_private bit.
169 170
  inline bool is_private_name() const;
  inline void set_is_private_name();
171

172
  DECL_CAST(Symbol)
173 174

  // Dispatched behavior.
175
  DECL_PRINTER(Symbol)
176
  DECL_VERIFIER(Symbol)
177 178

  // Layout description.
179 180 181 182 183 184 185 186
#define SYMBOL_FIELDS(V)      \
  V(kFlagsOffset, kInt32Size) \
  V(kNameOffset, kTaggedSize) \
  /* Header size. */          \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(Name::kHeaderSize, SYMBOL_FIELDS)
#undef SYMBOL_FIELDS
187 188 189 190 191 192 193

// Flags layout.
#define FLAGS_BIT_FIELDS(V, _)          \
  V(IsPrivateBit, bool, 1, _)           \
  V(IsWellKnownSymbolBit, bool, 1, _)   \
  V(IsPublicBit, bool, 1, _)            \
  V(IsInterestingSymbolBit, bool, 1, _) \
194
  V(IsPrivateNameBit, bool, 1, _)
195 196 197 198 199

  DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS

  typedef FixedBodyDescriptor<kNameOffset, kSize, kSize> BodyDescriptor;
200 201 202 203

  void SymbolShortPrint(std::ostream& os);

 private:
204
  const char* PrivateSymbolToName() const;
205

206
  // TODO(cbruni): remove once the new maptracer is in place.
207 208
  friend class Name;  // For PrivateSymbolToName.

209
  OBJECT_CONSTRUCTORS(Symbol, Name);
210 211 212 213 214 215 216 217
};

}  // namespace internal
}  // namespace v8

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

#endif  // V8_OBJECTS_NAME_H_