| Index: src/objects.h
|
| diff --git a/src/objects.h b/src/objects.h
|
| index 14f81f89a93534a9c33652ca2f8ae6d7d9b45928..9b33a4326c373b6508d2c097ed97e947b8a0776b 100644
|
| --- a/src/objects.h
|
| +++ b/src/objects.h
|
| @@ -178,23 +178,6 @@ enum TransitionFlag {
|
| };
|
|
|
|
|
| -// Indicates whether the transition is simple: the target map of the transition
|
| -// either extends the current map with a new property, or it modifies the
|
| -// property that was added last to the current map.
|
| -enum SimpleTransitionFlag {
|
| - SIMPLE_TRANSITION,
|
| - FULL_TRANSITION
|
| -};
|
| -
|
| -
|
| -// Indicates whether we are only interested in the descriptors of a particular
|
| -// map, or in all descriptors in the descriptor array.
|
| -enum DescriptorFlag {
|
| - ALL_DESCRIPTORS,
|
| - OWN_DESCRIPTORS
|
| -};
|
| -
|
| -
|
| // Instance size sentinel for objects of variable size.
|
| const int kVariableSizeSentinel = 0;
|
|
|
| @@ -1697,15 +1680,15 @@ class JSObject: public JSReceiver {
|
| String* name,
|
| PropertyAttributes* attributes);
|
| MUST_USE_RESULT MaybeObject* GetPropertyWithInterceptor(
|
| - Object* receiver,
|
| + JSReceiver* receiver,
|
| String* name,
|
| PropertyAttributes* attributes);
|
| MUST_USE_RESULT MaybeObject* GetPropertyPostInterceptor(
|
| - Object* receiver,
|
| + JSReceiver* receiver,
|
| String* name,
|
| PropertyAttributes* attributes);
|
| MUST_USE_RESULT MaybeObject* GetLocalPropertyPostInterceptor(
|
| - Object* receiver,
|
| + JSReceiver* receiver,
|
| String* name,
|
| PropertyAttributes* attributes);
|
|
|
| @@ -2385,6 +2368,23 @@ class FixedArray: public FixedArrayBase {
|
| }
|
| };
|
|
|
| + // WhitenessWitness is used to prove that a descriptor array is white
|
| + // (unmarked), so incremental write barriers can be skipped because the
|
| + // marking invariant cannot be broken and slots pointing into evacuation
|
| + // candidates will be discovered when the object is scanned. A witness is
|
| + // always stack-allocated right after creating an array. By allocating a
|
| + // witness, incremental marking is globally disabled. The witness is then
|
| + // passed along wherever needed to statically prove that the array is known to
|
| + // be white.
|
| + class WhitenessWitness {
|
| + public:
|
| + inline explicit WhitenessWitness(FixedArray* array);
|
| + inline ~WhitenessWitness();
|
| +
|
| + private:
|
| + IncrementalMarking* marking_;
|
| + };
|
| +
|
| protected:
|
| // Set operation on FixedArray without using write barriers. Can
|
| // only be used for storing old space objects or smis.
|
| @@ -2468,23 +2468,6 @@ class FixedDoubleArray: public FixedArrayBase {
|
| // [length() - kDescriptorSize]: last key
|
| class DescriptorArray: public FixedArray {
|
| public:
|
| - // WhitenessWitness is used to prove that a descriptor array is white
|
| - // (unmarked), so incremental write barriers can be skipped because the
|
| - // marking invariant cannot be broken and slots pointing into evacuation
|
| - // candidates will be discovered when the object is scanned. A witness is
|
| - // always stack-allocated right after creating an array. By allocating a
|
| - // witness, incremental marking is globally disabled. The witness is then
|
| - // passed along wherever needed to statically prove that the array is known to
|
| - // be white.
|
| - class WhitenessWitness {
|
| - public:
|
| - inline explicit WhitenessWitness(FixedArray* array);
|
| - inline ~WhitenessWitness();
|
| -
|
| - private:
|
| - IncrementalMarking* marking_;
|
| - };
|
| -
|
| // Returns true for both shared empty_descriptor_array and for smis, which the
|
| // map uses to encode additional bit fields when the descriptor array is not
|
| // yet used.
|
| @@ -2494,47 +2477,20 @@ class DescriptorArray: public FixedArray {
|
| int number_of_descriptors() {
|
| ASSERT(length() >= kFirstIndex || IsEmpty());
|
| int len = length();
|
| - return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value();
|
| - }
|
| -
|
| - int number_of_descriptors_storage() {
|
| - int len = length();
|
| - return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize;
|
| - }
|
| -
|
| - int NumberOfSlackDescriptors() {
|
| - return number_of_descriptors_storage() - number_of_descriptors();
|
| + return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kDescriptorSize;
|
| }
|
|
|
| - inline void SetNumberOfDescriptors(int number_of_descriptors);
|
| inline int number_of_entries() { return number_of_descriptors(); }
|
| + inline int NextEnumerationIndex() { return number_of_descriptors() + 1; }
|
|
|
| bool HasEnumCache() {
|
| return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi();
|
| }
|
|
|
| - void CopyEnumCacheFrom(DescriptorArray* array) {
|
| - set(kEnumCacheIndex, array->get(kEnumCacheIndex));
|
| - }
|
| -
|
| - FixedArray* GetEnumCache() {
|
| + Object* GetEnumCache() {
|
| ASSERT(HasEnumCache());
|
| FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
|
| - return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex));
|
| - }
|
| -
|
| - bool HasEnumIndicesCache() {
|
| - if (IsEmpty()) return false;
|
| - Object* object = get(kEnumCacheIndex);
|
| - if (object->IsSmi()) return false;
|
| - FixedArray* bridge = FixedArray::cast(object);
|
| - return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi();
|
| - }
|
| -
|
| - FixedArray* GetEnumIndicesCache() {
|
| - ASSERT(HasEnumIndicesCache());
|
| - FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
|
| - return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex));
|
| + return bridge->get(kEnumCacheBridgeCacheIndex);
|
| }
|
|
|
| Object** GetEnumCacheSlot() {
|
| @@ -2543,8 +2499,6 @@ class DescriptorArray: public FixedArray {
|
| kEnumCacheOffset);
|
| }
|
|
|
| - void ClearEnumCache();
|
| -
|
| // Initialize or change the enum cache,
|
| // using the supplied storage for the small "bridge".
|
| void SetEnumCache(FixedArray* bridge_storage,
|
| @@ -2572,14 +2526,13 @@ class DescriptorArray: public FixedArray {
|
| inline void Set(int descriptor_number,
|
| Descriptor* desc,
|
| const WhitenessWitness&);
|
| - inline void Set(int descriptor_number, Descriptor* desc);
|
| - inline void EraseDescriptor(Heap* heap, int descriptor_number);
|
|
|
| // Append automatically sets the enumeration index. This should only be used
|
| // to add descriptors in bulk at the end, followed by sorting the descriptor
|
| // array.
|
| - inline void Append(Descriptor* desc, const WhitenessWitness&);
|
| - inline void Append(Descriptor* desc);
|
| + inline void Append(Descriptor* desc,
|
| + const WhitenessWitness&,
|
| + int number_of_set_descriptors);
|
|
|
| // Transfer a complete descriptor from the src descriptor array to this
|
| // descriptor array.
|
| @@ -2588,22 +2541,23 @@ class DescriptorArray: public FixedArray {
|
| int src_index,
|
| const WhitenessWitness&);
|
|
|
| - MUST_USE_RESULT MaybeObject* CopyUpTo(int enumeration_index);
|
| -
|
| // Sort the instance descriptors by the hash codes of their keys.
|
| void Sort();
|
| + inline void SwapSortedKeys(int first, int second);
|
|
|
| // Search the instance descriptors for given name.
|
| - INLINE(int Search(String* name, int number_of_own_descriptors));
|
| + INLINE(int Search(String* name));
|
|
|
| // As the above, but uses DescriptorLookupCache and updates it when
|
| // necessary.
|
| - INLINE(int SearchWithCache(String* name, Map* map));
|
| + INLINE(int SearchWithCache(String* name));
|
| +
|
| + // Tells whether the name is present int the array.
|
| + bool Contains(String* name) { return kNotFound != Search(name); }
|
|
|
| // Allocates a DescriptorArray, but returns the singleton
|
| // empty descriptor array object if number_of_descriptors is 0.
|
| - MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors,
|
| - int slack = 0);
|
| + MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
|
|
|
| // Casting.
|
| static inline DescriptorArray* cast(Object* obj);
|
| @@ -2611,9 +2565,8 @@ class DescriptorArray: public FixedArray {
|
| // Constant for denoting key was not found.
|
| static const int kNotFound = -1;
|
|
|
| - static const int kDescriptorLengthIndex = 0;
|
| - static const int kEnumCacheIndex = 1;
|
| - static const int kFirstIndex = 2;
|
| + static const int kEnumCacheIndex = 0;
|
| + static const int kFirstIndex = 1;
|
|
|
| // The length of the "bridge" to the enum cache.
|
| static const int kEnumCacheBridgeLength = 2;
|
| @@ -2621,8 +2574,7 @@ class DescriptorArray: public FixedArray {
|
| static const int kEnumCacheBridgeIndicesCacheIndex = 1;
|
|
|
| // Layout description.
|
| - static const int kDescriptorLengthOffset = FixedArray::kHeaderSize;
|
| - static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize;
|
| + static const int kEnumCacheOffset = FixedArray::kHeaderSize;
|
| static const int kFirstOffset = kEnumCacheOffset + kPointerSize;
|
|
|
| // Layout description for the bridge array.
|
| @@ -2644,7 +2596,7 @@ class DescriptorArray: public FixedArray {
|
|
|
| #ifdef DEBUG
|
| // Is the descriptor array sorted and without duplicates?
|
| - bool IsSortedNoDuplicates(int valid_descriptors = -1);
|
| + bool IsSortedNoDuplicates();
|
|
|
| // Is the descriptor array consistent with the back pointers in targets?
|
| bool IsConsistentWithBackPointers(Map* current_map);
|
| @@ -2697,21 +2649,24 @@ class DescriptorArray: public FixedArray {
|
| kDescriptorValue;
|
| }
|
|
|
| + // Swap operation on FixedArray without using write barriers.
|
| + static inline void NoIncrementalWriteBarrierSwap(
|
| + FixedArray* array, int first, int second);
|
| +
|
| // Swap first and second descriptor.
|
| - inline void SwapSortedKeys(int first, int second);
|
| + inline void NoIncrementalWriteBarrierSwapDescriptors(
|
| + int first, int second);
|
|
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
|
| };
|
|
|
|
|
| -enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
|
| -
|
| -template<SearchMode search_mode, typename T>
|
| -inline int LinearSearch(T* array, String* name, int len, int valid_entries);
|
| +template<typename T>
|
| +inline int LinearSearch(T* array, String* name, int len);
|
|
|
|
|
| -template<SearchMode search_mode, typename T>
|
| -inline int Search(T* array, String* name, int valid_entries = 0);
|
| +template<typename T>
|
| +inline int Search(T* array, String* name);
|
|
|
|
|
| // HashTable is a subclass of FixedArray that implements a hash table
|
| @@ -2913,12 +2868,11 @@ class HashTable: public FixedArray {
|
| return (hash + GetProbeOffset(number)) & (size - 1);
|
| }
|
|
|
| - inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
|
| + static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
|
| return hash & (size - 1);
|
| }
|
|
|
| - inline static uint32_t NextProbe(
|
| - uint32_t last, uint32_t number, uint32_t size) {
|
| + static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
|
| return (last + number) & (size - 1);
|
| }
|
|
|
| @@ -3005,8 +2959,6 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
|
| private:
|
| MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
|
|
|
| - template <bool seq_ascii> friend class JsonParser;
|
| -
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
|
| };
|
|
|
| @@ -4720,7 +4672,6 @@ class Map: public HeapObject {
|
| class IsShared: public BitField<bool, 22, 1> {};
|
| class FunctionWithPrototype: public BitField<bool, 23, 1> {};
|
| class DictionaryMap: public BitField<bool, 24, 1> {};
|
| - class OwnsDescriptors: public BitField<bool, 25, 1> {};
|
|
|
| // Tells whether the object in the prototype property will be used
|
| // for instances created from this function. If the prototype
|
| @@ -4841,17 +4792,13 @@ class Map: public HeapObject {
|
| static bool IsValidElementsTransition(ElementsKind from_kind,
|
| ElementsKind to_kind);
|
|
|
| - bool StoresOwnDescriptors() { return HasTransitionArray(); }
|
| inline bool HasTransitionArray();
|
| inline bool HasElementsTransition();
|
| inline Map* elements_transition_map();
|
| MUST_USE_RESULT inline MaybeObject* set_elements_transition_map(
|
| Map* transitioned_map);
|
| - inline void SetTransition(int transition_index, Map* target);
|
| - inline Map* GetTransition(int transition_index);
|
| - MUST_USE_RESULT inline MaybeObject* AddTransition(String* key,
|
| - Map* target,
|
| - SimpleTransitionFlag flag);
|
| + inline void SetTransition(int index, Map* target);
|
| + MUST_USE_RESULT inline MaybeObject* AddTransition(String* key, Map* target);
|
| DECL_ACCESSORS(transitions, TransitionArray)
|
| inline void ClearTransitions(Heap* heap,
|
| WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
| @@ -4890,9 +4837,9 @@ class Map: public HeapObject {
|
|
|
| // [instance descriptors]: describes the object.
|
| inline DescriptorArray* instance_descriptors();
|
| - inline JSGlobalPropertyCell* descriptors_pointer();
|
| MUST_USE_RESULT inline MaybeObject* SetDescriptors(
|
| - DescriptorArray* descriptors);
|
| + DescriptorArray* descriptors,
|
| + WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
| static void SetDescriptors(Handle<Map> map,
|
| Handle<DescriptorArray> descriptors);
|
| MUST_USE_RESULT inline MaybeObject* InitializeDescriptors(
|
| @@ -4973,38 +4920,24 @@ class Map: public HeapObject {
|
| }
|
|
|
| void SetNumberOfOwnDescriptors(int number) {
|
| - ASSERT(number <= instance_descriptors()->number_of_descriptors());
|
| set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
|
| }
|
|
|
| - inline JSGlobalPropertyCell* RetrieveDescriptorsPointer();
|
| -
|
| int EnumLength() {
|
| return EnumLengthBits::decode(bit_field3());
|
| }
|
|
|
| - void SetEnumLength(int length) {
|
| - if (length != kInvalidEnumCache) {
|
| - ASSERT(length >= 0);
|
| - ASSERT(length == 0 || instance_descriptors()->HasEnumCache());
|
| - ASSERT(length <= NumberOfOwnDescriptors());
|
| - }
|
| - set_bit_field3(EnumLengthBits::update(bit_field3(), length));
|
| + void SetEnumLength(int index) {
|
| + set_bit_field3(EnumLengthBits::update(bit_field3(), index));
|
| }
|
|
|
| -
|
| - inline bool owns_descriptors();
|
| - inline void set_owns_descriptors(bool is_shared);
|
| -
|
| MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
|
| MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors();
|
| MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
|
| MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
|
| DescriptorArray* descriptors,
|
| String* name,
|
| - TransitionFlag flag,
|
| - int descriptor_index);
|
| - MUST_USE_RESULT MaybeObject* ShareDescriptor(Descriptor* descriptor);
|
| + TransitionFlag flag);
|
| MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor,
|
| TransitionFlag flag);
|
| MUST_USE_RESULT MaybeObject* CopyInsertDescriptor(Descriptor* descriptor,
|
| @@ -5033,8 +4966,7 @@ class Map: public HeapObject {
|
|
|
| // Returns the number of properties described in instance_descriptors
|
| // filtering out properties with the specified attributes.
|
| - int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS,
|
| - PropertyAttributes filter = NONE);
|
| + int NumberOfDescribedProperties(PropertyAttributes filter = NONE);
|
|
|
| // Casting.
|
| static inline Map* cast(Object* obj);
|
| @@ -5055,10 +4987,8 @@ class Map: public HeapObject {
|
|
|
| // Extend the descriptor array of the map with the list of descriptors.
|
| // In case of duplicates, the latest descriptor is used.
|
| - static void AppendCallbackDescriptors(Handle<Map> map,
|
| - Handle<Object> descriptors);
|
| -
|
| - static void EnsureDescriptorSlack(Handle<Map> map, int slack);
|
| + static void CopyAppendCallbackDescriptors(Handle<Map> map,
|
| + Handle<Object> descriptors);
|
|
|
| // Returns the found code or undefined if absent.
|
| Object* FindInCodeCache(String* name, Code::Flags flags);
|
| @@ -5140,7 +5070,7 @@ class Map: public HeapObject {
|
|
|
| static const int kMaxPreAllocatedPropertyFields = 255;
|
|
|
| - // Constant for denoting that the enum cache is not yet initialized.
|
| + // Constant for denoting that the Enum Cache field was not yet used.
|
| static const int kInvalidEnumCache = EnumLengthBits::kMax;
|
|
|
| // Layout description.
|
| @@ -7057,6 +6987,10 @@ class StringHasher {
|
| // index.
|
| bool is_array_index() { return is_array_index_; }
|
|
|
| + bool is_valid() { return is_valid_; }
|
| +
|
| + void invalidate() { is_valid_ = false; }
|
| +
|
| // Calculated hash value for a string consisting of 1 to
|
| // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
|
| // value is represented decimal value.
|
| @@ -7075,33 +7009,13 @@ class StringHasher {
|
|
|
| inline uint32_t GetHash();
|
|
|
| - // Reusable parts of the hashing algorithm.
|
| - INLINE(static uint32_t AddCharacterCore(uint32_t running_hash, uint32_t c));
|
| - INLINE(static uint32_t GetHashCore(uint32_t running_hash));
|
| -
|
| int length_;
|
| uint32_t raw_running_hash_;
|
| uint32_t array_index_;
|
| bool is_array_index_;
|
| bool is_first_char_;
|
| + bool is_valid_;
|
| friend class TwoCharHashTableKey;
|
| -
|
| - template <bool seq_ascii> friend class JsonParser;
|
| -};
|
| -
|
| -
|
| -class IncrementalAsciiStringHasher {
|
| - public:
|
| - explicit inline IncrementalAsciiStringHasher(uint32_t seed, char first_char);
|
| - inline void AddCharacter(uc32 c);
|
| - inline uint32_t GetHash();
|
| -
|
| - private:
|
| - int length_;
|
| - uint32_t raw_running_hash_;
|
| - uint32_t array_index_;
|
| - bool is_array_index_;
|
| - char first_char_;
|
| };
|
|
|
|
|
| @@ -7472,7 +7386,7 @@ class String: public HeapObject {
|
| #ifdef V8_HOST_CAN_READ_UNALIGNED
|
| ASSERT(kMaxAsciiCharCode == 0x7F);
|
| const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
|
| - while (chars + sizeof(uintptr_t) <= limit) {
|
| + while (chars <= limit - sizeof(uintptr_t)) {
|
| if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
|
| return false;
|
| }
|
|
|