| Index: src/objects.h
|
| diff --git a/src/objects.h b/src/objects.h
|
| index c56e8782627e86a86f41cc48a2d0117fc870223c..b314195f2d09751d8d12b86cf3be2368f8b8d847 100644
|
| --- a/src/objects.h
|
| +++ b/src/objects.h
|
| @@ -95,15 +95,25 @@
|
| // - ExternalIntArray
|
| // - ExternalUnsignedIntArray
|
| // - ExternalFloatArray
|
| -// - String
|
| -// - SeqString
|
| -// - SeqOneByteString
|
| -// - SeqTwoByteString
|
| -// - SlicedString
|
| -// - ConsString
|
| -// - ExternalString
|
| -// - ExternalAsciiString
|
| -// - ExternalTwoByteString
|
| +// - Name
|
| +// - String
|
| +// - SeqString
|
| +// - SeqOneByteString
|
| +// - SeqTwoByteString
|
| +// - SlicedString
|
| +// - ConsString
|
| +// - ExternalString
|
| +// - ExternalAsciiString
|
| +// - ExternalTwoByteString
|
| +// - InternalizedString
|
| +// - SeqInternalizedString
|
| +// - SeqOneByteInternalizedString
|
| +// - SeqTwoByteInternalizedString
|
| +// - ConsInternalizedString
|
| +// - ExternalInternalizedString
|
| +// - ExternalAsciiInternalizedString
|
| +// - ExternalTwoByteInternalizedString
|
| +// - Symbol
|
| // - HeapNumber
|
| // - Code
|
| // - Map
|
| @@ -266,6 +276,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
|
| V(SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE) \
|
| V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE) \
|
| \
|
| + V(SYMBOL_TYPE) \
|
| V(MAP_TYPE) \
|
| V(CODE_TYPE) \
|
| V(ODDBALL_TYPE) \
|
| @@ -571,8 +582,11 @@ enum InstanceType {
|
| SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE =
|
| SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE | kInternalizedTag,
|
|
|
| + // Non-string names
|
| + SYMBOL_TYPE = kNotStringTag, // LAST_NAME_TYPE, FIRST_NONSTRING_TYPE
|
| +
|
| // Objects allocated in their own spaces (never in new space).
|
| - MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
|
| + MAP_TYPE,
|
| CODE_TYPE,
|
| ODDBALL_TYPE,
|
| JS_GLOBAL_PROPERTY_CELL_TYPE,
|
| @@ -652,7 +666,8 @@ enum InstanceType {
|
| FIRST_TYPE = 0x0,
|
| LAST_TYPE = JS_FUNCTION_TYPE,
|
| INVALID_TYPE = FIRST_TYPE - 1,
|
| - FIRST_NONSTRING_TYPE = MAP_TYPE,
|
| + LAST_NAME_TYPE = SYMBOL_TYPE,
|
| + FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
|
| // Boundaries for testing for an external array.
|
| FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
|
| LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
|
| @@ -828,6 +843,7 @@ class MaybeObject BASE_EMBEDDED {
|
|
|
| #define HEAP_OBJECT_TYPE_LIST(V) \
|
| V(HeapNumber) \
|
| + V(Name) \
|
| V(String) \
|
| V(SeqString) \
|
| V(ExternalString) \
|
| @@ -838,6 +854,7 @@ class MaybeObject BASE_EMBEDDED {
|
| V(SeqTwoByteString) \
|
| V(SeqOneByteString) \
|
| V(InternalizedString) \
|
| + V(Symbol) \
|
| \
|
| V(ExternalArray) \
|
| V(ExternalByteArray) \
|
| @@ -7124,6 +7141,102 @@ class StringShape BASE_EMBEDDED {
|
| };
|
|
|
|
|
| +// 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();
|
| +
|
| + // Casting.
|
| + static inline Name* cast(Object* obj);
|
| +
|
| + // Layout description.
|
| + static const int kHashFieldOffset = HeapObject::kHeaderSize;
|
| + static const int kSize = kHashFieldOffset + 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;
|
| +
|
| + // 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_CHECK((kArrayIndexLengthBits > 0));
|
| +
|
| + static const int kArrayIndexHashLengthShift =
|
| + kArrayIndexValueBits + kNofHashBitFields;
|
| +
|
| + static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
|
| +
|
| + static const int kArrayIndexValueMask =
|
| + ((1 << kArrayIndexValueBits) - 1) << kHashShift;
|
| +
|
| + // 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_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
|
| +
|
| + static const int kContainsCachedArrayIndexMask =
|
| + (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
|
| + 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:
|
| + // Casting.
|
| + static inline Symbol* cast(Object* obj);
|
| +
|
| + // Dispatched behavior.
|
| + DECLARE_PRINTER(Symbol)
|
| + DECLARE_VERIFIER(Symbol)
|
| +
|
| + // Layout description.
|
| + static const int kSize = Name::kSize;
|
| +
|
| + private:
|
| + DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
|
| +};
|
| +
|
| +
|
| // The String abstract class captures JavaScript string values:
|
| //
|
| // Ecma-262:
|
| @@ -7132,7 +7245,7 @@ class StringShape BASE_EMBEDDED {
|
| // ordered sequence of zero or more 16-bit unsigned integer values.
|
| //
|
| // All string values have a length field.
|
| -class String: public HeapObject {
|
| +class String: public Name {
|
| public:
|
| enum Encoding { ONE_BYTE_ENCODING, TWO_BYTE_ENCODING };
|
|
|
| @@ -7185,10 +7298,6 @@ class String: public HeapObject {
|
| inline int length();
|
| inline void set_length(int value);
|
|
|
| - // Get and set the hash field of the string.
|
| - inline uint32_t hash_field();
|
| - inline void set_hash_field(uint32_t value);
|
| -
|
| // Returns whether this string has only ASCII chars, i.e. all of them can
|
| // be ASCII encoded. This might be the case even if the string is
|
| // two-byte. Such strings may appear when the embedder prefers
|
| @@ -7289,12 +7398,6 @@ class String: public HeapObject {
|
| SmartArrayPointer<uc16> ToWideCString(
|
| RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
|
|
|
| - // Tells whether the hash code has been computed.
|
| - inline bool HasHashCode();
|
| -
|
| - // Returns a hash value used for the property table
|
| - inline uint32_t Hash();
|
| -
|
| bool ComputeArrayIndex(uint32_t* index);
|
|
|
| // Externalization.
|
| @@ -7327,70 +7430,19 @@ class String: public HeapObject {
|
| inline bool IsFlat();
|
|
|
| // Layout description.
|
| - static const int kLengthOffset = HeapObject::kHeaderSize;
|
| - static const int kHashFieldOffset = kLengthOffset + kPointerSize;
|
| - static const int kSize = kHashFieldOffset + kPointerSize;
|
| + static const int kLengthOffset = Name::kSize;
|
| + static const int kSize = kLengthOffset + kPointerSize;
|
|
|
| // Maximum number of characters to consider when trying to convert a string
|
| // value into an array index.
|
| static const int kMaxArrayIndexSize = 10;
|
| + STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
|
|
|
| // Max char codes.
|
| static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
|
| static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
|
| static const int kMaxUtf16CodeUnit = 0xffff;
|
|
|
| - // Mask constant for checking if a string has a computed hash code
|
| - // and if it 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;
|
| -
|
| - // 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_CHECK((kArrayIndexLengthBits > 0));
|
| - STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
|
| -
|
| - static const int kArrayIndexHashLengthShift =
|
| - kArrayIndexValueBits + kNofHashBitFields;
|
| -
|
| - static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
|
| -
|
| - static const int kArrayIndexValueMask =
|
| - ((1 << kArrayIndexValueBits) - 1) << kHashShift;
|
| -
|
| - // 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_CHECK(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
|
| -
|
| - static const int kContainsCachedArrayIndexMask =
|
| - (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
|
| - kIsNotArrayIndexMask;
|
| -
|
| - // Value of empty hash field indicating that the hash is not computed.
|
| - static const int kEmptyHashField =
|
| - kIsNotArrayIndexMask | kHashNotComputedMask;
|
| -
|
| // Value of hash field containing computed hash equal to zero.
|
| static const int kEmptyStringHash = kIsNotArrayIndexMask;
|
|
|
| @@ -7472,13 +7524,13 @@ class String: public HeapObject {
|
| unsigned length);
|
|
|
| private:
|
| + friend class Name;
|
| +
|
| // Try to flatten the top level ConsString that is hiding behind this
|
| // string. This is a no-op unless the string is a ConsString. Flatten
|
| // mutates the ConsString and might return a failure.
|
| MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
|
|
|
| - static inline bool IsHashFieldComputed(uint32_t field);
|
| -
|
| // Slow case of String::Equals. This implementation works on any strings
|
| // but it is most efficient on strings that are almost flat.
|
| bool SlowEquals(String* other);
|
|
|