// 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"
|
|
// 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.
|
class Name : public HeapObject {
|
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.
|
inline bool Equals(Name* other);
|
inline static bool Equals(Isolate* isolate, Handle<Name> one,
|
Handle<Name> two);
|
|
// Conversion.
|
inline bool AsArrayIndex(uint32_t* index);
|
|
// 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;
|
|
// If the name is private, it can only name own properties.
|
inline bool IsPrivate();
|
|
// If the name is a private field, it should behave like a private
|
// symbol but also throw on property access miss.
|
inline bool IsPrivateField();
|
|
inline bool IsUniqueName() const;
|
|
static inline bool ContainsCachedArrayIndex(uint32_t hash);
|
|
// Return a string version of this name that is converted according to the
|
// rules described in ES6 section 9.2.11.
|
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName(
|
Isolate* isolate, Handle<Name> name);
|
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName(
|
Isolate* isolate, Handle<Name> name, Handle<String> prefix);
|
|
DECL_CAST(Name)
|
|
DECL_PRINTER(Name)
|
void NameShortPrint();
|
int NameShortPrint(Vector<char> str);
|
|
// Layout description.
|
static const int kHashFieldSlot = HeapObject::kHeaderSize;
|
#if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
|
static const int kHashFieldOffset = kHashFieldSlot;
|
#else
|
static const int kHashFieldOffset = kHashFieldSlot + kInt32Size;
|
#endif
|
static const int kSize = kHashFieldSlot + kPointerSize;
|
|
// 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.
|
static_assert(base::bits::IsPowerOfTwo(kMaxCachedArrayIndexLength + 1),
|
"(kMaxCachedArrayIndexLength + 1) must be power of two");
|
|
// When any of these bits is set then the hash field does not contain a cached
|
// array index.
|
static const unsigned int kDoesNotContainCachedArrayIndexMask =
|
(~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);
|
|
private:
|
DISALLOW_IMPLICIT_CONSTRUCTORS(Name);
|
};
|
|
// 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)
|
|
// [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)
|
|
// [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)
|
|
// [is_private_field]: Whether this is a private field. Private fields
|
// are the same as private symbols except they throw on missing
|
// property access.
|
//
|
// This also sets the is_private bit.
|
inline bool is_private_field() const;
|
inline void set_is_private_field();
|
|
DECL_CAST(Symbol)
|
|
// Dispatched behavior.
|
DECL_PRINTER(Symbol)
|
DECL_VERIFIER(Symbol)
|
|
// Layout description.
|
static const int kNameOffset = Name::kSize;
|
static const int kFlagsOffset = kNameOffset + kPointerSize;
|
static const int kSize = kFlagsOffset + kPointerSize;
|
|
// Flags layout.
|
static const int kPrivateBit = 0;
|
static const int kWellKnownSymbolBit = 1;
|
static const int kPublicBit = 2;
|
static const int kInterestingSymbolBit = 3;
|
static const int kPrivateFieldBit = 4;
|
|
typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor;
|
// No weak fields.
|
typedef BodyDescriptor BodyDescriptorWeak;
|
|
void SymbolShortPrint(std::ostream& os);
|
|
private:
|
const char* PrivateSymbolToName() const;
|
|
// TODO(cbruni): remove once the new maptracer is in place.
|
friend class Name; // For PrivateSymbolToName.
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
|
};
|
|
} // namespace internal
|
} // namespace v8
|
|
#include "src/objects/object-macros-undef.h"
|
|
#endif // V8_OBJECTS_NAME_H_
|